diff --git a/docs-cn/14-reference/02-rest-api/02-rest-api.mdx b/docs-cn/14-reference/02-rest-api/02-rest-api.mdx
index c7680ab3e9..43099319b9 100644
--- a/docs-cn/14-reference/02-rest-api/02-rest-api.mdx
+++ b/docs-cn/14-reference/02-rest-api/02-rest-api.mdx
@@ -16,7 +16,7 @@ RESTful 接口不依赖于任何 TDengine 的库,因此客户端不需要安
在已经安装 TDengine 服务器端的情况下,可以按照如下方式进行验证。
-下面以 Ubuntu 环境中使用 curl 工具(确认已经安装)来验证 RESTful 接口的正常。
+下面以 Ubuntu 环境中使用 curl 工具(确认已经安装)来验证 RESTful 接口的正常,验证前请确认 taosAdapter 服务已开启,在 Linux 系统上此服务默认由 systemd 管理,使用命令 `systemctl start taosadapter` 启动。
下面示例是列出所有的数据库,请把 h1.taosdata.com 和 6041(缺省值)替换为实际运行的 TDengine 服务 FQDN 和端口号:
diff --git a/docs-cn/14-reference/03-connector/cpp.mdx b/docs-cn/14-reference/03-connector/cpp.mdx
index aba1d6c717..aecf9fde12 100644
--- a/docs-cn/14-reference/03-connector/cpp.mdx
+++ b/docs-cn/14-reference/03-connector/cpp.mdx
@@ -114,7 +114,6 @@ TDengine 客户端驱动的安装请参考 [安装指南](/reference/connector#
订阅和消费
```c
-{{#include examples/c/subscribe.c}}
```
diff --git a/docs-cn/20-third-party/01-grafana.mdx b/docs-cn/20-third-party/01-grafana.mdx
index 328bd6bb45..40b5c0ff4f 100644
--- a/docs-cn/20-third-party/01-grafana.mdx
+++ b/docs-cn/20-third-party/01-grafana.mdx
@@ -18,21 +18,22 @@ TDengine 能够与开源数据可视化系统 [Grafana](https://www.grafana.com/
## 配置 Grafana
-TDengine 的 Grafana 插件托管在 GitHub,可从 下载,当前最新版本为 3.1.4。
-
-推荐使用 [`grafana-cli` 命令行工具](https://grafana.com/docs/grafana/latest/administration/cli/) 进行插件安装。
+使用 [`grafana-cli` 命令行工具](https://grafana.com/docs/grafana/latest/administration/cli/) 进行插件[安装](https://grafana.com/grafana/plugins/tdengine-datasource/?tab=installation)。
```bash
-sudo -u grafana grafana-cli \
- --pluginUrl https://github.com/taosdata/grafanaplugin/releases/download/v3.1.7/tdengine-datasource-3.1.7.zip \
- plugins install tdengine-datasource
+grafana-cli plugins install tdengine-datasource
+# with sudo
+sudo -u grafana grafana-cli plugins install tdengine-datasource
```
-或者下载到本地并解压到 Grafana 插件目录。
+或者从 [GitHub](https://github.com/taosdata/grafanaplugin/releases/tag/latest) 或 [Grafana](https://grafana.com/grafana/plugins/tdengine-datasource/?tab=installation) 下载 .zip 文件到本地并解压到 Grafana 插件目录。命令行下载示例如下:
```bash
-GF_VERSION=3.1.7
+GF_VERSION=3.2.2
+# from GitHub
wget https://github.com/taosdata/grafanaplugin/releases/download/v$GF_VERSION/tdengine-datasource-$GF_VERSION.zip
+# from Grafana
+wget -O tdengine-datasource-$GF_VERSION.zip https://grafana.com/api/plugins/tdengine-datasource/versions/$GF_VERSION/download
```
以 CentOS 7.2 操作系统为例,将插件包解压到 /var/lib/grafana/plugins 目录下,重新启动 grafana 即可。
@@ -41,28 +42,17 @@ wget https://github.com/taosdata/grafanaplugin/releases/download/v$GF_VERSION/td
sudo unzip tdengine-datasource-$GF_VERSION.zip -d /var/lib/grafana/plugins/
```
-:::note
-3.1.6 和更早版本未签名,会在 Grafana 7.3+ / 8.x 版本签名检查时失败导致无法加载插件,需要在 grafana.ini 文件中修改配置如下:
-
-```ini
-[plugins]
-allow_loading_unsigned_plugins = tdengine-datasource
-```
-
-:::
-
-在 Docker 环境下,可以使用如下的环境变量设置自动安装并设置 TDengine 插件:
+如果 Grafana 在 Docker 环境下运行,可以使用如下的环境变量设置自动安装 TDengine 数据源插件:
```bash
-GF_INSTALL_PLUGINS=https://github.com/taosdata/grafanaplugin/releases/download/v3.1.4/tdengine-datasource-3.1.4.zip;tdengine-datasource
-GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=tdengine-datasource
+GF_INSTALL_PLUGINS=tdengine-datasource
```
## 使用 Grafana
### 配置数据源
-用户可以直接通过 http://localhost:3000 的网址,登录 Grafana 服务器(用户名/密码:admin/admin),通过左侧 `Configuration -> Data Sources` 可以添加数据源,如下图所示:
+用户可以直接通过 的网址,登录 Grafana 服务器(用户名/密码:admin/admin),通过左侧 `Configuration -> Data Sources` 可以添加数据源,如下图所示:

@@ -74,7 +64,7 @@ GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=tdengine-datasource

-- Host: TDengine 集群中提供 REST 服务 (在 2.4 之前由 taosd 提供, 从 2.4 开始由 taosAdapter 提供)的组件所在服务器的 IP 地址与 TDengine REST 服务的端口号(6041),默认 http://localhost:6041。
+- Host: TDengine 集群中提供 REST 服务 (在 2.4 之前由 taosd 提供, 从 2.4 开始由 taosAdapter 提供)的组件所在服务器的 IP 地址与 TDengine REST 服务的端口号(6041),默认 。
- User:TDengine 用户名。
- Password:TDengine 用户密码。
diff --git a/docs-en/14-reference/03-connector/cpp.mdx b/docs-en/14-reference/03-connector/cpp.mdx
index d13a74384c..d549413012 100644
--- a/docs-en/14-reference/03-connector/cpp.mdx
+++ b/docs-en/14-reference/03-connector/cpp.mdx
@@ -114,7 +114,6 @@ This section shows sample code for standard access methods to TDengine clusters
Subscribe and consume
```c
-{{#include examples/c/subscribe.c}}
```
diff --git a/docs-en/20-third-party/01-grafana.mdx b/docs-en/20-third-party/01-grafana.mdx
index b3cab62710..1a84e02c66 100644
--- a/docs-en/20-third-party/01-grafana.mdx
+++ b/docs-en/20-third-party/01-grafana.mdx
@@ -9,7 +9,8 @@ You can learn more about using the TDengine plugin on [GitHub](https://github.co
## Prerequisites
-In order for Grafana to add the TDengine data source successfully, the following preparation is required:
+In order for Grafana to add the TDengine data source successfully, the following preparations are required:
+
1. The TDengine cluster is deployed and functioning properly
2. taosAdapter is installed and running properly. Please refer to the taosAdapter manual for details.
@@ -19,41 +20,34 @@ TDengine currently supports Grafana versions 7.0 and above. Users can go to the
## Configuring Grafana
-You can download The Grafana plugin for TDengine from . The current latest version is 3.1.4.
-
-Recommend using the [``grafana-cli`` command-line tool](https://grafana.com/docs/grafana/latest/administration/cli/) for plugin installation.
+Follow the installation steps in [Grafana](https://grafana.com/grafana/plugins/tdengine-datasource/?tab=installation) with the [``grafana-cli`` command-line tool](https://grafana.com/docs/grafana/latest/administration/cli/) for plugin installation.
```bash
-sudo -u grafana grafana-cli \
- --pluginUrl https://github.com/taosdata/grafanaplugin/releases/download/v3.1.4/tdengine-datasource-3.1.4.zip \
- plugins install tdengine-datasource
+grafana-cli plugins install tdengine-datasource
+# with sudo
+sudo -u grafana grafana-cli plugins install tdengine-datasource
```
-Or download it locally and extract it to the Grafana plugin directory.
+Alternatively, you can manually download the .zip file from [GitHub](https://github.com/taosdata/grafanaplugin/releases/tag/latest) or [Grafana](https://grafana.com/grafana/plugins/tdengine-datasource/?tab=installation) and unpack it into your grafana plugins directory.
```bash
-GF_VERSION=3.1.4
+GF_VERSION=3.2.2
+# from GitHub
wget https://github.com/taosdata/grafanaplugin/releases/download/v$GF_VERSION/tdengine-datasource-$GF_VERSION.zip
+# from Grafana
+wget -O tdengine-datasource-$GF_VERSION.zip https://grafana.com/api/plugins/tdengine-datasource/versions/$GF_VERSION/download
```
-In CentOS 7.2 for example, extract the plugin package to /var/lib/grafana/plugins directory, and restart grafana.
+Take CentOS 7.2 for example, extract the plugin package to /var/lib/grafana/plugins directory, and restart grafana.
```bash
sudo unzip tdengine-datasource-$GF_VERSION.zip -d /var/lib/grafana/plugins/
```
-Grafana versions 7.3+ / 8.x do signature checks on plugins, so you also need to add the following line to the grafana.ini file to use the plugin correctly.
-
-```ini
-[plugins]
-allow_loading_unsigned_plugins = tdengine-datasource
-```
-
-The TDengine plugin can be automatically installed and set up using the following environment variable settings in a Docker environment.
+If Grafana is running in a Docker environment, the TDengine plugin can be automatically installed and set up using the following environment variable settings:
```bash
-GF_INSTALL_PLUGINS=https://github.com/taosdata/grafanaplugin/releases/download/v3.1.4/tdengine-datasource-3.1.4.zip;tdengine- datasource
-GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=tdengine-datasource
+GF_INSTALL_PLUGINS=tdengine-datasource
```
## Using Grafana
diff --git a/examples/c/tmq.c b/examples/c/tmq.c
index a8584bae82..2e8aa21da7 100644
--- a/examples/c/tmq.c
+++ b/examples/c/tmq.c
@@ -24,6 +24,7 @@ static void msg_process(TAOS_RES* msg) {
char buf[1024];
/*memset(buf, 0, 1024);*/
printf("topic: %s\n", tmq_get_topic_name(msg));
+ printf("db: %s\n", tmq_get_db_name(msg));
printf("vg: %d\n", tmq_get_vgroup_id(msg));
while (1) {
TAOS_ROW row = taos_fetch_row(msg);
@@ -176,8 +177,8 @@ tmq_t* build_consumer() {
tmq_list_t* build_topic_list() {
tmq_list_t* topic_list = tmq_list_new();
- /*tmq_list_append(topic_list, "topic_ctb_column");*/
- tmq_list_append(topic_list, "tmq_test_db_multi_insert_topic");
+ tmq_list_append(topic_list, "topic_ctb_column");
+ /*tmq_list_append(topic_list, "tmq_test_db_multi_insert_topic");*/
return topic_list;
}
diff --git a/include/client/taos.h b/include/client/taos.h
index bab0c18db1..b65091f52b 100644
--- a/include/client/taos.h
+++ b/include/client/taos.h
@@ -144,8 +144,8 @@ DLL_EXPORT int taos_stmt_set_tbname_tags(TAOS_STMT *stmt, const char *nam
DLL_EXPORT int taos_stmt_set_tbname(TAOS_STMT *stmt, const char *name);
DLL_EXPORT int taos_stmt_set_tags(TAOS_STMT *stmt, TAOS_MULTI_BIND *tags);
DLL_EXPORT int taos_stmt_set_sub_tbname(TAOS_STMT *stmt, const char *name);
-DLL_EXPORT int taos_stmt_get_tag_fields(TAOS_STMT *stmt, int* fieldNum, TAOS_FIELD_E** fields);
-DLL_EXPORT int taos_stmt_get_col_fields(TAOS_STMT *stmt, int* fieldNum, TAOS_FIELD_E** fields);
+DLL_EXPORT int taos_stmt_get_tag_fields(TAOS_STMT *stmt, int *fieldNum, TAOS_FIELD_E **fields);
+DLL_EXPORT int taos_stmt_get_col_fields(TAOS_STMT *stmt, int *fieldNum, TAOS_FIELD_E **fields);
DLL_EXPORT int taos_stmt_is_insert(TAOS_STMT *stmt, int *insert);
DLL_EXPORT int taos_stmt_num_params(TAOS_STMT *stmt, int *nums);
@@ -269,6 +269,7 @@ DLL_EXPORT void tmq_conf_set_auto_commit_cb(tmq_conf_t *conf, tmq_comm
/* -------------------------TMQ MSG HANDLE INTERFACE---------------------- */
DLL_EXPORT const char *tmq_get_topic_name(TAOS_RES *res);
+DLL_EXPORT const char *tmq_get_db_name(TAOS_RES *res);
DLL_EXPORT int32_t tmq_get_vgroup_id(TAOS_RES *res);
DLL_EXPORT const char *tmq_get_table_name(TAOS_RES *res);
diff --git a/include/common/taosdef.h b/include/common/taosdef.h
index d39c7a1215..516df71b0b 100644
--- a/include/common/taosdef.h
+++ b/include/common/taosdef.h
@@ -97,6 +97,7 @@ extern char *qtypeStr[];
#undef TD_DEBUG_PRINT_ROW
#undef TD_DEBUG_PRINT_TSDB_LOAD_DCOLS
+#undef TD_DEBUG_PRINT_TAG
#ifdef __cplusplus
}
diff --git a/include/common/tdatablock.h b/include/common/tdatablock.h
index 9b71e8c454..66b81efc5b 100644
--- a/include/common/tdatablock.h
+++ b/include/common/tdatablock.h
@@ -227,6 +227,9 @@ int32_t blockDataTrimFirstNRows(SSDataBlock* pBlock, size_t n);
SSDataBlock* createOneDataBlock(const SSDataBlock* pDataBlock, bool copyData);
+void blockCompressEncode(const SSDataBlock* pBlock, char* data, int32_t* dataLen, int32_t numOfCols, int8_t needCompress);
+const char* blockCompressDecode(SSDataBlock* pBlock, int32_t numOfCols, int32_t numOfRows, const char* pData);
+
void blockDebugShowData(const SArray* dataBlocks);
int32_t buildSubmitReqFromDataBlock(SSubmitReq** pReq, const SArray* pDataBlocks, STSchema* pTSchema, int32_t vgId,
@@ -246,54 +249,6 @@ static FORCE_INLINE int32_t blockCompressColData(SColumnInfoData* pColRes, int32
colSize + COMP_OVERFLOW_BYTES, compressed, NULL, 0);
}
-static FORCE_INLINE void blockCompressEncode(const SSDataBlock* pBlock, char* data, int32_t* dataLen, int32_t numOfCols,
- int8_t needCompress) {
- int32_t* actualLen = (int32_t*)data;
- data += sizeof(int32_t);
-
- uint64_t* groupId = (uint64_t*)data;
- data += sizeof(uint64_t);
-
- int32_t* colSizes = (int32_t*)data;
- data += numOfCols * sizeof(int32_t);
-
- *dataLen = (numOfCols * sizeof(int32_t) + sizeof(uint64_t) + sizeof(int32_t));
-
- int32_t numOfRows = pBlock->info.rows;
- for (int32_t col = 0; col < numOfCols; ++col) {
- SColumnInfoData* pColRes = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, col);
-
- // copy the null bitmap
- if (IS_VAR_DATA_TYPE(pColRes->info.type)) {
- size_t metaSize = numOfRows * sizeof(int32_t);
- memcpy(data, pColRes->varmeta.offset, metaSize);
- data += metaSize;
- (*dataLen) += metaSize;
- } else {
- int32_t len = BitmapLen(numOfRows);
- memcpy(data, pColRes->nullbitmap, len);
- data += len;
- (*dataLen) += len;
- }
-
- if (needCompress) {
- colSizes[col] = blockCompressColData(pColRes, numOfRows, data, needCompress);
- data += colSizes[col];
- (*dataLen) += colSizes[col];
- } else {
- colSizes[col] = colDataGetLength(pColRes, numOfRows);
- (*dataLen) += colSizes[col];
- memmove(data, pColRes->pData, colSizes[col]);
- data += colSizes[col];
- }
-
- colSizes[col] = htonl(colSizes[col]);
- }
-
- *actualLen = *dataLen;
- *groupId = pBlock->info.groupId;
-}
-
#ifdef __cplusplus
}
#endif
diff --git a/include/common/tdataformat.h b/include/common/tdataformat.h
index 867115d16d..10bc6a6176 100644
--- a/include/common/tdataformat.h
+++ b/include/common/tdataformat.h
@@ -70,7 +70,8 @@ char* tTagValToData(const STagVal *pTagVal, bool isJson);
int32_t tEncodeTag(SEncoder *pEncoder, const STag *pTag);
int32_t tDecodeTag(SDecoder *pDecoder, STag **ppTag);
int32_t tTagToValArray(const STag *pTag, SArray **ppArray);
-void debugPrintSTag(STag *pTag, const char *tag, int32_t ln);
+void debugPrintSTag(STag *pTag, const char *tag, int32_t ln); // TODO: remove
+void debugCheckTags(STag *pTag); // TODO: remove
// STRUCT =================
struct STColumn {
diff --git a/include/common/tglobal.h b/include/common/tglobal.h
index 2a4ef565dd..30ae6c2adb 100644
--- a/include/common/tglobal.h
+++ b/include/common/tglobal.h
@@ -45,6 +45,8 @@ extern bool tsEnableSlaveQuery;
extern bool tsPrintAuth;
extern int64_t tsTickPerMin[3];
+extern int32_t tsCountAlwaysReturnValue;
+
// multi-process
extern int32_t tsMultiProcess;
extern int32_t tsMnodeShmSize;
@@ -102,7 +104,6 @@ extern int32_t tsMaxStreamComputDelay;
extern int32_t tsStreamCompStartDelay;
extern int32_t tsRetryStreamCompDelay;
extern float tsStreamComputDelayRatio; // the delayed computing ration of the whole time window
-extern int32_t tsProjectExecInterval;
extern int64_t tsMaxRetentWindow;
// build info
diff --git a/include/common/tmsg.h b/include/common/tmsg.h
index f332300a4f..e0dcfbd544 100644
--- a/include/common/tmsg.h
+++ b/include/common/tmsg.h
@@ -571,13 +571,6 @@ int32_t tSerializeSGetUserAuthRsp(void* buf, int32_t bufLen, SGetUserAuthRsp* pR
int32_t tDeserializeSGetUserAuthRsp(void* buf, int32_t bufLen, SGetUserAuthRsp* pRsp);
void tFreeSGetUserAuthRsp(SGetUserAuthRsp* pRsp);
-typedef struct {
- int16_t colId; // column id
- int16_t colIndex; // column index in colList if it is a normal column or index in tagColList if a tag
- int16_t flag; // denote if it is a tag or a normal column
- char name[TSDB_DB_FNAME_LEN];
-} SColIndex;
-
typedef struct {
int16_t lowerRelOptr;
int16_t upperRelOptr;
@@ -779,6 +772,7 @@ typedef struct {
int8_t cacheLastRow;
int32_t numOfRetensions;
SArray* pRetensions;
+ int8_t schemaless;
} SDbCfgRsp;
int32_t tSerializeSDbCfgRsp(void* buf, int32_t bufLen, const SDbCfgRsp* pRsp);
@@ -1127,6 +1121,14 @@ typedef struct {
SSchema* pSchemas;
} STableMetaRsp;
+typedef struct {
+ STableMetaRsp* pMeta;
+} SMAlterStbRsp;
+
+int32_t tEncodeSMAlterStbRsp(SEncoder *pEncoder, const SMAlterStbRsp *pRsp);
+int32_t tDecodeSMAlterStbRsp(SDecoder *pDecoder, SMAlterStbRsp *pRsp);
+void tFreeSMAlterStbRsp(SMAlterStbRsp* pRsp);
+
int32_t tSerializeSTableMetaRsp(void* buf, int32_t bufLen, STableMetaRsp* pRsp);
int32_t tDeserializeSTableMetaRsp(void* buf, int32_t bufLen, STableMetaRsp* pRsp);
void tFreeSTableMetaRsp(STableMetaRsp* pRsp);
@@ -1880,7 +1882,8 @@ int32_t tEncodeSVAlterTbReq(SEncoder* pEncoder, const SVAlterTbReq* pReq);
int32_t tDecodeSVAlterTbReq(SDecoder* pDecoder, SVAlterTbReq* pReq);
typedef struct {
- int32_t code;
+ int32_t code;
+ STableMetaRsp* pMeta;
} SVAlterTbRsp;
int32_t tEncodeSVAlterTbRsp(SEncoder* pEncoder, const SVAlterTbRsp* pRsp);
@@ -2203,10 +2206,8 @@ typedef struct {
int64_t newConsumerId;
char subKey[TSDB_SUBSCRIBE_KEY_LEN];
int8_t subType;
- // int8_t withTbName;
- // int8_t withSchema;
- // int8_t withTag;
- char* qmsg;
+ char* qmsg;
+ int64_t suid;
} SMqRebVgReq;
static FORCE_INLINE int32_t tEncodeSMqRebVgReq(void** buf, const SMqRebVgReq* pReq) {
@@ -2217,11 +2218,10 @@ static FORCE_INLINE int32_t tEncodeSMqRebVgReq(void** buf, const SMqRebVgReq* pR
tlen += taosEncodeFixedI64(buf, pReq->newConsumerId);
tlen += taosEncodeString(buf, pReq->subKey);
tlen += taosEncodeFixedI8(buf, pReq->subType);
- // tlen += taosEncodeFixedI8(buf, pReq->withTbName);
- // tlen += taosEncodeFixedI8(buf, pReq->withSchema);
- // tlen += taosEncodeFixedI8(buf, pReq->withTag);
if (pReq->subType == TOPIC_SUB_TYPE__COLUMN) {
tlen += taosEncodeString(buf, pReq->qmsg);
+ } else if (pReq->subType == TOPIC_SUB_TYPE__TABLE) {
+ tlen += taosEncodeFixedI64(buf, pReq->suid);
}
return tlen;
}
@@ -2233,11 +2233,10 @@ static FORCE_INLINE void* tDecodeSMqRebVgReq(const void* buf, SMqRebVgReq* pReq)
buf = taosDecodeFixedI64(buf, &pReq->newConsumerId);
buf = taosDecodeStringTo(buf, pReq->subKey);
buf = taosDecodeFixedI8(buf, &pReq->subType);
- // buf = taosDecodeFixedI8(buf, &pReq->withTbName);
- // buf = taosDecodeFixedI8(buf, &pReq->withSchema);
- // buf = taosDecodeFixedI8(buf, &pReq->withTag);
if (pReq->subType == TOPIC_SUB_TYPE__COLUMN) {
buf = taosDecodeString(buf, &pReq->qmsg);
+ } else if (pReq->subType == TOPIC_SUB_TYPE__TABLE) {
+ buf = taosDecodeFixedI64(buf, &pReq->suid);
}
return (void*)buf;
}
@@ -2348,19 +2347,19 @@ typedef struct {
STSma* tSma;
} STSmaWrapper;
-static FORCE_INLINE void tdDestroyTSma(STSma* pSma) {
+static FORCE_INLINE void tDestroyTSma(STSma* pSma) {
if (pSma) {
taosMemoryFreeClear(pSma->expr);
taosMemoryFreeClear(pSma->tagsFilter);
}
}
-static FORCE_INLINE void tdDestroyTSmaWrapper(STSmaWrapper* pSW, bool deepCopy) {
+static FORCE_INLINE void tDestroyTSmaWrapper(STSmaWrapper* pSW, bool deepCopy) {
if (pSW) {
if (pSW->tSma) {
if (deepCopy) {
for (uint32_t i = 0; i < pSW->number; ++i) {
- tdDestroyTSma(pSW->tSma + i);
+ tDestroyTSma(pSW->tSma + i);
}
}
taosMemoryFreeClear(pSW->tSma);
@@ -2368,8 +2367,8 @@ static FORCE_INLINE void tdDestroyTSmaWrapper(STSmaWrapper* pSW, bool deepCopy)
}
}
-static FORCE_INLINE void* tdFreeTSmaWrapper(STSmaWrapper* pSW, bool deepCopy) {
- tdDestroyTSmaWrapper(pSW, deepCopy);
+static FORCE_INLINE void* tFreeTSmaWrapper(STSmaWrapper* pSW, bool deepCopy) {
+ tDestroyTSmaWrapper(pSW, deepCopy);
taosMemoryFreeClear(pSW);
return NULL;
}
@@ -2396,6 +2395,17 @@ static int32_t tDecodeTSmaWrapper(SDecoder* pDecoder, STSmaWrapper* pReq) {
return 0;
}
+typedef struct {
+ int64_t tsmaIndexUid;
+ STimeWindow queryWindow;
+} SVGetTsmaExpWndsReq;
+
+typedef struct {
+ int64_t tsmaIndexUid;
+ int32_t numExpWnds;
+ TSKEY* expWndsStartTs;
+} SVGetTsmaExpWndsRsp;
+
typedef struct {
int idx;
} SMCreateFullTextReq;
@@ -2471,7 +2481,7 @@ static FORCE_INLINE void* tDecodeSMqSubVgEp(void* buf, SMqSubVgEp* pVgEp) {
typedef struct {
char topic[TSDB_TOPIC_FNAME_LEN];
- int8_t isSchemaAdaptive;
+ char db[TSDB_DB_FNAME_LEN];
SArray* vgs; // SArray
SSchemaWrapper schema;
} SMqSubTopicEp;
@@ -2479,7 +2489,7 @@ typedef struct {
static FORCE_INLINE int32_t tEncodeSMqSubTopicEp(void** buf, const SMqSubTopicEp* pTopicEp) {
int32_t tlen = 0;
tlen += taosEncodeString(buf, pTopicEp->topic);
- tlen += taosEncodeFixedI8(buf, pTopicEp->isSchemaAdaptive);
+ tlen += taosEncodeString(buf, pTopicEp->db);
int32_t sz = taosArrayGetSize(pTopicEp->vgs);
tlen += taosEncodeFixedI32(buf, sz);
for (int32_t i = 0; i < sz; i++) {
@@ -2492,7 +2502,7 @@ static FORCE_INLINE int32_t tEncodeSMqSubTopicEp(void** buf, const SMqSubTopicEp
static FORCE_INLINE void* tDecodeSMqSubTopicEp(void* buf, SMqSubTopicEp* pTopicEp) {
buf = taosDecodeStringTo(buf, pTopicEp->topic);
- buf = taosDecodeFixedI8(buf, &pTopicEp->isSchemaAdaptive);
+ buf = taosDecodeStringTo(buf, pTopicEp->db);
int32_t sz;
buf = taosDecodeFixedI32(buf, &sz);
pTopicEp->vgs = taosArrayInit(sz, sizeof(SMqSubVgEp));
diff --git a/include/common/tmsgdef.h b/include/common/tmsgdef.h
index ba4a221a9f..860674b343 100644
--- a/include/common/tmsgdef.h
+++ b/include/common/tmsgdef.h
@@ -205,6 +205,7 @@ enum {
TD_DEF_MSG_TYPE(TDMT_VND_CANCEL_SMA, "vnode-cancel-sma", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_DROP_SMA, "vnode-drop-sma", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_SUBMIT_RSMA, "vnode-submit-rsma", SSubmitReq, SSubmitRsp)
+ TD_DEF_MSG_TYPE(TDMT_VND_GET_TSMA_EXP_WNDS, "vnode-get-tsma-expired-windows", SVGetTsmaExpWndsReq, SVGetTsmaExpWndsRsp)
TD_DEF_MSG_TYPE(TDMT_VND_SYNC_TIMEOUT, "vnode-sync-timeout", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_SYNC_PING, "vnode-sync-ping", NULL, NULL)
diff --git a/include/libs/catalog/catalog.h b/include/libs/catalog/catalog.h
index 8027b9394e..f0e642bc9a 100644
--- a/include/libs/catalog/catalog.h
+++ b/include/libs/catalog/catalog.h
@@ -183,7 +183,7 @@ int32_t catalogGetTableMeta(SCatalog* pCatalog, void * pTransporter, const SEpSe
*/
int32_t catalogGetSTableMeta(SCatalog* pCatalog, void * pTransporter, const SEpSet* pMgmtEps, const SName* pTableName, STableMeta** pTableMeta);
-int32_t catalogUpdateSTableMeta(SCatalog* pCatalog, STableMetaRsp *rspMsg);
+int32_t catalogUpdateTableMeta(SCatalog* pCatalog, STableMetaRsp *rspMsg);
/**
diff --git a/include/libs/executor/executor.h b/include/libs/executor/executor.h
index 5379a8f712..288248422b 100644
--- a/include/libs/executor/executor.h
+++ b/include/libs/executor/executor.h
@@ -156,18 +156,6 @@ int64_t qGetQueriedTableUid(qTaskInfo_t tinfo);
*/
int32_t qGetQualifiedTableIdList(void* pTableList, const char* tagCond, int32_t tagCondLen, SArray* pTableIdList);
-/**
- * Create the table group according to the group by tags info
- * @param pTableIdList
- * @param skey
- * @param groupInfo
- * @param groupByIndex
- * @param numOfIndex
- * @return
- */
-// int32_t qCreateTableGroupByGroupExpr(SArray* pTableIdList, TSKEY skey, STableGroupInfo groupInfo, SColIndex*
-// groupByIndex, int32_t numOfIndex);
-
/**
* Update the table id list of a given query.
* @param uid child table uid
diff --git a/include/libs/function/function.h b/include/libs/function/function.h
index 21b7309055..e8cb363e08 100644
--- a/include/libs/function/function.h
+++ b/include/libs/function/function.h
@@ -61,56 +61,9 @@ typedef struct SFileBlockInfo {
#define TSDB_BLOCK_DIST_STEP_ROWS 8
#define MAX_INTERVAL_TIME_WINDOW 1000000 // maximum allowed time windows in final results
-#define FUNCTION_TYPE_SCALAR 1
-#define FUNCTION_TYPE_AGG 2
-
#define TOP_BOTTOM_QUERY_LIMIT 100
#define FUNCTIONS_NAME_MAX_LENGTH 16
-#define FUNCTION_INVALID_ID -1
-#define FUNCTION_COUNT 0
-#define FUNCTION_SUM 1
-#define FUNCTION_AVG 2
-#define FUNCTION_MIN 3
-#define FUNCTION_MAX 4
-#define FUNCTION_STDDEV 5
-#define FUNCTION_PERCT 6
-#define FUNCTION_APERCT 7
-#define FUNCTION_FIRST 8
-#define FUNCTION_LAST 9
-#define FUNCTION_LAST_ROW 10
-#define FUNCTION_TOP 11
-#define FUNCTION_BOTTOM 12
-#define FUNCTION_SPREAD 13
-#define FUNCTION_TWA 14
-#define FUNCTION_LEASTSQR 15
-
-#define FUNCTION_TS 16
-#define FUNCTION_TS_DUMMY 17
-#define FUNCTION_TAG_DUMMY 18
-#define FUNCTION_TS_COMP 19
-
-#define FUNCTION_TAG 20
-#define FUNCTION_PRJ 21
-
-#define FUNCTION_TAGPRJ 22
-#define FUNCTION_ARITHM 23
-#define FUNCTION_DIFF 24
-
-#define FUNCTION_FIRST_DST 25
-#define FUNCTION_LAST_DST 26
-#define FUNCTION_STDDEV_DST 27
-#define FUNCTION_INTERP 28
-
-#define FUNCTION_RATE 29
-#define FUNCTION_IRATE 30
-#define FUNCTION_TID_TAG 31
-#define FUNCTION_DERIVATIVE 32
-#define FUNCTION_BLKINFO 33
-
-
-#define FUNCTION_COV 38
-
typedef struct SResultRowEntryInfo {
bool initialized:1; // output buffer has been initialized
bool complete:1; // query has completed
@@ -180,10 +133,9 @@ typedef struct SqlFunctionCtx {
char *pOutput; // final result output buffer, point to sdata->data
int32_t numOfParams;
SFunctParam *param; // input parameter, e.g., top(k, 20), the number of results for top query is kept in param
- int64_t *ptsList; // corresponding timestamp array list
+ int64_t *ptsList; // corresponding timestamp array list, todo remove it
SColumnInfoData *pTsOutput; // corresponding output buffer for timestamp of each result, e.g., top/bottom*/
int32_t offset;
- SVariant tag;
struct SResultRowEntryInfo *resultInfo;
SSubsidiaryResInfo subsidiaries;
SPoint1 start;
@@ -210,9 +162,6 @@ enum {
typedef struct tExprNode {
int32_t nodeType;
union {
- SSchema *pSchema;// column node
- struct SVariant *pVal; // value node
-
struct {// function node
char functionName[FUNCTIONS_NAME_MAX_LENGTH]; // todo refactor
int32_t functionId;
@@ -255,47 +204,23 @@ struct SScalarParam {
int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionId, int32_t param, SResultDataInfo* pInfo, int16_t extLength,
bool isSuperTable);
-bool qIsValidUdf(SArray* pUdfInfo, const char* name, int32_t len, int32_t* functionId);
-
void resetResultRowEntryResult(SqlFunctionCtx* pCtx, int32_t num);
void cleanupResultRowEntry(struct SResultRowEntryInfo* pCell);
int32_t getNumOfResult(SqlFunctionCtx* pCtx, int32_t num, SSDataBlock* pResBlock);
bool isRowEntryCompleted(struct SResultRowEntryInfo* pEntry);
bool isRowEntryInitialized(struct SResultRowEntryInfo* pEntry);
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// fill api
-struct SFillInfo;
-struct SFillColInfo;
-
typedef struct SPoint {
int64_t key;
void * val;
} SPoint;
-//void taosFillSetStartInfo(struct SFillInfo* pFillInfo, int32_t numOfRows, TSKEY endKey);
-//void taosResetFillInfo(struct SFillInfo* pFillInfo, TSKEY startTimestamp);
-//void taosFillSetInputDataBlock(struct SFillInfo* pFillInfo, const struct SSDataBlock* pInput);
-//struct SFillColInfo* createFillColInfo(SExprInfo* pExpr, int32_t numOfOutput, const SValueNode* val);
-//bool taosFillHasMoreResults(struct SFillInfo* pFillInfo);
-//
-//struct SFillInfo* taosCreateFillInfo(int32_t order, TSKEY skey, int32_t numOfTags, int32_t capacity, int32_t numOfCols,
-// SInterval* pInterval, int32_t fillType,
-// struct SFillColInfo* pCol, const char* id);
-//
-//void* taosDestroyFillInfo(struct SFillInfo *pFillInfo);
-//int64_t taosFillResultDataBlock(struct SFillInfo* pFillInfo, void** output, int32_t capacity);
-//int64_t getFillInfoStart(struct SFillInfo *pFillInfo);
-
int32_t taosGetLinearInterpolationVal(SPoint* point, int32_t outputType, SPoint* point1, SPoint* point2, int32_t inputType);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// udf api
struct SUdfInfo;
-void qAddUdfInfo(uint64_t id, struct SUdfInfo* pUdfInfo);
-void qRemoveUdfInfo(uint64_t id, struct SUdfInfo* pUdfInfo);
-
/**
* create udfd proxy, called once in process that call doSetupUdf/callUdfxxx/doTeardownUdf
* @return error code
diff --git a/include/libs/function/functionMgt.h b/include/libs/function/functionMgt.h
index 922136b590..f3e28936af 100644
--- a/include/libs/function/functionMgt.h
+++ b/include/libs/function/functionMgt.h
@@ -156,6 +156,9 @@ bool fmIsDynamicScanOptimizedFunc(int32_t funcId);
bool fmIsMultiResFunc(int32_t funcId);
bool fmIsRepeatScanFunc(int32_t funcId);
bool fmIsUserDefinedFunc(int32_t funcId);
+bool fmIsDistExecFunc(int32_t funcId);
+
+int32_t fmGetDistMethod(const SFunctionNode* pFunc, SFunctionNode** pPartialFunc, SFunctionNode** pMergeFunc);
typedef enum EFuncDataRequired {
FUNC_DATA_REQUIRED_DATA_LOAD = 1,
diff --git a/include/libs/nodes/nodes.h b/include/libs/nodes/nodes.h
index d960ccbd65..41c196c916 100644
--- a/include/libs/nodes/nodes.h
+++ b/include/libs/nodes/nodes.h
@@ -189,6 +189,7 @@ typedef enum ENodeType {
QUERY_NODE_LOGIC_PLAN_PROJECT,
QUERY_NODE_LOGIC_PLAN_VNODE_MODIF,
QUERY_NODE_LOGIC_PLAN_EXCHANGE,
+ QUERY_NODE_LOGIC_PLAN_MERGE,
QUERY_NODE_LOGIC_PLAN_WINDOW,
QUERY_NODE_LOGIC_PLAN_FILL,
QUERY_NODE_LOGIC_PLAN_SORT,
@@ -206,6 +207,7 @@ typedef enum ENodeType {
QUERY_NODE_PHYSICAL_PLAN_JOIN,
QUERY_NODE_PHYSICAL_PLAN_AGG,
QUERY_NODE_PHYSICAL_PLAN_EXCHANGE,
+ QUERY_NODE_PHYSICAL_PLAN_MERGE,
QUERY_NODE_PHYSICAL_PLAN_SORT,
QUERY_NODE_PHYSICAL_PLAN_INTERVAL,
QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL,
diff --git a/include/libs/nodes/plannodes.h b/include/libs/nodes/plannodes.h
index 44e7295b69..5892bffac2 100644
--- a/include/libs/nodes/plannodes.h
+++ b/include/libs/nodes/plannodes.h
@@ -95,9 +95,15 @@ typedef struct SVnodeModifLogicNode {
typedef struct SExchangeLogicNode {
SLogicNode node;
int32_t srcGroupId;
- uint8_t precision;
} SExchangeLogicNode;
+typedef struct SMergeLogicNode {
+ SLogicNode node;
+ SNodeList* pMergeKeys;
+ int32_t numOfChannels;
+ int32_t srcGroupId;
+} SMergeLogicNode;
+
typedef enum EWindowType { WINDOW_TYPE_INTERVAL = 1, WINDOW_TYPE_SESSION, WINDOW_TYPE_STATE } EWindowType;
typedef struct SWindowLogicNode {
@@ -268,6 +274,13 @@ typedef struct SExchangePhysiNode {
SNodeList* pSrcEndPoints; // element is SDownstreamSource, scheduler fill by calling qSetSuplanExecutionNode
} SExchangePhysiNode;
+typedef struct SMergePhysiNode {
+ SPhysiNode node;
+ SNodeList* pMergeKeys;
+ int32_t numOfChannels;
+ int32_t srcGroupId;
+} SMergePhysiNode;
+
typedef struct SWinodwPhysiNode {
SPhysiNode node;
SNodeList* pExprs; // these are expression list of parameter expression of function
diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h
index ab5e10dc2a..e4af78892b 100644
--- a/include/libs/nodes/querynodes.h
+++ b/include/libs/nodes/querynodes.h
@@ -331,8 +331,8 @@ typedef struct SQuery {
int8_t precision;
SCmdMsgInfo* pCmdMsg;
int32_t msgType;
- SArray* pDbList;
SArray* pTableList;
+ SArray* pDbList;
bool showRewrite;
int32_t placeholderNum;
SArray* pPlaceholderValues;
diff --git a/include/libs/parser/parser.h b/include/libs/parser/parser.h
index ca825b9e2f..6abd1ffa6d 100644
--- a/include/libs/parser/parser.h
+++ b/include/libs/parser/parser.h
@@ -49,6 +49,7 @@ typedef struct SParseContext {
const char* pUser;
bool isSuperUser;
bool async;
+ int8_t schemalessType;
} SParseContext;
int32_t qParseSql(SParseContext* pCxt, SQuery** pQuery);
diff --git a/include/libs/qcom/query.h b/include/libs/qcom/query.h
index 296b18e8de..45a7e9a29f 100644
--- a/include/libs/qcom/query.h
+++ b/include/libs/qcom/query.h
@@ -56,6 +56,11 @@ typedef struct STableComInfo {
int32_t rowSize; // row size of the schema
} STableComInfo;
+typedef struct SQueryExecRes {
+ int32_t msgType;
+ void* res;
+} SQueryExecRes;
+
typedef struct SIndexMeta {
#ifdef WINDOWS
size_t avoidCompilationErrors;
@@ -192,6 +197,7 @@ int32_t queryCreateTableMetaFromMsg(STableMetaRsp* msg, bool isSuperTable, STabl
char* jobTaskStatusStr(int32_t status);
SSchema createSchema(int8_t type, int32_t bytes, col_id_t colId, const char* name);
+void destroyQueryExecRes(SQueryExecRes* pRes);
extern int32_t (*queryBuildMsg[TDMT_MAX])(void *input, char **msg, int32_t msgSize, int32_t *msgLen, void*(*mallocFp)(int32_t));
extern int32_t (*queryProcessMsgRsp[TDMT_MAX])(void* output, char* msg, int32_t msgSize);
@@ -204,7 +210,8 @@ extern int32_t (*queryProcessMsgRsp[TDMT_MAX])(void* output, char* msg, int32_t
#define NEED_CLIENT_RM_TBLMETA_ERROR(_code) \
((_code) == TSDB_CODE_PAR_TABLE_NOT_EXIST || (_code) == TSDB_CODE_VND_TB_NOT_EXIST || \
(_code) == TSDB_CODE_PAR_INVALID_COLUMNS_NUM || (_code) == TSDB_CODE_PAR_INVALID_COLUMN || \
- (_code) == TSDB_CODE_PAR_TAGS_NOT_MATCHED || (_code == TSDB_CODE_PAR_VALUE_TOO_LONG))
+ (_code) == TSDB_CODE_PAR_TAGS_NOT_MATCHED || (_code == TSDB_CODE_PAR_VALUE_TOO_LONG) || \
+ (_code == TSDB_CODE_PAR_INVALID_DROP_COL))
#define NEED_CLIENT_REFRESH_VG_ERROR(_code) \
((_code) == TSDB_CODE_VND_HASH_MISMATCH || (_code) == TSDB_CODE_VND_INVALID_VGROUP_ID)
#define NEED_CLIENT_REFRESH_TBLMETA_ERROR(_code) ((_code) == TSDB_CODE_TDB_TABLE_RECREATED)
diff --git a/include/libs/scheduler/scheduler.h b/include/libs/scheduler/scheduler.h
index 0d32cce20b..331b787690 100644
--- a/include/libs/scheduler/scheduler.h
+++ b/include/libs/scheduler/scheduler.h
@@ -56,7 +56,7 @@ typedef struct SQueryProfileSummary {
typedef struct SQueryResult {
int32_t code;
uint64_t numOfRows;
- void *res;
+ SQueryExecRes res;
} SQueryResult;
typedef struct STaskInfo {
diff --git a/include/libs/stream/tstream.h b/include/libs/stream/tstream.h
index 0525cbf367..f7ad7b4ed8 100644
--- a/include/libs/stream/tstream.h
+++ b/include/libs/stream/tstream.h
@@ -80,6 +80,37 @@ typedef struct {
int8_t type;
} SStreamCheckpoint;
+typedef struct {
+ STaosQueue* queue;
+ STaosQall* qall;
+ void* qItem;
+ int8_t failed;
+} SStreamQ;
+
+static FORCE_INLINE void* streamQCurItem(SStreamQ* queue) {
+ //
+ return queue->qItem;
+}
+
+static FORCE_INLINE void* streamQNextItem(SStreamQ* queue) {
+ int8_t failed = atomic_load_8(&queue->failed);
+ if (failed) {
+ ASSERT(queue->qItem != NULL);
+ return streamQCurItem(queue);
+ } else {
+ taosGetQitem(queue->qall, &queue->qItem);
+ if (queue->qItem == NULL) {
+ taosReadAllQitems(queue->queue, queue->qall);
+ taosGetQitem(queue->qall, &queue->qItem);
+ }
+ return streamQCurItem(queue);
+ }
+}
+
+static FORCE_INLINE void streamQSetFail(SStreamQ* queue) { atomic_store_8(&queue->failed, 1); }
+
+static FORCE_INLINE void streamQSetSuccess(SStreamQ* queue) { atomic_store_8(&queue->failed, 0); }
+
static FORCE_INLINE SStreamDataSubmit* streamDataSubmitNew(SSubmitReq* pReq) {
SStreamDataSubmit* pDataSubmit = (SStreamDataSubmit*)taosAllocateQitem(sizeof(SStreamDataSubmit), DEF_QITEM);
if (pDataSubmit == NULL) return NULL;
diff --git a/include/libs/wal/wal.h b/include/libs/wal/wal.h
index e541c214de..95af8ac306 100644
--- a/include/libs/wal/wal.h
+++ b/include/libs/wal/wal.h
@@ -184,6 +184,7 @@ int32_t walRollback(SWal *, int64_t ver);
// notify that previous logs can be pruned safely
int32_t walBeginSnapshot(SWal *, int64_t ver);
int32_t walEndSnapshot(SWal *);
+void walRestoreFromSnapshot(SWal *, int64_t ver);
// int32_t walDataCorrupted(SWal*);
// read
diff --git a/include/util/taoserror.h b/include/util/taoserror.h
index c3d2788897..7335d174a4 100644
--- a/include/util/taoserror.h
+++ b/include/util/taoserror.h
@@ -85,6 +85,7 @@ int32_t* taosGetErrno();
#define TSDB_CODE_RPC_NETWORK_UNAVAIL TAOS_DEF_ERROR_CODE(0, 0x0102)
#define TSDB_CODE_RPC_FQDN_ERROR TAOS_DEF_ERROR_CODE(0, 0x0103)
#define TSDB_CODE_RPC_PORT_EADDRINUSE TAOS_DEF_ERROR_CODE(0, 0x0104)
+#define TSDB_CODE_RPC_INDIRECT_NETWORK_UNAVAIL TAOS_DEF_ERROR_CODE(0, 0x0105)
//client
#define TSDB_CODE_TSC_INVALID_OPERATION TAOS_DEF_ERROR_CODE(0, 0x0200)
@@ -674,6 +675,7 @@ int32_t* taosGetErrno();
#define TSDB_CODE_SML_INVALID_PROTOCOL_TYPE TAOS_DEF_ERROR_CODE(0, 0x3000)
#define TSDB_CODE_SML_INVALID_PRECISION_TYPE TAOS_DEF_ERROR_CODE(0, 0x3001)
#define TSDB_CODE_SML_INVALID_DATA TAOS_DEF_ERROR_CODE(0, 0x3002)
+#define TSDB_CODE_SML_INVALID_DB_CONF TAOS_DEF_ERROR_CODE(0, 0x3003)
#ifdef __cplusplus
}
diff --git a/include/util/tdef.h b/include/util/tdef.h
index de139368c9..0ae22d1953 100644
--- a/include/util/tdef.h
+++ b/include/util/tdef.h
@@ -209,7 +209,7 @@ typedef enum ELogicConditionType {
#define TSDB_INDEX_FNAME_LEN (TSDB_DB_FNAME_LEN + TSDB_INDEX_NAME_LEN + TSDB_NAME_DELIMITER_LEN)
#define TSDB_TYPE_STR_MAX_LEN 32
#define TSDB_TABLE_FNAME_LEN (TSDB_DB_FNAME_LEN + TSDB_TABLE_NAME_LEN + TSDB_NAME_DELIMITER_LEN)
-#define TSDB_TOPIC_FNAME_LEN TSDB_TABLE_FNAME_LEN
+#define TSDB_TOPIC_FNAME_LEN (TSDB_ACCT_ID_LEN + TSDB_TABLE_NAME_LEN + TSDB_NAME_DELIMITER_LEN)
#define TSDB_STREAM_FNAME_LEN TSDB_TABLE_FNAME_LEN
#define TSDB_SUBSCRIBE_KEY_LEN (TSDB_CGROUP_LEN + TSDB_TOPIC_FNAME_LEN + 2)
#define TSDB_PARTITION_KEY_LEN (TSDB_SUBSCRIBE_KEY_LEN + 20)
diff --git a/include/util/tlist.h b/include/util/tlist.h
index 43833d7ecd..1954bda145 100644
--- a/include/util/tlist.h
+++ b/include/util/tlist.h
@@ -229,7 +229,7 @@ int32_t tdListAppend(SList *list, void *data);
SListNode *tdListPopHead(SList *list);
SListNode *tdListPopTail(SList *list);
SListNode *tdListGetHead(SList *list);
-SListNode *tsListGetTail(SList *list);
+SListNode *tdListGetTail(SList *list);
SListNode *tdListPopNode(SList *list, SListNode *node);
void tdListMove(SList *src, SList *dst);
void tdListDiscard(SList *list);
diff --git a/source/client/inc/clientInt.h b/source/client/inc/clientInt.h
index d5e07ce676..3ff61eca25 100644
--- a/source/client/inc/clientInt.h
+++ b/source/client/inc/clientInt.h
@@ -151,6 +151,7 @@ typedef struct STscObj {
int32_t numOfReqs; // number of sqlObj bound to this connection
SAppInstInfo* pAppInfo;
SHashObj* pRequests;
+ int8_t schemalessType;
} STscObj;
typedef struct SResultColumn {
@@ -162,6 +163,7 @@ typedef struct SResultColumn {
} SResultColumn;
typedef struct SReqResultInfo {
+ SQueryExecRes execRes;
const char* pRspMsg;
const char* pData;
TAOS_FIELD* fields; // todo, column names are not needed.
@@ -191,6 +193,7 @@ typedef struct SRequestSendRecvBody {
typedef struct {
int8_t resType;
char topic[TSDB_TOPIC_FNAME_LEN];
+ char db[TSDB_DB_FNAME_LEN];
int32_t vgId;
SSchemaWrapper schema;
int32_t resIter;
@@ -318,7 +321,7 @@ void hbMgrInitMqHbRspHandle();
SRequestObj* launchQueryImpl(SRequestObj* pRequest, SQuery* pQuery, int32_t code, bool keepQuery, void** res);
int32_t getQueryPlan(SRequestObj* pRequest, SQuery* pQuery, SArray** pNodeList);
-int32_t scheduleQuery(SRequestObj* pRequest, SQueryPlan* pDag, SArray* pNodeList, void** res);
+int32_t scheduleQuery(SRequestObj* pRequest, SQueryPlan* pDag, SArray* pNodeList);
int32_t refreshMeta(STscObj* pTscObj, SRequestObj* pRequest);
int32_t updateQnodeList(SAppInstInfo* pInfo, SArray* pNodeList);
diff --git a/source/client/src/clientEnv.c b/source/client/src/clientEnv.c
index 669b2bc97e..19847d9aa2 100644
--- a/source/client/src/clientEnv.c
+++ b/source/client/src/clientEnv.c
@@ -161,6 +161,7 @@ void *createTscObj(const char *user, const char *auth, const char *db, int32_t c
taosThreadMutexInit(&pObj->mutex, NULL);
pObj->id = taosAddRef(clientConnRefPool, pObj);
+ pObj->schemalessType = 0;
tscDebug("connObj created, 0x%" PRIx64, pObj->id);
return pObj;
@@ -234,6 +235,8 @@ static void doDestroyRequest(void *p) {
taosArrayDestroy(pRequest->tableList);
taosArrayDestroy(pRequest->dbList);
+ destroyQueryExecRes(&pRequest->body.resInfo.execRes);
+
deregisterRequest(pRequest);
taosMemoryFreeClear(pRequest);
}
diff --git a/source/client/src/clientHb.c b/source/client/src/clientHb.c
index 70b60195d2..09c3d269c7 100644
--- a/source/client/src/clientHb.c
+++ b/source/client/src/clientHb.c
@@ -120,7 +120,7 @@ static int32_t hbProcessStbInfoRsp(void *value, int32_t valueLen, struct SCatalo
return TSDB_CODE_TSC_INVALID_VALUE;
}
- catalogUpdateSTableMeta(pCatalog, rsp);
+ catalogUpdateTableMeta(pCatalog, rsp);
}
}
diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c
index 375e1c0da9..e7b4fb0657 100644
--- a/source/client/src/clientImpl.c
+++ b/source/client/src/clientImpl.c
@@ -176,6 +176,7 @@ int32_t parseSql(SRequestObj* pRequest, bool topicQuery, SQuery** pQuery, SStmtC
.pTransporter = pTscObj->pAppInfo->pTransporter,
.pStmtCb = pStmtCb,
.pUser = pTscObj->user,
+ .schemalessType = pTscObj->schemalessType,
.isSuperUser = (0 == strcmp(pTscObj->user, TSDB_DEFAULT_USER))};
cxt.mgmtEpSet = getEpSet_s(&pTscObj->pAppInfo->mgmtEp);
@@ -340,22 +341,23 @@ void setResPrecision(SReqResultInfo* pResInfo, int32_t precision) {
pResInfo->precision = precision;
}
-int32_t scheduleAsyncQuery(SRequestObj* pRequest, SQueryPlan* pDag, SArray* pNodeList, void** pRes) {
+int32_t scheduleAsyncQuery(SRequestObj* pRequest, SQueryPlan* pDag, SArray* pNodeList) {
void* pTransporter = pRequest->pTscObj->pAppInfo->pTransporter;
tsem_init(&schdRspSem, 0, 0);
SQueryResult res = {.code = 0, .numOfRows = 0};
int32_t code = schedulerAsyncExecJob(pTransporter, pNodeList, pDag, &pRequest->body.queryJob, pRequest->sqlstr,
- pRequest->metric.start, schdExecCallback, &res);
- while (true) {
+ pRequest->metric.start, schdExecCallback, &res);
+
+ pRequest->body.resInfo.execRes = res.res;
+
+ while (true) {
if (code != TSDB_CODE_SUCCESS) {
if (pRequest->body.queryJob != 0) {
schedulerFreeJob(pRequest->body.queryJob);
}
- *pRes = res.res;
-
pRequest->code = code;
terrno = code;
return pRequest->code;
@@ -378,26 +380,25 @@ int32_t scheduleAsyncQuery(SRequestObj* pRequest, SQueryPlan* pDag, SArray* pNod
}
}
- *pRes = res.res;
-
pRequest->code = res.code;
terrno = res.code;
return pRequest->code;
}
-int32_t scheduleQuery(SRequestObj* pRequest, SQueryPlan* pDag, SArray* pNodeList, void** pRes) {
+int32_t scheduleQuery(SRequestObj* pRequest, SQueryPlan* pDag, SArray* pNodeList) {
void* pTransporter = pRequest->pTscObj->pAppInfo->pTransporter;
SQueryResult res = {.code = 0, .numOfRows = 0};
int32_t code = schedulerExecJob(pTransporter, pNodeList, pDag, &pRequest->body.queryJob, pRequest->sqlstr,
pRequest->metric.start, &res);
+
+ pRequest->body.resInfo.execRes = res.res;
+
if (code != TSDB_CODE_SUCCESS) {
if (pRequest->body.queryJob != 0) {
schedulerFreeJob(pRequest->body.queryJob);
}
- *pRes = res.res;
-
pRequest->code = code;
terrno = code;
return pRequest->code;
@@ -411,8 +412,6 @@ int32_t scheduleQuery(SRequestObj* pRequest, SQueryPlan* pDag, SArray* pNodeList
}
}
- *pRes = res.res;
-
pRequest->code = res.code;
terrno = res.code;
return pRequest->code;
@@ -422,80 +421,109 @@ int32_t getQueryPlan(SRequestObj* pRequest, SQuery* pQuery, SArray** pNodeList)
return getPlan(pRequest, pQuery, &pRequest->body.pDag, pNodeList);
}
-int32_t validateSversion(SRequestObj* pRequest, void* res) {
- SArray* pArray = NULL;
+int32_t handleSubmitExecRes(SRequestObj* pRequest, void* res, SCatalog* pCatalog, SEpSet *epset) {
int32_t code = 0;
-
- if (TDMT_VND_SUBMIT == pRequest->type) {
- SSubmitRsp* pRsp = (SSubmitRsp*)res;
- if (pRsp->nBlocks <= 0) {
- return TSDB_CODE_SUCCESS;
- }
-
- pArray = taosArrayInit(pRsp->nBlocks, sizeof(STbSVersion));
- if (NULL == pArray) {
- terrno = TSDB_CODE_OUT_OF_MEMORY;
- return TSDB_CODE_OUT_OF_MEMORY;
- }
-
- for (int32_t i = 0; i < pRsp->nBlocks; ++i) {
- SSubmitBlkRsp* blk = pRsp->pBlocks + i;
- if (NULL == blk->tblFName || 0 == blk->tblFName[0]) {
- continue;
- }
-
- STbSVersion tbSver = {.tbFName = blk->tblFName, .sver = blk->sver};
- taosArrayPush(pArray, &tbSver);
- }
- } else if (TDMT_VND_QUERY == pRequest->type) {
- SArray* pTbArray = (SArray*)res;
- int32_t tbNum = taosArrayGetSize(pTbArray);
- if (tbNum <= 0) {
- return TSDB_CODE_SUCCESS;
- }
-
- pArray = taosArrayInit(tbNum, sizeof(STbSVersion));
- if (NULL == pArray) {
- terrno = TSDB_CODE_OUT_OF_MEMORY;
- return TSDB_CODE_OUT_OF_MEMORY;
- }
-
- for (int32_t i = 0; i < tbNum; ++i) {
- STbVerInfo* tbInfo = taosArrayGet(pTbArray, i);
- STbSVersion tbSver = {.tbFName = tbInfo->tbFName, .sver = tbInfo->sversion, .tver = tbInfo->tversion};
- taosArrayPush(pArray, &tbSver);
+ SArray* pArray = NULL;
+ SSubmitRsp* pRsp = (SSubmitRsp*)res;
+ if (pRsp->nBlocks <= 0) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ pArray = taosArrayInit(pRsp->nBlocks, sizeof(STbSVersion));
+ if (NULL == pArray) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ for (int32_t i = 0; i < pRsp->nBlocks; ++i) {
+ SSubmitBlkRsp* blk = pRsp->pBlocks + i;
+ if (NULL == blk->tblFName || 0 == blk->tblFName[0]) {
+ continue;
}
+
+ STbSVersion tbSver = {.tbFName = blk->tblFName, .sver = blk->sver};
+ taosArrayPush(pArray, &tbSver);
}
- SCatalog* pCatalog = NULL;
- CHECK_CODE_GOTO(catalogGetHandle(pRequest->pTscObj->pAppInfo->clusterId, &pCatalog), _return);
-
- SEpSet epset = getEpSet_s(&pRequest->pTscObj->pAppInfo->mgmtEp);
-
- code = catalogChkTbMetaVersion(pCatalog, pRequest->pTscObj->pAppInfo->pTransporter, &epset, pArray);
+ code = catalogChkTbMetaVersion(pCatalog, pRequest->pTscObj->pAppInfo->pTransporter, epset, pArray);
_return:
taosArrayDestroy(pArray);
+ return code;
+}
+
+int32_t handleQueryExecRes(SRequestObj* pRequest, void* res, SCatalog* pCatalog, SEpSet *epset) {
+ int32_t code = 0;
+ SArray* pArray = NULL;
+ SArray* pTbArray = (SArray*)res;
+ int32_t tbNum = taosArrayGetSize(pTbArray);
+ if (tbNum <= 0) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ pArray = taosArrayInit(tbNum, sizeof(STbSVersion));
+ if (NULL == pArray) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ for (int32_t i = 0; i < tbNum; ++i) {
+ STbVerInfo* tbInfo = taosArrayGet(pTbArray, i);
+ STbSVersion tbSver = {.tbFName = tbInfo->tbFName, .sver = tbInfo->sversion, .tver = tbInfo->tversion};
+ taosArrayPush(pArray, &tbSver);
+ }
+
+ code = catalogChkTbMetaVersion(pCatalog, pRequest->pTscObj->pAppInfo->pTransporter, epset, pArray);
+
+_return:
+
+ taosArrayDestroy(pArray);
+ return code;
+}
+
+int32_t handleAlterTbExecRes(void* res, SCatalog* pCatalog) {
+ return catalogUpdateTableMeta(pCatalog, (STableMetaRsp*)res);
+}
+
+int32_t handleExecRes(SRequestObj* pRequest) {
+ if (NULL == pRequest->body.resInfo.execRes.res) {
+ return TSDB_CODE_SUCCESS;
+ }
+
+ int32_t code = 0;
+ SCatalog* pCatalog = NULL;
+ code = catalogGetHandle(pRequest->pTscObj->pAppInfo->clusterId, &pCatalog);
+ if (code) {
+ return code;
+ }
+
+ SEpSet epset = getEpSet_s(&pRequest->pTscObj->pAppInfo->mgmtEp);
+ SQueryExecRes* pRes = &pRequest->body.resInfo.execRes;
+
+ switch (pRes->msgType) {
+ case TDMT_VND_ALTER_TABLE:
+ case TDMT_MND_ALTER_STB: {
+ code = handleAlterTbExecRes(pRes->res, pCatalog);
+ break;
+ }
+ case TDMT_VND_SUBMIT: {
+ code = handleSubmitExecRes(pRequest, pRes->res, pCatalog, &epset);
+ break;
+ }
+ case TDMT_VND_QUERY: {
+ code = handleQueryExecRes(pRequest, pRes->res, pCatalog, &epset);
+ break;
+ }
+ default:
+ tscError("invalid exec result for request type %d", pRequest->type);
+ return TSDB_CODE_APP_ERROR;
+ }
return code;
}
-void freeRequestRes(SRequestObj* pRequest, void* res) {
- if (NULL == pRequest || NULL == res) {
- return;
- }
-
- if (TDMT_VND_SUBMIT == pRequest->type) {
- tFreeSSubmitRsp((SSubmitRsp*)res);
- } else if (TDMT_VND_QUERY == pRequest->type) {
- taosArrayDestroy((SArray*)res);
- }
-}
-
SRequestObj* launchQueryImpl(SRequestObj* pRequest, SQuery* pQuery, int32_t code, bool keepQuery, void** res) {
- void* pRes = NULL;
-
if (TSDB_CODE_SUCCESS == code) {
switch (pQuery->execMode) {
case QUERY_EXEC_MODE_LOCAL:
@@ -508,10 +536,7 @@ SRequestObj* launchQueryImpl(SRequestObj* pRequest, SQuery* pQuery, int32_t code
SArray* pNodeList = NULL;
code = getPlan(pRequest, pQuery, &pRequest->body.pDag, &pNodeList);
if (TSDB_CODE_SUCCESS == code) {
- code = scheduleQuery(pRequest, pRequest->body.pDag, pNodeList, &pRes);
- if (NULL != pRes) {
- code = validateSversion(pRequest, pRes);
- }
+ code = scheduleQuery(pRequest, pRequest->body.pDag, pNodeList);
}
taosArrayDestroy(pNodeList);
break;
@@ -528,15 +553,15 @@ SRequestObj* launchQueryImpl(SRequestObj* pRequest, SQuery* pQuery, int32_t code
qDestroyQuery(pQuery);
}
+ handleExecRes(pRequest);
+
if (NULL != pRequest && TSDB_CODE_SUCCESS != code) {
pRequest->code = terrno;
}
if (res) {
- *res = pRes;
- } else {
- freeRequestRes(pRequest, pRes);
- pRes = NULL;
+ *res = pRequest->body.resInfo.execRes.res;
+ pRequest->body.resInfo.execRes.res = NULL;
}
return pRequest;
diff --git a/source/client/src/clientMsgHandler.c b/source/client/src/clientMsgHandler.c
index f15315fe60..9de3ee1d0f 100644
--- a/source/client/src/clientMsgHandler.c
+++ b/source/client/src/clientMsgHandler.c
@@ -223,10 +223,33 @@ int32_t processDropDbRsp(void* param, const SDataBuf* pMsg, int32_t code) {
return code;
}
+int32_t processAlterStbRsp(void* param, const SDataBuf* pMsg, int32_t code) {
+ SRequestObj* pRequest = param;
+ if (code != TSDB_CODE_SUCCESS) {
+ setErrno(pRequest, code);
+ tsem_post(&pRequest->body.rspSem);
+ return code;
+ }
+
+ SMAlterStbRsp alterRsp = {0};
+ SDecoder coder = {0};
+ tDecoderInit(&coder, pMsg->pData, pMsg->len);
+ tDecodeSMAlterStbRsp(&coder, &alterRsp);
+ tDecoderClear(&coder);
+
+ pRequest->body.resInfo.execRes.msgType = TDMT_MND_ALTER_STB;
+ pRequest->body.resInfo.execRes.res = alterRsp.pMeta;
+
+ tsem_post(&pRequest->body.rspSem);
+ return code;
+}
+
+
void initMsgHandleFp() {
handleRequestRspFp[TMSG_INDEX(TDMT_MND_CONNECT)] = processConnectRsp;
handleRequestRspFp[TMSG_INDEX(TDMT_MND_CREATE_DB)] = processCreateDbRsp;
handleRequestRspFp[TMSG_INDEX(TDMT_MND_USE_DB)] = processUseDbRsp;
handleRequestRspFp[TMSG_INDEX(TDMT_MND_CREATE_STB)] = processCreateTableRsp;
handleRequestRspFp[TMSG_INDEX(TDMT_MND_DROP_DB)] = processDropDbRsp;
+ handleRequestRspFp[TMSG_INDEX(TDMT_MND_ALTER_STB)] = processAlterStbRsp;
}
diff --git a/source/client/src/clientSml.c b/source/client/src/clientSml.c
index 7d623072d6..e77b9a9bd0 100644
--- a/source/client/src/clientSml.c
+++ b/source/client/src/clientSml.c
@@ -960,10 +960,10 @@ static int32_t smlParseInfluxString(const char* sql, SSmlLineInfo *elements, SSm
return TSDB_CODE_SML_INVALID_DATA;
}
elements->colsLen = sql - elements->cols;
- if(elements->colsLen == 0) {
- smlBuildInvalidDataMsg(msg, "cols is empty", NULL);
- return TSDB_CODE_SML_INVALID_DATA;
- }
+// if(elements->colsLen == 0) {
+// smlBuildInvalidDataMsg(msg, "cols is empty", NULL);
+// return TSDB_CODE_SML_INVALID_DATA;
+// }
// parse timestamp
JUMP_SPACE(sql)
@@ -1124,7 +1124,7 @@ static int32_t smlParseTelnetString(SSmlHandle *info, const char* sql, SSmlTable
}
static int32_t smlParseCols(const char* data, int32_t len, SArray *cols, char *childTableName, bool isTag, SHashObj *dumplicateKey, SSmlMsgBuf *msg){
- if(isTag && len == 0){
+ if(len == 0){
return TSDB_CODE_SUCCESS;
}
@@ -2318,6 +2318,28 @@ cleanup:
return code;
}
+static int32_t isSchemalessDb(SSmlHandle* info){
+ SName name;
+ tNameSetDbName(&name, info->taos->acctId, info->taos->db, strlen(info->taos->db));
+ char dbFname[TSDB_DB_FNAME_LEN] = {0};
+ tNameGetFullDbName(&name, dbFname);
+ SDbCfgInfo pInfo = {0};
+ SEpSet ep = getEpSet_s(&info->taos->pAppInfo->mgmtEp);
+
+ int32_t code = catalogGetDBCfg(info->pCatalog, info->taos->pAppInfo->pTransporter, &ep, dbFname, &pInfo);
+ if (code != TSDB_CODE_SUCCESS) {
+ info->pRequest->code = code;
+ smlBuildInvalidDataMsg(&info->msgBuf, "catalogGetDBCfg error, code:", tstrerror(code));
+ return code;
+ }
+ if (!pInfo.schemaless){
+ info->pRequest->code = TSDB_CODE_SML_INVALID_DB_CONF;
+ smlBuildInvalidDataMsg(&info->msgBuf, "can not insert into schemaless db:", dbFname);
+ return TSDB_CODE_SML_INVALID_DB_CONF;
+ }
+ return TSDB_CODE_SUCCESS;
+}
+
/**
* taos_schemaless_insert() parse and insert data points into database according to
* different protocol.
@@ -2351,6 +2373,19 @@ TAOS_RES* taos_schemaless_insert(TAOS* taos, char* lines[], int numLines, int pr
return (TAOS_RES*)request;
}
+ info->taos->schemalessType = 1;
+ if(request->pDb == NULL){
+ request->code = TSDB_CODE_PAR_DB_NOT_SPECIFIED;
+ smlBuildInvalidDataMsg(&info->msgBuf, "Database not specified", NULL);
+ goto end;
+ }
+
+ if(isSchemalessDb(info) != TSDB_CODE_SUCCESS){
+ request->code = TSDB_CODE_SML_INVALID_DB_CONF;
+ smlBuildInvalidDataMsg(&info->msgBuf, "Cannot write data to a non schemaless database", NULL);
+ goto end;
+ }
+
if (!lines) {
request->code = TSDB_CODE_SML_INVALID_DATA;
smlBuildInvalidDataMsg(&info->msgBuf, "lines is null", NULL);
@@ -2372,6 +2407,7 @@ TAOS_RES* taos_schemaless_insert(TAOS* taos, char* lines[], int numLines, int pr
info->pRequest->code = smlProcess(info, lines, numLines);
end:
+ uDebug("result:%s", info->msgBuf.buf);
smlDestroyInfo(info);
return (TAOS_RES*)request;
}
diff --git a/source/client/src/tmq.c b/source/client/src/tmq.c
index 416d1a6f26..c2170631c2 100644
--- a/source/client/src/tmq.c
+++ b/source/client/src/tmq.c
@@ -143,6 +143,7 @@ typedef struct {
typedef struct {
// subscribe info
char* topicName;
+ char db[TSDB_DB_FNAME_LEN];
SArray* vgs; // SArray
@@ -1039,6 +1040,7 @@ bool tmqUpdateEp(tmq_t* tmq, int32_t epoch, SMqAskEpRsp* pRsp) {
topic.schema = pTopicEp->schema;
taosHashClear(pHash);
topic.topicName = strdup(pTopicEp->topic);
+ tstrncpy(topic.db, pTopicEp->db, TSDB_DB_FNAME_LEN);
tscDebug("consumer %ld update topic: %s", tmq->consumerId, topic.topicName);
int32_t topicNumCur = taosArrayGetSize(tmq->clientTopics);
@@ -1283,7 +1285,8 @@ SMqPollReq* tmqBuildConsumeReqImpl(tmq_t* tmq, int64_t timeout, SMqClientTopic*
SMqRspObj* tmqBuildRspFromWrapper(SMqPollRspWrapper* pWrapper) {
SMqRspObj* pRspObj = taosMemoryCalloc(1, sizeof(SMqRspObj));
pRspObj->resType = RES_TYPE__TMQ;
- strncpy(pRspObj->topic, pWrapper->topicHandle->topicName, TSDB_TOPIC_FNAME_LEN);
+ tstrncpy(pRspObj->topic, pWrapper->topicHandle->topicName, TSDB_TOPIC_FNAME_LEN);
+ tstrncpy(pRspObj->db, pWrapper->topicHandle->db, TSDB_DB_FNAME_LEN);
pRspObj->vgId = pWrapper->vgHandle->vgId;
pRspObj->resIter = -1;
memcpy(&pRspObj->rsp, &pWrapper->msg, sizeof(SMqDataBlkRsp));
@@ -1506,6 +1509,15 @@ const char* tmq_get_topic_name(TAOS_RES* res) {
}
}
+const char* tmq_get_db_name(TAOS_RES* res) {
+ if (TD_RES_TMQ(res)) {
+ SMqRspObj* pRspObj = (SMqRspObj*)res;
+ return strchr(pRspObj->db, '.') + 1;
+ } else {
+ return NULL;
+ }
+}
+
int32_t tmq_get_vgroup_id(TAOS_RES* res) {
if (TD_RES_TMQ(res)) {
SMqRspObj* pRspObj = (SMqRspObj*)res;
diff --git a/source/client/test/clientTests.cpp b/source/client/test/clientTests.cpp
index b5b6ea65e0..914e5aefc2 100644
--- a/source/client/test/clientTests.cpp
+++ b/source/client/test/clientTests.cpp
@@ -567,6 +567,7 @@ TEST(testCase, insert_test) {
taos_free_result(pRes);
taos_close(pConn);
}
+#endif
TEST(testCase, projection_query_tables) {
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
@@ -625,23 +626,23 @@ TEST(testCase, projection_query_tables) {
printf("start to insert next table\n");
- for(int32_t i = 0; i < 1000000; i += 20) {
- char sql[1024] = {0};
- sprintf(sql,
- "insert into tu2 values(now+%da, %d)(now+%da, %d)(now+%da, %d)(now+%da, %d)"
- "(now+%da, %d)(now+%da, %d)(now+%da, %d)(now+%da, %d)(now+%da, %d)(now+%da, %d)"
- "(now+%da, %d)(now+%da, %d)(now+%da, %d)(now+%da, %d)"
- "(now+%da, %d)(now+%da, %d)(now+%da, %d)(now+%da, %d)(now+%da, %d)(now+%da, %d)",
- i, i, i + 1, i + 1, i + 2, i + 2, i + 3, i + 3, i + 4, i + 4, i + 5, i + 5, i + 6, i + 6, i + 7, i + 7,
- i + 8, i + 8, i + 9, i + 9, i + 10, i + 10, i + 11, i + 11, i + 12, i + 12, i + 13, i + 13, i + 14, i + 14,
- i + 15, i + 15, i + 16, i + 16, i + 17, i + 17, i + 18, i + 18, i + 19, i + 19);
- TAOS_RES* p = taos_query(pConn, sql);
- if (taos_errno(p) != 0) {
- printf("failed to insert data, reason:%s\n", taos_errstr(p));
- }
-
- taos_free_result(p);
- }
+// for(int32_t i = 0; i < 1000000; i += 20) {
+// char sql[1024] = {0};
+// sprintf(sql,
+// "insert into tu2 values(now+%da, %d)(now+%da, %d)(now+%da, %d)(now+%da, %d)"
+// "(now+%da, %d)(now+%da, %d)(now+%da, %d)(now+%da, %d)(now+%da, %d)(now+%da, %d)"
+// "(now+%da, %d)(now+%da, %d)(now+%da, %d)(now+%da, %d)"
+// "(now+%da, %d)(now+%da, %d)(now+%da, %d)(now+%da, %d)(now+%da, %d)(now+%da, %d)",
+// i, i, i + 1, i + 1, i + 2, i + 2, i + 3, i + 3, i + 4, i + 4, i + 5, i + 5, i + 6, i + 6, i + 7, i + 7,
+// i + 8, i + 8, i + 9, i + 9, i + 10, i + 10, i + 11, i + 11, i + 12, i + 12, i + 13, i + 13, i + 14, i + 14,
+// i + 15, i + 15, i + 16, i + 16, i + 17, i + 17, i + 18, i + 18, i + 19, i + 19);
+// TAOS_RES* p = taos_query(pConn, sql);
+// if (taos_errno(p) != 0) {
+// printf("failed to insert data, reason:%s\n", taos_errstr(p));
+// }
+//
+// taos_free_result(p);
+// }
// pRes = taos_query(pConn, "select * from tu");
// if (taos_errno(pRes) != 0) {
@@ -663,7 +664,7 @@ TEST(testCase, projection_query_tables) {
// taos_free_result(pRes);
taos_close(pConn);
}
-
+#if 0
TEST(testCase, projection_query_stables) {
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
ASSERT_NE(pConn, nullptr);
@@ -692,8 +693,6 @@ TEST(testCase, projection_query_stables) {
taos_close(pConn);
}
-#endif
-
TEST(testCase, agg_query_tables) {
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
ASSERT_NE(pConn, nullptr);
@@ -734,5 +733,6 @@ TEST(testCase, agg_query_tables) {
taos_free_result(pRes);
taos_close(pConn);
}
+#endif
#pragma GCC diagnostic pop
diff --git a/source/client/test/smlTest.cpp b/source/client/test/smlTest.cpp
index 217699e360..4684df8418 100644
--- a/source/client/test/smlTest.cpp
+++ b/source/client/test/smlTest.cpp
@@ -1258,4 +1258,26 @@ TEST(testCase, sml_TD15742_Test) {
destroyRequest(request);
smlDestroyInfo(info);
-}
\ No newline at end of file
+}
+
+TEST(testCase, sml_params_Test) {
+ TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0);
+ ASSERT_NE(taos, nullptr);
+
+ TAOS_RES* pRes = taos_query(taos, "create database if not exists param");
+ taos_free_result(pRes);
+
+ const char *sql[] = {
+ "test_ms,t0=t c0=f 1626006833641",
+ };
+ TAOS_RES* res = taos_schemaless_insert(taos, (char**)sql, 1, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_MILLI_SECONDS);
+ ASSERT_EQ(taos_errno(res), TSDB_CODE_PAR_DB_NOT_SPECIFIED);
+ taos_free_result(pRes);
+
+ pRes = taos_query(taos, "use param");
+ taos_free_result(pRes);
+
+ res = taos_schemaless_insert(taos, (char**)sql, 1, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_MILLI_SECONDS);
+ ASSERT_EQ(taos_errno(res), TSDB_CODE_SML_INVALID_DB_CONF);
+ taos_free_result(pRes);
+}
diff --git a/source/common/src/systable.c b/source/common/src/systable.c
index 8207ffb22f..948b50c01a 100644
--- a/source/common/src/systable.c
+++ b/source/common/src/systable.c
@@ -36,6 +36,7 @@ static const SSysDbTableSchema mnodesSchema[] = {
{.name = "id", .bytes = 4, .type = TSDB_DATA_TYPE_INT},
{.name = "endpoint", .bytes = TSDB_EP_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
{.name = "role", .bytes = 12 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
+ {.name = "status", .bytes = 9 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
{.name = "create_time", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP},
};
@@ -90,6 +91,8 @@ static const SSysDbTableSchema userDBSchema[] = {
{.name = "precision", .bytes = 2 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
{.name = "single_stable", .bytes = 1, .type = TSDB_DATA_TYPE_TINYINT},
{.name = "status", .bytes = 10 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
+ {.name = "schemaless", .bytes = 1, .type = TSDB_DATA_TYPE_TINYINT},
+
// {.name = "update", .bytes = 1, .type = TSDB_DATA_TYPE_TINYINT}, // disable update
};
diff --git a/source/common/src/tdatablock.c b/source/common/src/tdatablock.c
index 9d16de43b3..f77b823f3c 100644
--- a/source/common/src/tdatablock.c
+++ b/source/common/src/tdatablock.c
@@ -355,14 +355,19 @@ int32_t blockDataUpdateTsWindow(SSDataBlock* pDataBlock, int32_t tsColumnIndex)
return -1;
}
- int32_t index = (tsColumnIndex == -1) ? 0 : tsColumnIndex;
+ int32_t index = (tsColumnIndex == -1) ? 0 : tsColumnIndex;
+
SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, index);
if (pColInfoData->info.type != TSDB_DATA_TYPE_TIMESTAMP) {
return 0;
}
- pDataBlock->info.window.skey = *(TSKEY*)colDataGetData(pColInfoData, 0);
- pDataBlock->info.window.ekey = *(TSKEY*)colDataGetData(pColInfoData, (pDataBlock->info.rows - 1));
+ TSKEY skey = *(TSKEY*)colDataGetData(pColInfoData, 0);
+ TSKEY ekey = *(TSKEY*)colDataGetData(pColInfoData, (pDataBlock->info.rows - 1));
+
+ pDataBlock->info.window.skey = TMIN(skey, ekey);
+ pDataBlock->info.window.ekey = TMAX(skey, ekey);
+
return 0;
}
@@ -1273,25 +1278,39 @@ static void doShiftBitmap(char* nullBitmap, size_t n, size_t total) {
memmove(nullBitmap, nullBitmap + n / 8, newLen);
} else {
int32_t tail = n % 8;
- int32_t i = 0;
-
+ int32_t i = 0;
uint8_t* p = (uint8_t*)nullBitmap;
- while (i < len) {
- uint8_t v = p[i];
- p[i] = 0;
- p[i] = (v << tail);
+ if (n < 8) {
+ while (i < len) {
+ uint8_t v = p[i]; // source bitmap value
+ p[i] = (v << tail);
- if (i < len - 1) {
- uint8_t next = p[i + 1];
- p[i] |= (next >> (8 - tail));
+ if (i < len - 1) {
+ uint8_t next = p[i + 1];
+ p[i] |= (next >> (8 - tail));
+ }
+
+ i += 1;
}
+ } else if (n > 8) {
+ int32_t gap = len - newLen;
+ while(i < newLen) {
+ uint8_t v = p[i + gap];
+ p[i] = (v << tail);
- i += 1;
+ if (i < newLen - 1) {
+ uint8_t next = p[i + gap + 1];
+ p[i] |= (next >> (8 - tail));
+ }
+
+ i += 1;
+ }
}
}
}
+
static void colDataTrimFirstNRows(SColumnInfoData* pColInfoData, size_t n, size_t total) {
if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
memmove(pColInfoData->varmeta.offset, &pColInfoData->varmeta.offset[n], (total - n) * sizeof(int32_t));
@@ -1803,3 +1822,99 @@ SSubmitReq* tdBlockToSubmit(const SArray* pBlocks, const STSchema* pTSchema, boo
taosArrayDestroy(tagArray);
return ret;
}
+
+void blockCompressEncode(const SSDataBlock* pBlock, char* data, int32_t* dataLen, int32_t numOfCols, int8_t needCompress) {
+ int32_t* actualLen = (int32_t*)data;
+ data += sizeof(int32_t);
+
+ uint64_t* groupId = (uint64_t*)data;
+ data += sizeof(uint64_t);
+
+ int32_t* colSizes = (int32_t*)data;
+ data += numOfCols * sizeof(int32_t);
+
+ *dataLen = (numOfCols * sizeof(int32_t) + sizeof(uint64_t) + sizeof(int32_t));
+
+ int32_t numOfRows = pBlock->info.rows;
+ for (int32_t col = 0; col < numOfCols; ++col) {
+ SColumnInfoData* pColRes = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, col);
+
+ // copy the null bitmap
+ if (IS_VAR_DATA_TYPE(pColRes->info.type)) {
+ size_t metaSize = numOfRows * sizeof(int32_t);
+ memcpy(data, pColRes->varmeta.offset, metaSize);
+ data += metaSize;
+ (*dataLen) += metaSize;
+ } else {
+ int32_t len = BitmapLen(numOfRows);
+ memcpy(data, pColRes->nullbitmap, len);
+ data += len;
+ (*dataLen) += len;
+ }
+
+ if (needCompress) {
+ colSizes[col] = blockCompressColData(pColRes, numOfRows, data, needCompress);
+ data += colSizes[col];
+ (*dataLen) += colSizes[col];
+ } else {
+ colSizes[col] = colDataGetLength(pColRes, numOfRows);
+ (*dataLen) += colSizes[col];
+ memmove(data, pColRes->pData, colSizes[col]);
+ data += colSizes[col];
+ }
+
+ colSizes[col] = htonl(colSizes[col]);
+ }
+
+ *actualLen = *dataLen;
+ *groupId = pBlock->info.groupId;
+}
+
+const char* blockCompressDecode(SSDataBlock* pBlock, int32_t numOfCols, int32_t numOfRows, const char* pData) {
+ blockDataEnsureCapacity(pBlock, numOfRows);
+ const char* pStart = pData;
+
+ int32_t dataLen = *(int32_t*)pStart;
+ pStart += sizeof(int32_t);
+
+ pBlock->info.groupId = *(uint64_t*)pStart;
+ pStart += sizeof(uint64_t);
+
+ int32_t* colLen = (int32_t*)pStart;
+ pStart += sizeof(int32_t) * numOfCols;
+
+ for (int32_t i = 0; i < numOfCols; ++i) {
+ colLen[i] = htonl(colLen[i]);
+ ASSERT(colLen[i] >= 0);
+
+ SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
+ if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
+ pColInfoData->varmeta.length = colLen[i];
+ pColInfoData->varmeta.allocLen = colLen[i];
+
+ memcpy(pColInfoData->varmeta.offset, pStart, sizeof(int32_t) * numOfRows);
+ pStart += sizeof(int32_t) * numOfRows;
+
+ if (colLen[i] > 0) {
+ taosMemoryFreeClear(pColInfoData->pData);
+ pColInfoData->pData = taosMemoryMalloc(colLen[i]);
+ }
+ } else {
+ memcpy(pColInfoData->nullbitmap, pStart, BitmapLen(numOfRows));
+ pStart += BitmapLen(numOfRows);
+ }
+
+ if (colLen[i] > 0) {
+ memcpy(pColInfoData->pData, pStart, colLen[i]);
+ }
+
+ // TODO
+ // setting this flag to true temporarily so aggregate function on stable will
+ // examine NULL value for non-primary key column
+ pColInfoData->hasNull = true;
+ pStart += colLen[i];
+ }
+
+ ASSERT(pStart - pData == dataLen);
+ return pStart;
+}
\ No newline at end of file
diff --git a/source/common/src/tdataformat.c b/source/common/src/tdataformat.c
index c66ff290cf..65daee6508 100644
--- a/source/common/src/tdataformat.c
+++ b/source/common/src/tdataformat.c
@@ -1008,6 +1008,21 @@ void debugPrintSTag(STag *pTag, const char *tag, int32_t ln) {
printf("\n");
}
+void debugCheckTags(STag *pTag) {
+ switch (pTag->flags) {
+ case 0x0:
+ case 0x20:
+ case 0x40:
+ case 0x60:
+ break;
+ default:
+ ASSERT(0);
+ }
+
+ ASSERT(pTag->nTag <= 128 && pTag->nTag >= 0);
+ ASSERT(pTag->ver <= 512 && pTag->ver >= 0); // temp condition for pTag->ver
+}
+
static int32_t tPutTagVal(uint8_t *p, STagVal *pTagVal, int8_t isJson) {
int32_t n = 0;
@@ -1114,9 +1129,11 @@ int32_t tTagNew(SArray *pArray, int32_t version, int8_t isJson, STag **ppTag) {
}
n += tPutTagVal(p + n, (STagVal *)taosArrayGet(pArray, iTag), isJson);
}
-
+#ifdef TD_DEBUG_PRINT_TAG
debugPrintSTag(*ppTag, __func__, __LINE__);
+#endif
+ debugCheckTags(*ppTag); // TODO: remove this line after debug
return code;
_err:
@@ -1199,8 +1216,7 @@ int32_t tEncodeTag(SEncoder *pEncoder, const STag *pTag) {
}
int32_t tDecodeTag(SDecoder *pDecoder, STag **ppTag) {
- uint32_t len = 0;
- return tDecodeBinary(pDecoder, (uint8_t **)ppTag, &len);
+ return tDecodeBinary(pDecoder, (uint8_t **)ppTag, NULL);
}
int32_t tTagToValArray(const STag *pTag, SArray **ppArray) {
diff --git a/source/common/src/tglobal.c b/source/common/src/tglobal.c
index 141ec4f03b..e77c462e5a 100644
--- a/source/common/src/tglobal.c
+++ b/source/common/src/tglobal.c
@@ -109,8 +109,11 @@ int32_t tsCompressColData = -1;
*/
int32_t tsCompatibleModel = 1;
+// count/hyperloglog function always return values in case of all NULL data or Empty data set.
+int32_t tsCountAlwaysReturnValue = 1;
+
// 10 ms for sliding time, the value will changed in case of time precision changed
-int32_t tsMinSlidingTime = 10;
+int32_t tsMinSlidingTime = 10;
// the maxinum number of distict query result
int32_t tsMaxNumOfDistinctResults = 1000 * 10000;
@@ -130,7 +133,6 @@ int32_t tsRetryStreamCompDelay = 10 * 1000;
// The delayed computing ration. 10% of the whole computing time window by default.
float tsStreamComputDelayRatio = 0.1f;
-int32_t tsProjectExecInterval = 10000; // every 10sec, the projection will be executed once
int64_t tsMaxRetentWindow = 24 * 3600L; // maximum time window tolerance
// the maximum allowed query buffer size during query processing for each data node.
@@ -374,6 +376,7 @@ static int32_t taosAddServerCfg(SConfig *pCfg) {
if (cfgAddInt32(pCfg, "minSlidingTime", tsMinSlidingTime, 10, 1000000, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "minIntervalTime", tsMinIntervalTime, 1, 1000000, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "maxNumOfDistinctRes", tsMaxNumOfDistinctResults, 10 * 10000, 10000 * 10000, 0) != 0) return -1;
+ if (cfgAddInt32(pCfg, "countAlwaysReturnValue", tsCountAlwaysReturnValue, 0, 1, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "maxStreamCompDelay", tsMaxStreamComputDelay, 10, 1000000000, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "maxFirstStreamCompDelay", tsStreamCompStartDelay, 1000, 1000000000, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "retryStreamCompDelay", tsRetryStreamCompDelay, 10, 1000000000, 0) != 0) return -1;
@@ -567,6 +570,7 @@ static int32_t taosSetServerCfg(SConfig *pCfg) {
tsMinSlidingTime = cfgGetItem(pCfg, "minSlidingTime")->i32;
tsMinIntervalTime = cfgGetItem(pCfg, "minIntervalTime")->i32;
tsMaxNumOfDistinctResults = cfgGetItem(pCfg, "maxNumOfDistinctRes")->i32;
+ tsCountAlwaysReturnValue = cfgGetItem(pCfg, "countAlwaysReturnValue")->i32;
tsMaxStreamComputDelay = cfgGetItem(pCfg, "maxStreamCompDelay")->i32;
tsStreamCompStartDelay = cfgGetItem(pCfg, "maxFirstStreamCompDelay")->i32;
tsRetryStreamCompDelay = cfgGetItem(pCfg, "retryStreamCompDelay")->i32;
diff --git a/source/common/src/tmsg.c b/source/common/src/tmsg.c
index 2962216b0c..9c6c532bcd 100644
--- a/source/common/src/tmsg.c
+++ b/source/common/src/tmsg.c
@@ -693,6 +693,7 @@ void tFreeSMAltertbReq(SMAlterStbReq *pReq) {
pReq->pFields = NULL;
}
+
int32_t tSerializeSEpSet(void *buf, int32_t bufLen, const SEpSet *pEpset) {
SEncoder encoder = {0};
tEncoderInit(&encoder, buf, bufLen);
@@ -2277,6 +2278,7 @@ int32_t tSerializeSDbCfgRsp(void *buf, int32_t bufLen, const SDbCfgRsp *pRsp) {
if (tEncodeI8(&encoder, pRetension->freqUnit) < 0) return -1;
if (tEncodeI8(&encoder, pRetension->keepUnit) < 0) return -1;
}
+ if (tEncodeI8(&encoder, pRsp->schemaless) < 0) return -1;
tEndEncode(&encoder);
int32_t tlen = encoder.pos;
@@ -2325,6 +2327,7 @@ int32_t tDeserializeSDbCfgRsp(void *buf, int32_t bufLen, SDbCfgRsp *pRsp) {
return -1;
}
}
+ if (tDecodeI8(&decoder, &pRsp->schemaless) < 0) return -1;
tEndDecode(&decoder);
tDecoderClear(&decoder);
@@ -4347,13 +4350,96 @@ int32_t tDecodeSVAlterTbReq(SDecoder *pDecoder, SVAlterTbReq *pReq) {
int32_t tEncodeSVAlterTbRsp(SEncoder *pEncoder, const SVAlterTbRsp *pRsp) {
if (tStartEncode(pEncoder) < 0) return -1;
if (tEncodeI32(pEncoder, pRsp->code) < 0) return -1;
+ if (tEncodeI32(pEncoder, pRsp->pMeta ? 1 : 0) < 0) return -1;
+ if (pRsp->pMeta) {
+ if (tEncodeSTableMetaRsp(pEncoder, pRsp->pMeta) < 0) return -1;
+ }
tEndEncode(pEncoder);
return 0;
}
int32_t tDecodeSVAlterTbRsp(SDecoder *pDecoder, SVAlterTbRsp *pRsp) {
+ int32_t meta = 0;
if (tStartDecode(pDecoder) < 0) return -1;
if (tDecodeI32(pDecoder, &pRsp->code) < 0) return -1;
+ if (tDecodeI32(pDecoder, &meta) < 0) return -1;
+ if (meta) {
+ pRsp->pMeta = taosMemoryCalloc(1, sizeof(STableMetaRsp));
+ if (NULL == pRsp->pMeta) return -1;
+ if (tDecodeSTableMetaRsp(pDecoder, pRsp->pMeta) < 0) return -1;
+ }
tEndDecode(pDecoder);
return 0;
}
+
+int32_t tDeserializeSVAlterTbRsp(void *buf, int32_t bufLen, SVAlterTbRsp *pRsp) {
+ int32_t meta = 0;
+ SDecoder decoder = {0};
+ tDecoderInit(&decoder, buf, bufLen);
+
+ if (tStartDecode(&decoder) < 0) return -1;
+ if (tDecodeI32(&decoder, &pRsp->code) < 0) return -1;
+ if (tDecodeI32(&decoder, &meta) < 0) return -1;
+ if (meta) {
+ pRsp->pMeta = taosMemoryCalloc(1, sizeof(STableMetaRsp));
+ if (NULL == pRsp->pMeta) return -1;
+ if (tDecodeSTableMetaRsp(&decoder, pRsp->pMeta) < 0) return -1;
+ }
+ tEndDecode(&decoder);
+ tDecoderClear(&decoder);
+ return 0;
+}
+
+int32_t tEncodeSMAlterStbRsp(SEncoder *pEncoder, const SMAlterStbRsp *pRsp) {
+ if (tStartEncode(pEncoder) < 0) return -1;
+ if (tEncodeI32(pEncoder, pRsp->pMeta->pSchemas ? 1 : 0) < 0) return -1;
+ if (pRsp->pMeta->pSchemas) {
+ if (tEncodeSTableMetaRsp(pEncoder, pRsp->pMeta) < 0) return -1;
+ }
+ tEndEncode(pEncoder);
+ return 0;
+}
+
+int32_t tDecodeSMAlterStbRsp(SDecoder *pDecoder, SMAlterStbRsp *pRsp) {
+ int32_t meta = 0;
+ if (tStartDecode(pDecoder) < 0) return -1;
+ if (tDecodeI32(pDecoder, &meta) < 0) return -1;
+ if (meta) {
+ pRsp->pMeta = taosMemoryCalloc(1, sizeof(STableMetaRsp));
+ if (NULL == pRsp->pMeta) return -1;
+ if (tDecodeSTableMetaRsp(pDecoder, pRsp->pMeta) < 0) return -1;
+ }
+ tEndDecode(pDecoder);
+ return 0;
+}
+
+int32_t tDeserializeSMAlterStbRsp(void *buf, int32_t bufLen, SMAlterStbRsp *pRsp) {
+ int32_t meta = 0;
+ SDecoder decoder = {0};
+ tDecoderInit(&decoder, buf, bufLen);
+
+ if (tStartDecode(&decoder) < 0) return -1;
+ if (tDecodeI32(&decoder, &meta) < 0) return -1;
+ if (meta) {
+ pRsp->pMeta = taosMemoryCalloc(1, sizeof(STableMetaRsp));
+ if (NULL == pRsp->pMeta) return -1;
+ if (tDecodeSTableMetaRsp(&decoder, pRsp->pMeta) < 0) return -1;
+ }
+ tEndDecode(&decoder);
+ tDecoderClear(&decoder);
+ return 0;
+}
+
+void tFreeSMAlterStbRsp(SMAlterStbRsp* pRsp) {
+ if (NULL == pRsp) {
+ return;
+ }
+
+ if (pRsp->pMeta) {
+ taosMemoryFree(pRsp->pMeta->pSchemas);
+ taosMemoryFree(pRsp->pMeta);
+ }
+}
+
+
+
diff --git a/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c b/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c
index 018d7a607c..819d6b3657 100644
--- a/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c
+++ b/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c
@@ -180,6 +180,24 @@ static void vmGenerateWrapperCfg(SVnodeMgmt *pMgmt, SCreateVnodeReq *pCreate, SW
snprintf(pCfg->path, sizeof(pCfg->path), "%s%svnode%d", pMgmt->path, TD_DIRSEP, pCreate->vgId);
}
+static int32_t vmTsmaAdjustDays(SVnodeCfg *pCfg, SCreateVnodeReq *pReq) {
+ if (pReq->isTsma) {
+ SMsgHead *smaMsg = pReq->pTsma;
+ uint32_t contLen = (uint32_t)(htonl(smaMsg->contLen) - sizeof(SMsgHead));
+ return smaGetTSmaDays(pCfg, POINTER_SHIFT(smaMsg, sizeof(SMsgHead)), contLen, &pCfg->tsdbCfg.days);
+ }
+ return 0;
+}
+
+static int32_t vmTsmaProcessCreate(SVnode *pVnode, SCreateVnodeReq *pReq) {
+ if (pReq->isTsma) {
+ SMsgHead *smaMsg = pReq->pTsma;
+ uint32_t contLen = (uint32_t)(htonl(smaMsg->contLen) - sizeof(SMsgHead));
+ return vnodeProcessCreateTSma(pVnode, POINTER_SHIFT(smaMsg, sizeof(SMsgHead)), contLen);
+ }
+ return 0;
+}
+
int32_t vmProcessCreateVnodeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
SCreateVnodeReq createReq = {0};
SVnodeCfg vnodeCfg = {0};
@@ -195,6 +213,13 @@ int32_t vmProcessCreateVnodeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
dDebug("vgId:%d, create vnode req is received, tsma:%d standby:%d", createReq.vgId, createReq.isTsma,
createReq.standby);
vmGenerateVnodeCfg(&createReq, &vnodeCfg);
+
+ if (vmTsmaAdjustDays(&vnodeCfg, &createReq) < 0) {
+ dError("vgId:%d, failed to adjust tsma days since %s", createReq.vgId, terrstr());
+ code = terrno;
+ goto _OVER;
+ }
+
vmGenerateWrapperCfg(pMgmt, &createReq, &wrapperCfg);
SVnodeObj *pVnode = vmAcquireVnode(pMgmt, createReq.vgId);
@@ -203,14 +228,16 @@ int32_t vmProcessCreateVnodeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
tFreeSCreateVnodeReq(&createReq);
vmReleaseVnode(pMgmt, pVnode);
terrno = TSDB_CODE_NODE_ALREADY_DEPLOYED;
- return -1;
+ code = terrno;
+ goto _OVER;
}
snprintf(path, TSDB_FILENAME_LEN, "vnode%svnode%d", TD_DIRSEP, vnodeCfg.vgId);
if (vnodeCreate(path, &vnodeCfg, pMgmt->pTfs) < 0) {
tFreeSCreateVnodeReq(&createReq);
dError("vgId:%d, failed to create vnode since %s", createReq.vgId, terrstr());
- return -1;
+ code = terrno;
+ goto _OVER;
}
SVnode *pImpl = vnodeOpen(path, pMgmt->pTfs, pMgmt->msgCb);
@@ -227,14 +254,11 @@ int32_t vmProcessCreateVnodeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
goto _OVER;
}
- if (createReq.isTsma) {
- SMsgHead *smaMsg = createReq.pTsma;
- uint32_t contLen = (uint32_t)(htonl(smaMsg->contLen) - sizeof(SMsgHead));
- if (vnodeProcessCreateTSma(pImpl, POINTER_SHIFT(smaMsg, sizeof(SMsgHead)), contLen) < 0) {
- dError("vgId:%d, failed to create tsma since %s", createReq.vgId, terrstr());
- code = terrno;
- goto _OVER;
- };
+ code = vmTsmaProcessCreate(pImpl, &createReq);
+ if (code != 0) {
+ dError("vgId:%d, failed to create tsma since %s", createReq.vgId, terrstr());
+ code = terrno;
+ goto _OVER;
}
code = vnodeStart(pImpl);
diff --git a/source/dnode/mnode/impl/inc/mndDef.h b/source/dnode/mnode/impl/inc/mndDef.h
index d0c737ae5a..83a36f4b0d 100644
--- a/source/dnode/mnode/impl/inc/mndDef.h
+++ b/source/dnode/mnode/impl/inc/mndDef.h
@@ -168,7 +168,7 @@ typedef struct {
int64_t createdTime;
int64_t updateTime;
SDnodeObj* pDnode;
- SQnodeLoad load;
+ SQnodeLoad load;
} SQnodeObj;
typedef struct {
@@ -255,6 +255,7 @@ typedef struct {
int8_t hashMethod; // default is 1
int32_t numOfRetensions;
SArray* pRetensions;
+ int8_t schemaless;
} SDbCfg;
typedef struct {
@@ -403,26 +404,22 @@ int32_t tEncodeSMqOffsetObj(void** buf, const SMqOffsetObj* pOffset);
void* tDecodeSMqOffsetObj(void* buf, SMqOffsetObj* pOffset);
typedef struct {
- char name[TSDB_TOPIC_FNAME_LEN];
- char db[TSDB_DB_FNAME_LEN];
- int64_t createTime;
- int64_t updateTime;
- int64_t uid;
- int64_t dbUid;
- int32_t version;
- int8_t subType; // column, db or stable
- // int8_t withTbName;
- // int8_t withSchema;
- // int8_t withTag;
+ char name[TSDB_TOPIC_FNAME_LEN];
+ char db[TSDB_DB_FNAME_LEN];
+ int64_t createTime;
+ int64_t updateTime;
+ int64_t uid;
+ int64_t dbUid;
+ int32_t version;
+ int8_t subType; // column, db or stable
SRWLatch lock;
- int32_t consumerCnt;
int32_t sqlLen;
int32_t astLen;
char* sql;
char* ast;
char* physicalPlan;
SSchemaWrapper schema;
- // int32_t refConsumerCnt;
+ int64_t stbUid;
} SMqTopicObj;
typedef struct {
@@ -476,14 +473,12 @@ int32_t tEncodeSMqConsumerEp(void** buf, const SMqConsumerEp* pEp);
void* tDecodeSMqConsumerEp(const void* buf, SMqConsumerEp* pEp);
typedef struct {
- char key[TSDB_SUBSCRIBE_KEY_LEN];
- SRWLatch lock;
- int64_t dbUid;
- int32_t vgNum;
- int8_t subType;
- // int8_t withTbName;
- // int8_t withSchema;
- // int8_t withTag;
+ char key[TSDB_SUBSCRIBE_KEY_LEN];
+ SRWLatch lock;
+ int64_t dbUid;
+ int32_t vgNum;
+ int8_t subType;
+ int64_t stbUid;
SHashObj* consumerHash; // consumerId -> SMqConsumerEp
SArray* unassignedVgs; // SArray
} SMqSubscribeObj;
@@ -535,7 +530,7 @@ typedef struct {
} SMqRebOutputObj;
typedef struct {
- char name[TSDB_TOPIC_FNAME_LEN];
+ char name[TSDB_STREAM_FNAME_LEN];
char sourceDb[TSDB_DB_FNAME_LEN];
char targetDb[TSDB_DB_FNAME_LEN];
char targetSTbName[TSDB_TABLE_FNAME_LEN];
diff --git a/source/dnode/mnode/impl/inc/mndTopic.h b/source/dnode/mnode/impl/inc/mndTopic.h
index c5c4800e02..4aa18ea591 100644
--- a/source/dnode/mnode/impl/inc/mndTopic.h
+++ b/source/dnode/mnode/impl/inc/mndTopic.h
@@ -37,6 +37,8 @@ const char *mndTopicGetShowName(const char topic[TSDB_TOPIC_FNAME_LEN]);
int32_t mndSetTopicCommitLogs(SMnode *pMnode, STrans *pTrans, SMqTopicObj *pTopic);
+bool mndCheckColAndTagModifiable(SMnode *pMnode, int64_t suid, const SArray *colIds);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/dnode/mnode/impl/src/mndConsumer.c b/source/dnode/mnode/impl/src/mndConsumer.c
index 0314891d59..1f8bf06993 100644
--- a/source/dnode/mnode/impl/src/mndConsumer.c
+++ b/source/dnode/mnode/impl/src/mndConsumer.c
@@ -306,6 +306,7 @@ static int32_t mndProcessAskEpReq(SRpcMsg *pMsg) {
SMqTopicObj *pTopic = mndAcquireTopic(pMnode, topic);
ASSERT(pTopic);
taosRLockLatch(&pTopic->lock);
+ tstrncpy(topicEp.db, pTopic->db, TSDB_DB_FNAME_LEN);
topicEp.schema.nCols = pTopic->schema.nCols;
if (topicEp.schema.nCols) {
topicEp.schema.pSchema = taosMemoryCalloc(topicEp.schema.nCols, sizeof(SSchema));
diff --git a/source/dnode/mnode/impl/src/mndDb.c b/source/dnode/mnode/impl/src/mndDb.c
index c062a2c552..6d7a638c30 100644
--- a/source/dnode/mnode/impl/src/mndDb.c
+++ b/source/dnode/mnode/impl/src/mndDb.c
@@ -115,6 +115,7 @@ static SSdbRaw *mndDbActionEncode(SDbObj *pDb) {
SDB_SET_INT8(pRaw, dataPos, pRetension->freqUnit, _OVER)
SDB_SET_INT8(pRaw, dataPos, pRetension->keepUnit, _OVER)
}
+ SDB_SET_INT8(pRaw, dataPos, pDb->cfg.schemaless, _OVER)
SDB_SET_RESERVE(pRaw, dataPos, DB_RESERVE_SIZE, _OVER)
SDB_SET_DATALEN(pRaw, dataPos, _OVER)
@@ -192,6 +193,7 @@ static SSdbRow *mndDbActionDecode(SSdbRaw *pRaw) {
}
}
}
+ SDB_GET_INT8(pRaw, dataPos, &pDb->cfg.schemaless, _OVER)
SDB_GET_RESERVE(pRaw, dataPos, DB_RESERVE_SIZE, _OVER)
taosInitRWLatch(&pDb->lock);
@@ -380,6 +382,7 @@ static int32_t mndCheckDbCfg(SMnode *pMnode, SDbCfg *pCfg) {
if (pCfg->replications < TSDB_MIN_DB_REPLICA || pCfg->replications > TSDB_MAX_DB_REPLICA) return -1;
if (pCfg->replications != 1 && pCfg->replications != 3) return -1;
if (pCfg->strict < TSDB_DB_STRICT_OFF || pCfg->strict > TSDB_DB_STRICT_ON) return -1;
+ if (pCfg->schemaless < TSDB_DB_SCHEMALESS_OFF || pCfg->schemaless > TSDB_DB_SCHEMALESS_ON) return -1;
if (pCfg->cacheLastRow < TSDB_MIN_DB_CACHE_LAST_ROW || pCfg->cacheLastRow > TSDB_MAX_DB_CACHE_LAST_ROW) return -1;
if (pCfg->hashMethod != 1) return -1;
if (pCfg->replications > mndGetDnodeSize(pMnode)) {
@@ -411,6 +414,8 @@ static void mndSetDefaultDbCfg(SDbCfg *pCfg) {
if (pCfg->strict < 0) pCfg->strict = TSDB_DEFAULT_DB_STRICT;
if (pCfg->cacheLastRow < 0) pCfg->cacheLastRow = TSDB_DEFAULT_CACHE_LAST_ROW;
if (pCfg->numOfRetensions < 0) pCfg->numOfRetensions = 0;
+ if (pCfg->schemaless < 0) pCfg->schemaless = TSDB_DB_SCHEMALESS_OFF;
+
}
static int32_t mndSetCreateDbRedoLogs(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroups) {
@@ -521,6 +526,7 @@ static int32_t mndCreateDb(SMnode *pMnode, SRpcMsg *pReq, SCreateDbReq *pCreate,
.strict = pCreate->strict,
.cacheLastRow = pCreate->cacheLastRow,
.hashMethod = 1,
+ .schemaless = pCreate->schemaless,
};
dbObj.cfg.numOfRetensions = pCreate->numOfRetensions;
@@ -899,6 +905,7 @@ static int32_t mndProcessGetDbCfgReq(SRpcMsg *pReq) {
cfgRsp.cacheLastRow = pDb->cfg.cacheLastRow;
cfgRsp.numOfRetensions = pDb->cfg.numOfRetensions;
cfgRsp.pRetensions = pDb->cfg.pRetensions;
+ cfgRsp.schemaless = pDb->cfg.schemaless;
int32_t contLen = tSerializeSDbCfgRsp(NULL, 0, &cfgRsp);
void *pRsp = rpcMallocCont(contLen);
@@ -1542,8 +1549,11 @@ static void dumpDbInfoData(SSDataBlock *pBlock, SDbObj *pDb, SShowObj *pShow, in
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.numOfStables, false);
- pColInfo = taosArrayGet(pBlock->pDataBlock, cols);
+ pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
colDataAppend(pColInfo, rows, (const char *)statusB, false);
+
+ pColInfo = taosArrayGet(pBlock->pDataBlock, cols);
+ colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.schemaless, false);
}
}
diff --git a/source/dnode/mnode/impl/src/mndDef.c b/source/dnode/mnode/impl/src/mndDef.c
index b45b6f9ee9..b6659e1632 100644
--- a/source/dnode/mnode/impl/src/mndDef.c
+++ b/source/dnode/mnode/impl/src/mndDef.c
@@ -395,10 +395,8 @@ SMqSubscribeObj *tCloneSubscribeObj(const SMqSubscribeObj *pSub) {
taosInitRWLatch(&pSubNew->lock);
pSubNew->dbUid = pSub->dbUid;
+ pSubNew->stbUid = pSub->stbUid;
pSubNew->subType = pSub->subType;
- /*pSubNew->withTbName = pSub->withTbName;*/
- /*pSubNew->withSchema = pSub->withSchema;*/
- /*pSubNew->withTag = pSub->withTag;*/
pSubNew->vgNum = pSub->vgNum;
pSubNew->consumerHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
@@ -431,9 +429,7 @@ int32_t tEncodeSubscribeObj(void **buf, const SMqSubscribeObj *pSub) {
tlen += taosEncodeFixedI64(buf, pSub->dbUid);
tlen += taosEncodeFixedI32(buf, pSub->vgNum);
tlen += taosEncodeFixedI8(buf, pSub->subType);
- /*tlen += taosEncodeFixedI8(buf, pSub->withTbName);*/
- /*tlen += taosEncodeFixedI8(buf, pSub->withSchema);*/
- /*tlen += taosEncodeFixedI8(buf, pSub->withTag);*/
+ tlen += taosEncodeFixedI64(buf, pSub->stbUid);
void *pIter = NULL;
int32_t sz = taosHashGetSize(pSub->consumerHash);
@@ -458,9 +454,7 @@ void *tDecodeSubscribeObj(const void *buf, SMqSubscribeObj *pSub) {
buf = taosDecodeFixedI64(buf, &pSub->dbUid);
buf = taosDecodeFixedI32(buf, &pSub->vgNum);
buf = taosDecodeFixedI8(buf, &pSub->subType);
- /*buf = taosDecodeFixedI8(buf, &pSub->withTbName);*/
- /*buf = taosDecodeFixedI8(buf, &pSub->withSchema);*/
- /*buf = taosDecodeFixedI8(buf, &pSub->withTag);*/
+ buf = taosDecodeFixedI64(buf, &pSub->stbUid);
int32_t sz;
buf = taosDecodeFixedI32(buf, &sz);
diff --git a/source/dnode/mnode/impl/src/mndMnode.c b/source/dnode/mnode/impl/src/mndMnode.c
index 4578d81efb..7c94a33ffe 100644
--- a/source/dnode/mnode/impl/src/mndMnode.c
+++ b/source/dnode/mnode/impl/src/mndMnode.c
@@ -392,11 +392,6 @@ static int32_t mndProcessCreateMnodeReq(SRpcMsg *pReq) {
mDebug("mnode:%d, start to create", createReq.dnodeId);
- if (sdbGetSize(pMnode->pSdb, SDB_MNODE) >= 3) {
- terrno = TSDB_CODE_MND_TOO_MANY_MNODES;
- goto _OVER;
- }
-
pObj = mndAcquireMnode(pMnode, createReq.dnodeId);
if (pObj != NULL) {
terrno = TSDB_CODE_MND_MNODE_ALREADY_EXIST;
@@ -405,12 +400,22 @@ static int32_t mndProcessCreateMnodeReq(SRpcMsg *pReq) {
goto _OVER;
}
+ if (sdbGetSize(pMnode->pSdb, SDB_MNODE) >= 3) {
+ terrno = TSDB_CODE_MND_TOO_MANY_MNODES;
+ goto _OVER;
+ }
+
pDnode = mndAcquireDnode(pMnode, createReq.dnodeId);
if (pDnode == NULL) {
terrno = TSDB_CODE_MND_DNODE_NOT_EXIST;
goto _OVER;
}
+ if (!mndIsDnodeOnline(pMnode, pDnode, taosGetTimestampMs())) {
+ terrno = TSDB_CODE_NODE_OFFLINE;
+ goto _OVER;
+ }
+
pUser = mndAcquireUser(pMnode, pReq->conn.user);
if (pUser == NULL) {
terrno = TSDB_CODE_MND_NO_USER_FROM_CONN;
@@ -632,11 +637,12 @@ static int32_t mndRetrieveMnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pB
int32_t numOfRows = 0;
int32_t cols = 0;
SMnodeObj *pObj = NULL;
+ ESdbStatus objStatus;
char *pWrite;
int64_t curMs = taosGetTimestampMs();
while (numOfRows < rows) {
- pShow->pIter = sdbFetch(pSdb, SDB_MNODE, pShow->pIter, (void **)&pObj);
+ pShow->pIter = sdbFetchAll(pSdb, SDB_MNODE, pShow->pIter, (void **)&pObj, &objStatus);
if (pShow->pIter == NULL) break;
cols = 0;
@@ -649,23 +655,26 @@ static int32_t mndRetrieveMnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pB
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
colDataAppend(pColInfo, numOfRows, b1, false);
- bool online = mndIsDnodeOnline(pMnode, pObj->pDnode, curMs);
- const char *roles = NULL;
+ const char *roles = "OFFLINE";
if (pObj->id == pMnode->selfDnodeId) {
roles = syncStr(TAOS_SYNC_STATE_LEADER);
- } else {
- if (!online) {
- roles = "OFFLINE";
- } else {
- roles = syncStr(pObj->state);
- }
}
- char *b2 = taosMemoryCalloc(1, 12 + VARSTR_HEADER_SIZE);
+ if (pObj->pDnode && mndIsDnodeOnline(pMnode, pObj->pDnode, curMs)) {
+ roles = syncStr(pObj->state);
+ }
+ char b2[12 + VARSTR_HEADER_SIZE] = {0};
STR_WITH_MAXSIZE_TO_VARSTR(b2, roles, pShow->pMeta->pSchemas[cols].bytes);
-
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
colDataAppend(pColInfo, numOfRows, (const char *)b2, false);
+ const char *status = "READY";
+ if (objStatus == SDB_STATUS_CREATING) status = "CREATING";
+ if (objStatus == SDB_STATUS_DROPPING) status = "DROPPING";
+ char b3[9 + VARSTR_HEADER_SIZE] = {0};
+ STR_WITH_MAXSIZE_TO_VARSTR(b3, status, pShow->pMeta->pSchemas[cols].bytes);
+ pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
+ colDataAppend(pColInfo, numOfRows, (const char *)b3, false);
+
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
colDataAppend(pColInfo, numOfRows, (const char *)&pObj->createdTime, false);
diff --git a/source/dnode/mnode/impl/src/mndStb.c b/source/dnode/mnode/impl/src/mndStb.c
index acb344c8a5..556837f397 100644
--- a/source/dnode/mnode/impl/src/mndStb.c
+++ b/source/dnode/mnode/impl/src/mndStb.c
@@ -1207,13 +1207,125 @@ static int32_t mndSetAlterStbRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj
return 0;
}
+
+static int32_t mndBuildStbSchemaImp(SDbObj *pDb, SStbObj *pStb, const char *tbName, STableMetaRsp *pRsp) {
+ taosRLockLatch(&pStb->lock);
+
+ int32_t totalCols = pStb->numOfColumns + pStb->numOfTags;
+ pRsp->pSchemas = taosMemoryCalloc(totalCols, sizeof(SSchema));
+ if (pRsp->pSchemas == NULL) {
+ taosRUnLockLatch(&pStb->lock);
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return -1;
+ }
+
+ strcpy(pRsp->dbFName, pStb->db);
+ strcpy(pRsp->tbName, tbName);
+ strcpy(pRsp->stbName, tbName);
+ pRsp->dbId = pDb->uid;
+ pRsp->numOfTags = pStb->numOfTags;
+ pRsp->numOfColumns = pStb->numOfColumns;
+ pRsp->precision = pDb->cfg.precision;
+ pRsp->tableType = TSDB_SUPER_TABLE;
+ pRsp->sversion = pStb->colVer;
+ pRsp->tversion = pStb->tagVer;
+ pRsp->suid = pStb->uid;
+ pRsp->tuid = pStb->uid;
+
+ for (int32_t i = 0; i < pStb->numOfColumns; ++i) {
+ SSchema *pSchema = &pRsp->pSchemas[i];
+ SSchema *pSrcSchema = &pStb->pColumns[i];
+ memcpy(pSchema->name, pSrcSchema->name, TSDB_COL_NAME_LEN);
+ pSchema->type = pSrcSchema->type;
+ pSchema->colId = pSrcSchema->colId;
+ pSchema->bytes = pSrcSchema->bytes;
+ }
+
+ for (int32_t i = 0; i < pStb->numOfTags; ++i) {
+ SSchema *pSchema = &pRsp->pSchemas[i + pStb->numOfColumns];
+ SSchema *pSrcSchema = &pStb->pTags[i];
+ memcpy(pSchema->name, pSrcSchema->name, TSDB_COL_NAME_LEN);
+ pSchema->type = pSrcSchema->type;
+ pSchema->colId = pSrcSchema->colId;
+ pSchema->bytes = pSrcSchema->bytes;
+ }
+
+ taosRUnLockLatch(&pStb->lock);
+ return 0;
+}
+
+static int32_t mndBuildStbSchema(SMnode *pMnode, const char *dbFName, const char *tbName, STableMetaRsp *pRsp) {
+ char tbFName[TSDB_TABLE_FNAME_LEN] = {0};
+ snprintf(tbFName, sizeof(tbFName), "%s.%s", dbFName, tbName);
+
+ SDbObj *pDb = mndAcquireDb(pMnode, dbFName);
+ if (pDb == NULL) {
+ terrno = TSDB_CODE_MND_DB_NOT_SELECTED;
+ return -1;
+ }
+
+ SStbObj *pStb = mndAcquireStb(pMnode, tbFName);
+ if (pStb == NULL) {
+ mndReleaseDb(pMnode, pDb);
+ terrno = TSDB_CODE_MND_INVALID_STB;
+ return -1;
+ }
+
+ int32_t code = mndBuildStbSchemaImp(pDb, pStb, tbName, pRsp);
+ mndReleaseDb(pMnode, pDb);
+ mndReleaseStb(pMnode, pStb);
+ return code;
+}
+
+
+static int32_t mndBuildSMAlterStbRsp(SDbObj *pDb, const SMAlterStbReq *pAlter, SStbObj *pObj, void **pCont, int32_t *pLen) {
+ int ret;
+ SEncoder ec = {0};
+ uint32_t contLen = 0;
+ SMAlterStbRsp alterRsp = {0};
+ SName name = {0};
+ tNameFromString(&name, pAlter->name, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE);
+
+ alterRsp.pMeta = taosMemoryCalloc(1, sizeof(STableMetaRsp));
+ if (NULL == alterRsp.pMeta) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return -1;
+ }
+
+ ret = mndBuildStbSchemaImp(pDb, pObj, name.tname, alterRsp.pMeta);
+ if (ret) {
+ tFreeSMAlterStbRsp(&alterRsp);
+ return ret;
+ }
+
+ tEncodeSize(tEncodeSMAlterStbRsp, &alterRsp, contLen, ret);
+ if (ret) {
+ tFreeSMAlterStbRsp(&alterRsp);
+ return ret;
+ }
+
+ void* cont = taosMemoryMalloc(contLen);
+ tEncoderInit(&ec, cont, contLen);
+ tEncodeSMAlterStbRsp(&ec, &alterRsp);
+ tEncoderClear(&ec);
+
+ tFreeSMAlterStbRsp(&alterRsp);
+
+ *pCont = cont;
+ *pLen = contLen;
+
+ return 0;
+}
+
static int32_t mndAlterStb(SMnode *pMnode, SRpcMsg *pReq, const SMAlterStbReq *pAlter, SDbObj *pDb, SStbObj *pOld) {
+ bool needRsp = true;
SStbObj stbObj = {0};
taosRLockLatch(&pOld->lock);
memcpy(&stbObj, pOld, sizeof(SStbObj));
stbObj.pColumns = NULL;
stbObj.pTags = NULL;
stbObj.updateTime = taosGetTimestampMs();
+ stbObj.lock = 0;
taosRUnLockLatch(&pOld->lock);
int32_t code = -1;
@@ -1247,9 +1359,11 @@ static int32_t mndAlterStb(SMnode *pMnode, SRpcMsg *pReq, const SMAlterStbReq *p
code = mndAlterStbColumnBytes(pOld, &stbObj, pField0);
break;
case TSDB_ALTER_TABLE_UPDATE_OPTIONS:
+ needRsp = false;
code = mndUpdateStbCommentAndTTL(pOld, &stbObj, pAlter->comment, pAlter->commentLen, pAlter->ttl);
break;
default:
+ needRsp = false;
terrno = TSDB_CODE_OPS_NOT_SUPPORT;
break;
}
@@ -1263,6 +1377,13 @@ static int32_t mndAlterStb(SMnode *pMnode, SRpcMsg *pReq, const SMAlterStbReq *p
mDebug("trans:%d, used to alter stb:%s", pTrans->id, pAlter->name);
mndTransSetDbName(pTrans, pDb->name);
+ if (needRsp) {
+ void* pCont = NULL;
+ int32_t contLen = 0;
+ if (mndBuildSMAlterStbRsp(pDb, pAlter, &stbObj, &pCont, &contLen)) goto _OVER;
+ mndTransSetRpcRsp(pTrans, pCont, contLen);
+ }
+
if (mndSetAlterStbRedoLogs(pMnode, pTrans, pDb, &stbObj) != 0) goto _OVER;
if (mndSetAlterStbCommitLogs(pMnode, pTrans, pDb, &stbObj) != 0) goto _OVER;
if (mndSetAlterStbRedoActions(pMnode, pTrans, pDb, &stbObj) != 0) goto _OVER;
@@ -1483,75 +1604,6 @@ static int32_t mndProcessVDropStbRsp(SRpcMsg *pRsp) {
return 0;
}
-static int32_t mndBuildStbSchemaImp(SDbObj *pDb, SStbObj *pStb, const char *tbName, STableMetaRsp *pRsp) {
- taosRLockLatch(&pStb->lock);
-
- int32_t totalCols = pStb->numOfColumns + pStb->numOfTags;
- pRsp->pSchemas = taosMemoryCalloc(totalCols, sizeof(SSchema));
- if (pRsp->pSchemas == NULL) {
- taosRUnLockLatch(&pStb->lock);
- terrno = TSDB_CODE_OUT_OF_MEMORY;
- return -1;
- }
-
- strcpy(pRsp->dbFName, pStb->db);
- strcpy(pRsp->tbName, tbName);
- strcpy(pRsp->stbName, tbName);
- pRsp->dbId = pDb->uid;
- pRsp->numOfTags = pStb->numOfTags;
- pRsp->numOfColumns = pStb->numOfColumns;
- pRsp->precision = pDb->cfg.precision;
- pRsp->tableType = TSDB_SUPER_TABLE;
- pRsp->sversion = pStb->colVer;
- pRsp->tversion = pStb->tagVer;
- pRsp->suid = pStb->uid;
- pRsp->tuid = pStb->uid;
-
- for (int32_t i = 0; i < pStb->numOfColumns; ++i) {
- SSchema *pSchema = &pRsp->pSchemas[i];
- SSchema *pSrcSchema = &pStb->pColumns[i];
- memcpy(pSchema->name, pSrcSchema->name, TSDB_COL_NAME_LEN);
- pSchema->type = pSrcSchema->type;
- pSchema->colId = pSrcSchema->colId;
- pSchema->bytes = pSrcSchema->bytes;
- }
-
- for (int32_t i = 0; i < pStb->numOfTags; ++i) {
- SSchema *pSchema = &pRsp->pSchemas[i + pStb->numOfColumns];
- SSchema *pSrcSchema = &pStb->pTags[i];
- memcpy(pSchema->name, pSrcSchema->name, TSDB_COL_NAME_LEN);
- pSchema->type = pSrcSchema->type;
- pSchema->colId = pSrcSchema->colId;
- pSchema->bytes = pSrcSchema->bytes;
- }
-
- taosRUnLockLatch(&pStb->lock);
- return 0;
-}
-
-static int32_t mndBuildStbSchema(SMnode *pMnode, const char *dbFName, const char *tbName, STableMetaRsp *pRsp) {
- char tbFName[TSDB_TABLE_FNAME_LEN] = {0};
- snprintf(tbFName, sizeof(tbFName), "%s.%s", dbFName, tbName);
-
- SDbObj *pDb = mndAcquireDb(pMnode, dbFName);
- if (pDb == NULL) {
- terrno = TSDB_CODE_MND_DB_NOT_SELECTED;
- return -1;
- }
-
- SStbObj *pStb = mndAcquireStb(pMnode, tbFName);
- if (pStb == NULL) {
- mndReleaseDb(pMnode, pDb);
- terrno = TSDB_CODE_MND_INVALID_STB;
- return -1;
- }
-
- int32_t code = mndBuildStbSchemaImp(pDb, pStb, tbName, pRsp);
- mndReleaseDb(pMnode, pDb);
- mndReleaseStb(pMnode, pStb);
- return code;
-}
-
static int32_t mndProcessTableMetaReq(SRpcMsg *pReq) {
SMnode *pMnode = pReq->info.node;
int32_t code = -1;
diff --git a/source/dnode/mnode/impl/src/mndSubscribe.c b/source/dnode/mnode/impl/src/mndSubscribe.c
index fc736809fd..41065a3fdd 100644
--- a/source/dnode/mnode/impl/src/mndSubscribe.c
+++ b/source/dnode/mnode/impl/src/mndSubscribe.c
@@ -93,10 +93,8 @@ static SMqSubscribeObj *mndCreateSub(SMnode *pMnode, const SMqTopicObj *pTopic,
return NULL;
}
pSub->dbUid = pTopic->dbUid;
+ pSub->stbUid = pTopic->stbUid;
pSub->subType = pTopic->subType;
- /*pSub->withTbName = pTopic->withTbName;*/
- /*pSub->withSchema = pTopic->withSchema;*/
- /*pSub->withTag = pTopic->withTag;*/
ASSERT(pSub->unassignedVgs->size == 0);
ASSERT(taosHashGetSize(pSub->consumerHash) == 0);
@@ -121,9 +119,7 @@ static int32_t mndBuildSubChangeReq(void **pBuf, int32_t *pLen, const SMqSubscri
req.vgId = pRebVg->pVgEp->vgId;
req.qmsg = pRebVg->pVgEp->qmsg;
req.subType = pSub->subType;
- /*req.withTbName = pSub->withTbName;*/
- /*req.withSchema = pSub->withSchema;*/
- /*req.withTag = pSub->withTag;*/
+ req.suid = pSub->stbUid;
strncpy(req.subKey, pSub->key, TSDB_SUBSCRIBE_KEY_LEN);
int32_t tlen = sizeof(SMsgHead) + tEncodeSMqRebVgReq(NULL, &req);
diff --git a/source/dnode/mnode/impl/src/mndTopic.c b/source/dnode/mnode/impl/src/mndTopic.c
index 446992a245..e0d565c9af 100644
--- a/source/dnode/mnode/impl/src/mndTopic.c
+++ b/source/dnode/mnode/impl/src/mndTopic.c
@@ -70,6 +70,56 @@ const char *mndTopicGetShowName(const char topic[TSDB_TOPIC_FNAME_LEN]) {
return strchr(topic, '.') + 1;
}
+bool mndCheckColAndTagModifiable(SMnode *pMnode, int64_t suid, const SArray *colAndTagIds) {
+ SSdb *pSdb = pMnode->pSdb;
+ void *pIter = NULL;
+ bool found = false;
+ while (1) {
+ SMqTopicObj *pTopic = NULL;
+ pIter = sdbFetch(pSdb, SDB_TOPIC, pIter, (void **)&pTopic);
+ if (pIter == NULL) break;
+ if (pTopic->subType != TOPIC_SUB_TYPE__COLUMN) {
+ sdbRelease(pSdb, pTopic);
+ continue;
+ }
+
+ SNode *pAst = NULL;
+ if (nodesStringToNode(pTopic->ast, &pAst) != 0) {
+ ASSERT(0);
+ return false;
+ }
+
+ SHashObj *pColHash = NULL;
+ SNodeList *pNodeList;
+ nodesCollectColumns((SSelectStmt *)pAst, SQL_CLAUSE_FROM, NULL, COLLECT_COL_TYPE_ALL, &pNodeList);
+ SNode *pNode = NULL;
+ FOREACH(pNode, pNodeList) {
+ SColumnNode *pCol = (SColumnNode *)pNode;
+ if (pCol->tableId != suid) goto NEXT;
+ if (pColHash == NULL) {
+ pColHash = taosHashInit(0, taosGetDefaultHashFunction(TSDB_DATA_TYPE_SMALLINT), false, HASH_NO_LOCK);
+ }
+ if (pCol->colId > 0) {
+ taosHashPut(pColHash, &pCol->colId, sizeof(int16_t), NULL, 0);
+ }
+ }
+
+ for (int32_t i = 0; i < taosArrayGetSize(colAndTagIds); i++) {
+ int16_t *pColId = taosArrayGet(colAndTagIds, i);
+ if (taosHashGet(pColHash, pColId, sizeof(int16_t)) != NULL) {
+ found = true;
+ goto NEXT;
+ }
+ }
+
+ NEXT:
+ sdbRelease(pSdb, pTopic);
+ nodesDestroyNode(pAst);
+ if (found) return false;
+ }
+ return true;
+}
+
SSdbRaw *mndTopicActionEncode(SMqTopicObj *pTopic) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
@@ -96,11 +146,8 @@ SSdbRaw *mndTopicActionEncode(SMqTopicObj *pTopic) {
SDB_SET_INT64(pRaw, dataPos, pTopic->dbUid, TOPIC_ENCODE_OVER);
SDB_SET_INT32(pRaw, dataPos, pTopic->version, TOPIC_ENCODE_OVER);
SDB_SET_INT8(pRaw, dataPos, pTopic->subType, TOPIC_ENCODE_OVER);
- /*SDB_SET_INT8(pRaw, dataPos, pTopic->withTbName, TOPIC_ENCODE_OVER);*/
- /*SDB_SET_INT8(pRaw, dataPos, pTopic->withSchema, TOPIC_ENCODE_OVER);*/
- /*SDB_SET_INT8(pRaw, dataPos, pTopic->withTag, TOPIC_ENCODE_OVER);*/
- SDB_SET_INT32(pRaw, dataPos, pTopic->consumerCnt, TOPIC_ENCODE_OVER);
+ SDB_SET_INT64(pRaw, dataPos, pTopic->stbUid, TOPIC_ENCODE_OVER);
SDB_SET_INT32(pRaw, dataPos, pTopic->sqlLen, TOPIC_ENCODE_OVER);
SDB_SET_BINARY(pRaw, dataPos, pTopic->sql, pTopic->sqlLen, TOPIC_ENCODE_OVER);
SDB_SET_INT32(pRaw, dataPos, pTopic->astLen, TOPIC_ENCODE_OVER);
@@ -122,8 +169,6 @@ SSdbRaw *mndTopicActionEncode(SMqTopicObj *pTopic) {
SDB_SET_BINARY(pRaw, dataPos, swBuf, schemaLen, TOPIC_ENCODE_OVER);
}
- /*SDB_SET_INT32(pRaw, dataPos, pTopic->refConsumerCnt, TOPIC_ENCODE_OVER);*/
-
SDB_SET_RESERVE(pRaw, dataPos, MND_TOPIC_RESERVE_SIZE, TOPIC_ENCODE_OVER);
SDB_SET_DATALEN(pRaw, dataPos, TOPIC_ENCODE_OVER);
@@ -168,12 +213,8 @@ SSdbRow *mndTopicActionDecode(SSdbRaw *pRaw) {
SDB_GET_INT64(pRaw, dataPos, &pTopic->dbUid, TOPIC_DECODE_OVER);
SDB_GET_INT32(pRaw, dataPos, &pTopic->version, TOPIC_DECODE_OVER);
SDB_GET_INT8(pRaw, dataPos, &pTopic->subType, TOPIC_DECODE_OVER);
- /*SDB_GET_INT8(pRaw, dataPos, &pTopic->withTbName, TOPIC_DECODE_OVER);*/
- /*SDB_GET_INT8(pRaw, dataPos, &pTopic->withSchema, TOPIC_DECODE_OVER);*/
- /*SDB_GET_INT8(pRaw, dataPos, &pTopic->withTag, TOPIC_DECODE_OVER);*/
-
- SDB_GET_INT32(pRaw, dataPos, &pTopic->consumerCnt, TOPIC_DECODE_OVER);
+ SDB_GET_INT64(pRaw, dataPos, &pTopic->stbUid, TOPIC_DECODE_OVER);
SDB_GET_INT32(pRaw, dataPos, &pTopic->sqlLen, TOPIC_DECODE_OVER);
pTopic->sql = taosMemoryCalloc(pTopic->sqlLen, sizeof(char));
if (pTopic->sql == NULL) {
@@ -222,8 +263,6 @@ SSdbRow *mndTopicActionDecode(SSdbRaw *pRaw) {
pTopic->schema.pSchema = NULL;
}
- /*SDB_GET_INT32(pRaw, dataPos, &pTopic->refConsumerCnt, TOPIC_DECODE_OVER);*/
-
SDB_GET_RESERVE(pRaw, dataPos, MND_TOPIC_RESERVE_SIZE, TOPIC_DECODE_OVER);
terrno = TSDB_CODE_SUCCESS;
@@ -254,8 +293,6 @@ static int32_t mndTopicActionUpdate(SSdb *pSdb, SMqTopicObj *pOldTopic, SMqTopic
atomic_exchange_64(&pOldTopic->updateTime, pNewTopic->updateTime);
atomic_exchange_32(&pOldTopic->version, pNewTopic->version);
- /*atomic_store_32(&pOldTopic->refConsumerCnt, pNewTopic->refConsumerCnt);*/
-
/*taosWLockLatch(&pOldTopic->lock);*/
// TODO handle update
@@ -278,18 +315,6 @@ void mndReleaseTopic(SMnode *pMnode, SMqTopicObj *pTopic) {
sdbRelease(pSdb, pTopic);
}
-#if 0
-static SDbObj *mndAcquireDbByTopic(SMnode *pMnode, char *topicName) {
- SName name = {0};
- tNameFromString(&name, topicName, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE);
-
- char db[TSDB_TOPIC_FNAME_LEN] = {0};
- tNameGetFullDbName(&name, db);
-
- return mndAcquireDb(pMnode, db);
-}
-#endif
-
static SDDropTopicReq *mndBuildDropTopicMsg(SMnode *pMnode, SVgObj *pVgroup, SMqTopicObj *pTopic) {
int32_t contLen = sizeof(SDDropTopicReq);
@@ -341,8 +366,6 @@ static int32_t mndCreateTopic(SMnode *pMnode, SRpcMsg *pReq, SCMCreateTopicReq *
if (pCreate->subType == TOPIC_SUB_TYPE__COLUMN) {
topicObj.ast = strdup(pCreate->ast);
topicObj.astLen = strlen(pCreate->ast) + 1;
- /*topicObj.withTbName = pCreate->withTbName;*/
- /*topicObj.withSchema = pCreate->withSchema;*/
SNode *pAst = NULL;
if (nodesStringToNode(pCreate->ast, &pAst) != 0) {
@@ -375,13 +398,16 @@ static int32_t mndCreateTopic(SMnode *pMnode, SRpcMsg *pReq, SCMCreateTopicReq *
taosMemoryFree(topicObj.sql);
return -1;
}
- /*} else if (pCreate->subType == TOPIC_SUB_TYPE__DB) {*/
- /*topicObj.ast = NULL;*/
- /*topicObj.astLen = 0;*/
- /*topicObj.physicalPlan = NULL;*/
- /*topicObj.withTbName = 1;*/
- /*topicObj.withSchema = 1;*/
+ } else if (pCreate->subType == TOPIC_SUB_TYPE__TABLE) {
+ SStbObj *pStb = mndAcquireStb(pMnode, pCreate->subStbName);
+ topicObj.stbUid = pStb->uid;
}
+ /*} else if (pCreate->subType == TOPIC_SUB_TYPE__DB) {*/
+ /*topicObj.ast = NULL;*/
+ /*topicObj.astLen = 0;*/
+ /*topicObj.physicalPlan = NULL;*/
+ /*topicObj.withTbName = 1;*/
+ /*topicObj.withSchema = 1;*/
STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq);
if (pTrans == NULL) {
diff --git a/source/dnode/mnode/impl/src/mndTrans.c b/source/dnode/mnode/impl/src/mndTrans.c
index e191bb9b2a..bbee59090d 100644
--- a/source/dnode/mnode/impl/src/mndTrans.c
+++ b/source/dnode/mnode/impl/src/mndTrans.c
@@ -344,7 +344,7 @@ static SSdbRow *mndTransActionDecode(SSdbRaw *pRaw) {
SDB_GET_INT32(pRaw, dataPos, &dataLen, _OVER)
action.pRaw = taosMemoryMalloc(dataLen);
if (action.pRaw == NULL) goto _OVER;
- mTrace("raw:%p, is created", pData);
+ mTrace("raw:%p, is created", action.pRaw);
SDB_GET_BINARY(pRaw, dataPos, (void *)action.pRaw, dataLen, _OVER);
if (taosArrayPush(pTrans->commitActions, &action) == NULL) goto _OVER;
action.pRaw = NULL;
@@ -619,9 +619,7 @@ void mndTransSetCb(STrans *pTrans, ETrnFunc startFunc, ETrnFunc stopFunc, void *
pTrans->paramLen = paramLen;
}
-void mndTransSetDbName(STrans *pTrans, const char *dbname) {
- memcpy(pTrans->dbname, dbname, TSDB_DB_FNAME_LEN);
-}
+void mndTransSetDbName(STrans *pTrans, const char *dbname) { memcpy(pTrans->dbname, dbname, TSDB_DB_FNAME_LEN); }
void mndTransSetSerial(STrans *pTrans) { pTrans->exec = TRN_EXEC_SERIAL; }
@@ -753,22 +751,30 @@ static void mndTransSendRpcRsp(SMnode *pMnode, STrans *pTrans) {
sendRsp = true;
}
} else {
- if (pTrans->stage == TRN_STAGE_REDO_ACTION && pTrans->failedTimes > 6) {
+ if (pTrans->stage == TRN_STAGE_REDO_ACTION && pTrans->failedTimes > 3) {
if (code == 0) code = TSDB_CODE_MND_TRANS_UNKNOW_ERROR;
sendRsp = true;
}
}
if (sendRsp && pTrans->rpcInfo.handle != NULL) {
- void *rpcCont = rpcMallocCont(pTrans->rpcRspLen);
- if (rpcCont != NULL) {
- memcpy(rpcCont, pTrans->rpcRsp, pTrans->rpcRspLen);
- }
- taosMemoryFree(pTrans->rpcRsp);
-
mDebug("trans:%d, send rsp, code:0x%x stage:%s app:%p", pTrans->id, code, mndTransStr(pTrans->stage),
pTrans->rpcInfo.ahandle);
- SRpcMsg rspMsg = {.code = code, .pCont = rpcCont, .contLen = pTrans->rpcRspLen, .info = pTrans->rpcInfo};
+ if (code == TSDB_CODE_RPC_NETWORK_UNAVAIL) {
+ code = TSDB_CODE_RPC_INDIRECT_NETWORK_UNAVAIL;
+ }
+ SRpcMsg rspMsg = {.code = code, .info = pTrans->rpcInfo};
+
+ if (pTrans->rpcRspLen != 0) {
+ void *rpcCont = rpcMallocCont(pTrans->rpcRspLen);
+ if (rpcCont != NULL) {
+ memcpy(rpcCont, pTrans->rpcRsp, pTrans->rpcRspLen);
+ rspMsg.pCont = rpcCont;
+ rspMsg.contLen = pTrans->rpcRspLen;
+ }
+ taosMemoryFree(pTrans->rpcRsp);
+ }
+
tmsgSendRsp(&rspMsg);
pTrans->rpcInfo.handle = NULL;
pTrans->rpcRsp = NULL;
@@ -1000,6 +1006,9 @@ static int32_t mndTransExecuteRedoActionsSerial(SMnode *pMnode, STrans *pTrans)
if (pAction->msgReceived) {
if (pAction->errCode != 0 && pAction->errCode != pAction->acceptableCode) {
code = pAction->errCode;
+ pAction->msgSent = 0;
+ pAction->msgReceived = 0;
+ mDebug("trans:%d, %s:%d execute status is reset", pTrans->id, mndTransStr(pAction->stage), action);
}
} else {
code = TSDB_CODE_ACTION_IN_PROGRESS;
@@ -1025,18 +1034,23 @@ static int32_t mndTransExecuteRedoActionsSerial(SMnode *pMnode, STrans *pTrans)
}
if (code == 0) {
+ pTrans->code = 0;
pTrans->redoActionPos++;
mDebug("trans:%d, %s:%d is executed and need sync to other mnodes", pTrans->id, mndTransStr(pAction->stage),
pAction->id);
code = mndTransSync(pMnode, pTrans);
if (code != 0) {
- mError("trans:%d, failed to sync redoActionPos since %s", pTrans->id, terrstr());
+ pTrans->code = terrno;
+ mError("trans:%d, %s:%d is executed and failed to sync to other mnodes since %s", pTrans->id,
+ mndTransStr(pAction->stage), pAction->id, terrstr());
break;
}
} else if (code == TSDB_CODE_ACTION_IN_PROGRESS) {
mDebug("trans:%d, %s:%d is in progress and wait it finish", pTrans->id, mndTransStr(pAction->stage), pAction->id);
break;
} else {
+ terrno = code;
+ pTrans->code = code;
mError("trans:%d, %s:%d failed to execute since %s", pTrans->id, mndTransStr(pAction->stage), pAction->id,
terrstr());
break;
@@ -1239,19 +1253,8 @@ int32_t mndKillTrans(SMnode *pMnode, STrans *pTrans) {
return -1;
}
- int32_t size = taosArrayGetSize(pArray);
-
- for (int32_t i = 0; i < size; ++i) {
+ for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
STransAction *pAction = taosArrayGet(pArray, i);
- if (pAction == NULL) continue;
-
- if (pAction->msgReceived == 0) {
- mInfo("trans:%d, %s:%d set processed for kill msg received", pTrans->id, mndTransStr(pAction->stage), i);
- pAction->msgSent = 1;
- pAction->msgReceived = 1;
- pAction->errCode = 0;
- }
-
if (pAction->errCode != 0) {
mInfo("trans:%d, %s:%d set processed for kill msg received, errCode from %s to success", pTrans->id,
mndTransStr(pAction->stage), i, tstrerror(pAction->errCode));
@@ -1290,9 +1293,7 @@ static int32_t mndProcessKillTransReq(SRpcMsg *pReq) {
pTrans = mndAcquireTrans(pMnode, killReq.transId);
if (pTrans == NULL) {
- terrno = TSDB_CODE_MND_TRANS_NOT_EXIST;
- mError("trans:%d, failed to kill since %s", killReq.transId, terrstr());
- return -1;
+ goto _OVER;
}
code = mndKillTrans(pMnode, pTrans);
@@ -1300,9 +1301,9 @@ static int32_t mndProcessKillTransReq(SRpcMsg *pReq) {
_OVER:
if (code != 0) {
mError("trans:%d, failed to kill since %s", killReq.transId, terrstr());
- return -1;
}
+ mndReleaseUser(pMnode, pUser);
mndReleaseTrans(pMnode, pTrans);
return code;
}
diff --git a/source/dnode/mnode/impl/src/mndVgroup.c b/source/dnode/mnode/impl/src/mndVgroup.c
index 219e0fa3dc..9262aa167b 100644
--- a/source/dnode/mnode/impl/src/mndVgroup.c
+++ b/source/dnode/mnode/impl/src/mndVgroup.c
@@ -504,7 +504,7 @@ _OVER:
taosArrayDestroy(pArray);
return code;
}
-//--->
+
int32_t mndAddVnodeToVgroup(SMnode *pMnode, SVgObj *pVgroup, SArray *pArray) {
taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
@@ -543,7 +543,7 @@ int32_t mndAddVnodeToVgroup(SMnode *pMnode, SVgObj *pVgroup, SArray *pArray) {
terrno = TSDB_CODE_MND_NO_ENOUGH_DNODES;
return -1;
}
-//--->
+
int32_t mndRemoveVnodeFromVgroup(SMnode *pMnode, SVgObj *pVgroup, SArray *pArray, SVnodeGid *del1, SVnodeGid *del2) {
taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes);
for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) {
diff --git a/source/dnode/mnode/sdb/inc/sdb.h b/source/dnode/mnode/sdb/inc/sdb.h
index 1fd0260d0d..4a00befa1e 100644
--- a/source/dnode/mnode/sdb/inc/sdb.h
+++ b/source/dnode/mnode/sdb/inc/sdb.h
@@ -301,6 +301,7 @@ void sdbRelease(SSdb *pSdb, void *pObj);
* @return void* The next iterator of the table.
*/
void *sdbFetch(SSdb *pSdb, ESdbType type, void *pIter, void **ppObj);
+void *sdbFetchAll(SSdb *pSdb, ESdbType type, void *pIter, void **ppObj, ESdbStatus *status) ;
/**
* @brief Cancel a traversal
diff --git a/source/dnode/mnode/sdb/src/sdbHash.c b/source/dnode/mnode/sdb/src/sdbHash.c
index abf35b71a9..162da2bd0a 100644
--- a/source/dnode/mnode/sdb/src/sdbHash.c
+++ b/source/dnode/mnode/sdb/src/sdbHash.c
@@ -368,6 +368,34 @@ void *sdbFetch(SSdb *pSdb, ESdbType type, void *pIter, void **ppObj) {
return ppRow;
}
+void *sdbFetchAll(SSdb *pSdb, ESdbType type, void *pIter, void **ppObj, ESdbStatus *status) {
+ *ppObj = NULL;
+
+ SHashObj *hash = sdbGetHash(pSdb, type);
+ if (hash == NULL) return NULL;
+
+ TdThreadRwlock *pLock = &pSdb->locks[type];
+ taosThreadRwlockRdlock(pLock);
+
+ SSdbRow **ppRow = taosHashIterate(hash, pIter);
+ while (ppRow != NULL) {
+ SSdbRow *pRow = *ppRow;
+ if (pRow == NULL) {
+ ppRow = taosHashIterate(hash, ppRow);
+ continue;
+ }
+
+ atomic_add_fetch_32(&pRow->refCount, 1);
+ sdbPrintOper(pSdb, pRow, "fetch");
+ *ppObj = pRow->pObj;
+ *status = pRow->status;
+ break;
+ }
+ taosThreadRwlockUnlock(pLock);
+
+ return ppRow;
+}
+
void sdbCancelFetch(SSdb *pSdb, void *pIter) {
if (pIter == NULL) return;
SSdbRow *pRow = *(SSdbRow **)pIter;
diff --git a/source/dnode/vnode/CMakeLists.txt b/source/dnode/vnode/CMakeLists.txt
index 890b8d08ab..05b4a270d6 100644
--- a/source/dnode/vnode/CMakeLists.txt
+++ b/source/dnode/vnode/CMakeLists.txt
@@ -32,7 +32,7 @@ target_sources(
"src/sma/smaEnv.c"
"src/sma/smaOpen.c"
"src/sma/smaRollup.c"
- "src/sma/smaTimeRange.c"
+ "src/sma/smaTimeRange2.c"
# tsdb
"src/tsdb/tsdbCommit.c"
diff --git a/source/dnode/vnode/inc/vnode.h b/source/dnode/vnode/inc/vnode.h
index 3e56ea75ad..35b2b93546 100644
--- a/source/dnode/vnode/inc/vnode.h
+++ b/source/dnode/vnode/inc/vnode.h
@@ -85,7 +85,7 @@ typedef struct SMetaFltParam {
tb_uid_t suid;
int16_t cid;
int16_t type;
- char * val;
+ char *val;
bool reverse;
int (*filterFunc)(void *a, void *b, int16_t type);
@@ -119,7 +119,8 @@ tsdbReaderT tsdbQueryCacheLast(SVnode *pVnode, SQueryTableDataCond *pCond, STab
int32_t tsdbGetFileBlocksDistInfo(tsdbReaderT *pReader, STableBlockDistInfo *pTableBlockInfo);
bool isTsdbCacheLastRow(tsdbReaderT *pReader);
int32_t tsdbGetAllTableList(SMeta *pMeta, uint64_t uid, SArray *list);
-void * tsdbGetIdx(SMeta *pMeta);
+int32_t tsdbGetCtbIdList(SMeta *pMeta, int64_t suid, SArray *list);
+void *tsdbGetIdx(SMeta *pMeta);
int64_t tsdbGetNumOfRowsInMemTable(tsdbReaderT *pHandle);
bool tsdbNextDataBlock(tsdbReaderT pTsdbReadHandle);
@@ -146,6 +147,9 @@ bool tqNextDataBlockFilterOut(STqReadHandle *pHandle, SHashObj *filterOutUids
int32_t tqRetrieveDataBlock(SArray **ppCols, STqReadHandle *pHandle, uint64_t *pGroupId, uint64_t *pUid,
int32_t *pNumOfRows, int16_t *pNumOfCols);
+// sma
+int32_t smaGetTSmaDays(SVnodeCfg *pCfg, void *pCont, uint32_t contLen, int32_t *days);
+
// need to reposition
// structs
@@ -192,7 +196,7 @@ struct SMetaEntry {
int64_t version;
int8_t type;
tb_uid_t uid;
- char * name;
+ char *name;
union {
struct {
SSchemaWrapper schemaRow;
@@ -220,17 +224,17 @@ struct SMetaEntry {
struct SMetaReader {
int32_t flags;
- SMeta * pMeta;
+ SMeta *pMeta;
SDecoder coder;
SMetaEntry me;
- void * pBuf;
+ void *pBuf;
int32_t szBuf;
};
struct SMTbCursor {
- TBC * pDbc;
- void * pKey;
- void * pVal;
+ TBC *pDbc;
+ void *pKey;
+ void *pVal;
int32_t kLen;
int32_t vLen;
SMetaReader mr;
diff --git a/source/dnode/vnode/src/inc/sma.h b/source/dnode/vnode/src/inc/sma.h
index 03dd2ea66c..4ca62f1de9 100644
--- a/source/dnode/vnode/src/inc/sma.h
+++ b/source/dnode/vnode/src/inc/sma.h
@@ -223,6 +223,8 @@ int32_t tdUpdateExpiredWindowImpl(SSma *pSma, const SSubmitReq *pMsg, int64_t ve
// TODO: This is the basic params, and should wrap the params to a queryHandle.
int32_t tdGetTSmaDataImpl(SSma *pSma, char *pData, int64_t indexUid, TSKEY querySKey, int32_t nMaxResult);
+int32_t tdGetTSmaDaysImpl(SVnodeCfg *pCfg, void *pCont, uint32_t contLen, int32_t *days);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/dnode/vnode/src/inc/tq.h b/source/dnode/vnode/src/inc/tq.h
index 0715ee8066..7cd82b0ac3 100644
--- a/source/dnode/vnode/src/inc/tq.h
+++ b/source/dnode/vnode/src/inc/tq.h
@@ -65,12 +65,6 @@ struct STqReadHandle {
// tqPush
-typedef struct {
- STaosQueue* queue;
- STaosQall* qall;
- void* qItem;
-} STqInputQ;
-
typedef struct {
// msg info
int64_t consumerId;
@@ -84,10 +78,10 @@ typedef struct {
tmr_h timerId;
int8_t tmrStopped;
// exec
- int8_t inputStatus;
- int8_t execStatus;
- STqInputQ inputQ;
- SRWLatch lock;
+ int8_t inputStatus;
+ int8_t execStatus;
+ SStreamQ inputQ;
+ SRWLatch lock;
} STqPushHandle;
// tqExec
@@ -155,6 +149,7 @@ int64_t tqFetchLog(STQ* pTq, STqHandle* pHandle, int64_t* fetchOffset, SWalHead*
// tqExec
int32_t tqDataExec(STQ* pTq, STqExecHandle* pExec, SSubmitReq* pReq, SMqDataBlkRsp* pRsp, int32_t workerId);
+int32_t tqSendPollRsp(STQ* pTq, const SRpcMsg* pMsg, const SMqPollReq* pReq, const SMqDataBlkRsp* pRsp);
// tqMeta
int32_t tqMetaOpen(STQ* pTq);
diff --git a/source/dnode/vnode/src/inc/vnodeInt.h b/source/dnode/vnode/src/inc/vnodeInt.h
index 03c70b2601..d3b5f29aac 100644
--- a/source/dnode/vnode/src/inc/vnodeInt.h
+++ b/source/dnode/vnode/src/inc/vnodeInt.h
@@ -87,7 +87,7 @@ int metaAlterSTable(SMeta* pMeta, int64_t version, SVCreateStbReq* p
int metaDropSTable(SMeta* pMeta, int64_t verison, SVDropStbReq* pReq);
int metaCreateTable(SMeta* pMeta, int64_t version, SVCreateTbReq* pReq);
int metaDropTable(SMeta* pMeta, int64_t version, SVDropTbReq* pReq, SArray* tbUids);
-int metaAlterTable(SMeta* pMeta, int64_t version, SVAlterTbReq* pReq);
+int metaAlterTable(SMeta* pMeta, int64_t version, SVAlterTbReq* pReq, STableMetaRsp *pMetaRsp);
SSchemaWrapper* metaGetTableSchema(SMeta* pMeta, tb_uid_t uid, int32_t sver, bool isinline);
STSchema* metaGetTbTSchema(SMeta* pMeta, tb_uid_t uid, int32_t sver);
int metaGetTableEntryByName(SMetaReader* pReader, const char* name);
diff --git a/source/dnode/vnode/src/meta/metaEntry.c b/source/dnode/vnode/src/meta/metaEntry.c
index a003494457..db99257ea7 100644
--- a/source/dnode/vnode/src/meta/metaEntry.c
+++ b/source/dnode/vnode/src/meta/metaEntry.c
@@ -30,6 +30,7 @@ int metaEncodeEntry(SEncoder *pCoder, const SMetaEntry *pME) {
if (tEncodeI64(pCoder, pME->ctbEntry.ctime) < 0) return -1;
if (tEncodeI32(pCoder, pME->ctbEntry.ttlDays) < 0) return -1;
if (tEncodeI64(pCoder, pME->ctbEntry.suid) < 0) return -1;
+ debugCheckTags((STag*)pME->ctbEntry.pTags); // TODO: remove after debug
if (tEncodeTag(pCoder, (const STag *)pME->ctbEntry.pTags) < 0) return -1;
} else if (pME->type == TSDB_NORMAL_TABLE) {
if (tEncodeI64(pCoder, pME->ntbEntry.ctime) < 0) return -1;
@@ -62,6 +63,7 @@ int metaDecodeEntry(SDecoder *pCoder, SMetaEntry *pME) {
if (tDecodeI32(pCoder, &pME->ctbEntry.ttlDays) < 0) return -1;
if (tDecodeI64(pCoder, &pME->ctbEntry.suid) < 0) return -1;
if (tDecodeTag(pCoder, (STag **)&pME->ctbEntry.pTags) < 0) return -1; // (TODO)
+ debugCheckTags((STag*)pME->ctbEntry.pTags); // TODO: remove after debug
} else if (pME->type == TSDB_NORMAL_TABLE) {
if (tDecodeI64(pCoder, &pME->ntbEntry.ctime) < 0) return -1;
if (tDecodeI32(pCoder, &pME->ntbEntry.ttlDays) < 0) return -1;
diff --git a/source/dnode/vnode/src/meta/metaQuery.c b/source/dnode/vnode/src/meta/metaQuery.c
index 7928f715e2..934a916652 100644
--- a/source/dnode/vnode/src/meta/metaQuery.c
+++ b/source/dnode/vnode/src/meta/metaQuery.c
@@ -464,7 +464,7 @@ STSmaWrapper *metaGetSmaInfoByTable(SMeta *pMeta, tb_uid_t uid, bool deepCopy) {
_err:
metaReaderClear(&mr);
taosArrayDestroy(pSmaIds);
- tdFreeTSmaWrapper(pSW, deepCopy);
+ tFreeTSmaWrapper(pSW, deepCopy);
return NULL;
}
diff --git a/source/dnode/vnode/src/meta/metaTable.c b/source/dnode/vnode/src/meta/metaTable.c
index 4e0b4b8b44..6d4441e2e8 100644
--- a/source/dnode/vnode/src/meta/metaTable.c
+++ b/source/dnode/vnode/src/meta/metaTable.c
@@ -25,6 +25,24 @@ static int metaUpdateCtbIdx(SMeta *pMeta, const SMetaEntry *pME);
static int metaUpdateTagIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry);
static int metaDropTableByUid(SMeta *pMeta, tb_uid_t uid, int *type);
+static int metaUpdateMetaRsp(tb_uid_t uid, char* tbName, SSchemaWrapper *pSchema, STableMetaRsp *pMetaRsp) {
+ pMetaRsp->pSchemas = taosMemoryMalloc(pSchema->nCols * sizeof(SSchema));
+ if (NULL == pMetaRsp->pSchemas) {
+ terrno = TSDB_CODE_VND_OUT_OF_MEMORY;
+ return -1;
+ }
+
+ strcpy(pMetaRsp->tbName, tbName);
+ pMetaRsp->numOfColumns = pSchema->nCols;
+ pMetaRsp->tableType = TSDB_NORMAL_TABLE;
+ pMetaRsp->sversion = pSchema->version;
+ pMetaRsp->tuid = uid;
+
+ memcpy(pMetaRsp->pSchemas, pSchema->pSchema, pSchema->nCols * sizeof(SSchema));
+
+ return 0;
+}
+
int metaCreateSTable(SMeta *pMeta, int64_t version, SVCreateStbReq *pReq) {
SMetaEntry me = {0};
int kLen = 0;
@@ -323,7 +341,8 @@ static int metaDropTableByUid(SMeta *pMeta, tb_uid_t uid, int *type) {
return 0;
}
-static int metaAlterTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pAlterTbReq) {
+
+static int metaAlterTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pAlterTbReq, STableMetaRsp *pMetaRsp) {
void * pVal = NULL;
int nVal = 0;
const void * pData = NULL;
@@ -463,6 +482,8 @@ static int metaAlterTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pAl
metaULock(pMeta);
+ metaUpdateMetaRsp(uid, pAlterTbReq->tbName, pSchema, pMetaRsp);
+
if (pNewSchema) taosMemoryFree(pNewSchema);
tDecoderClear(&dc);
tdbTbcClose(pTbDbc);
@@ -584,7 +605,7 @@ static int metaUpdateTableTagVal(SMeta *pMeta, int64_t version, SVAlterTbReq *pA
}
taosArrayPush(pTagArray, &val);
} else {
- STagVal val = {0};
+ STagVal val = {.cid = pCol->colId};
if (tTagGet(pOldTag, &val)) {
taosArrayPush(pTagArray, &val);
}
@@ -629,13 +650,13 @@ static int metaUpdateTableOptions(SMeta *pMeta, int64_t version, SVAlterTbReq *p
return 0;
}
-int metaAlterTable(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq) {
+int metaAlterTable(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq, STableMetaRsp *pMetaRsp) {
switch (pReq->action) {
case TSDB_ALTER_TABLE_ADD_COLUMN:
case TSDB_ALTER_TABLE_DROP_COLUMN:
case TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES:
case TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME:
- return metaAlterTableColumn(pMeta, version, pReq);
+ return metaAlterTableColumn(pMeta, version, pReq, pMetaRsp);
case TSDB_ALTER_TABLE_UPDATE_TAG_VAL:
return metaUpdateTableTagVal(pMeta, version, pReq);
case TSDB_ALTER_TABLE_UPDATE_OPTIONS:
diff --git a/source/dnode/vnode/src/sma/sma.c b/source/dnode/vnode/src/sma/sma.c
index 7a2b6a2757..a09e9b99ea 100644
--- a/source/dnode/vnode/src/sma/sma.c
+++ b/source/dnode/vnode/src/sma/sma.c
@@ -51,3 +51,11 @@ int32_t tdGetTSmaData(SSma* pSma, char* pData, int64_t indexUid, TSKEY querySKey
}
return code;
}
+
+int32_t smaGetTSmaDays(SVnodeCfg* pCfg, void* pCont, uint32_t contLen, int32_t *days) {
+ int32_t code = TSDB_CODE_SUCCESS;
+ if ((code = tdGetTSmaDaysImpl(pCfg, pCont, contLen, days)) < 0) {
+ smaWarn("vgId:%d get tSma days failed since %s", pCfg->vgId, tstrerror(terrno));
+ }
+ return code;
+}
diff --git a/source/dnode/vnode/src/sma/smaEnv.c b/source/dnode/vnode/src/sma/smaEnv.c
index 8285b74e50..531feaf861 100644
--- a/source/dnode/vnode/src/sma/smaEnv.c
+++ b/source/dnode/vnode/src/sma/smaEnv.c
@@ -278,7 +278,7 @@ static int32_t tdInitSmaStat(SSmaStat **pSmaStat, int8_t smaType) {
void *tdFreeSmaStatItem(SSmaStatItem *pSmaStatItem) {
if (pSmaStatItem) {
- tdDestroyTSma(pSmaStatItem->pTSma);
+ tDestroyTSma(pSmaStatItem->pTSma);
taosMemoryFreeClear(pSmaStatItem->pTSma);
taosHashCleanup(pSmaStatItem->expiredWindows);
taosMemoryFreeClear(pSmaStatItem);
diff --git a/source/dnode/vnode/src/sma/smaTimeRange.c b/source/dnode/vnode/src/sma/smaTimeRange.c
index f88afcaddf..0b41778c87 100644
--- a/source/dnode/vnode/src/sma/smaTimeRange.c
+++ b/source/dnode/vnode/src/sma/smaTimeRange.c
@@ -828,7 +828,7 @@ int32_t tdDropTSma(SSma *pSma, char *pMsg) {
// TODO: send msg to stream computing to drop tSma
// if ((send msg to stream computing) < 0) {
- // tdDestroyTSma(&vCreateSmaReq);
+ // tDestroyTSma(&vCreateSmaReq);
// return -1;
// }
//
@@ -982,25 +982,25 @@ int32_t tdUpdateExpiredWindowImpl(SSma *pSma, const SSubmitReq *pMsg, int64_t ve
SSubmitBlkIter blkIter = {0};
if (tInitSubmitBlkIter(&msgIter, pBlock, &blkIter) < 0) {
- pSW = tdFreeTSmaWrapper(pSW, false);
+ pSW = tFreeTSmaWrapper(pSW, false);
break;
}
while (true) {
STSRow *row = tGetSubmitBlkNext(&blkIter);
if (!row) {
- pSW = tdFreeTSmaWrapper(pSW, false);
+ pSW = tFreeTSmaWrapper(pSW, false);
break;
}
if (!pSW || (pTSma && (pTSma->tableUid != msgIter.suid))) {
if (pSW) {
- pSW = tdFreeTSmaWrapper(pSW, false);
+ pSW = tFreeTSmaWrapper(pSW, false);
}
if (!(pSW = metaGetSmaInfoByTable(SMA_META(pSma), msgIter.suid, false))) {
break;
}
if ((pSW->number) <= 0 || !pSW->tSma) {
- pSW = tdFreeTSmaWrapper(pSW, false);
+ pSW = tFreeTSmaWrapper(pSW, false);
break;
}
@@ -1020,7 +1020,7 @@ int32_t tdUpdateExpiredWindowImpl(SSma *pSma, const SSubmitReq *pMsg, int64_t ve
if (lastWinSKey != winSKey) {
lastWinSKey = winSKey;
if (tdSetExpiredWindow(pSma, pItemsHash, pTSma->indexUid, winSKey, version) < 0) {
- pSW = tdFreeTSmaWrapper(pSW, false);
+ pSW = tFreeTSmaWrapper(pSW, false);
tdUnRefSmaStat(pSma, pStat);
return TSDB_CODE_FAILED;
}
diff --git a/source/dnode/vnode/src/sma/smaTimeRange2.c b/source/dnode/vnode/src/sma/smaTimeRange2.c
new file mode 100644
index 0000000000..5ef171c799
--- /dev/null
+++ b/source/dnode/vnode/src/sma/smaTimeRange2.c
@@ -0,0 +1,1084 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include "sma.h"
+#include "tsdb.h"
+
+typedef STsdbCfg STSmaKeepCfg;
+
+#undef _TEST_SMA_PRINT_DEBUG_LOG_
+#define SMA_STORAGE_MINUTES_MAX 86400
+#define SMA_STORAGE_MINUTES_DAY 1440
+#define SMA_STORAGE_MINUTES_MIN 1440
+#define SMA_STORAGE_TSDB_MINUTES 86400
+#define SMA_STORAGE_TSDB_TIMES 10
+#define SMA_STORAGE_SPLIT_FACTOR 14400 // least records in tsma file TODO: the feasible value?
+#define SMA_KEY_LEN 16 // TSKEY+groupId 8+8
+#define SMA_DROP_EXPIRED_TIME 10 // default is 10 seconds
+
+#define SMA_STATE_ITEM_HASH_SLOT 32
+
+typedef struct {
+ SSma *pSma;
+ SDBFile dFile;
+ const SArray *pDataBlocks; // sma data
+ int64_t interval; // interval with the precision of DB
+} STSmaWriteH;
+
+typedef struct {
+ int32_t iter;
+ int32_t fid;
+} SmaFsIter;
+
+typedef struct {
+ STsdb *pTsdb;
+ SSma *pSma;
+ SDBFile dFile;
+ int64_t interval; // interval with the precision of DB
+ int32_t blockSize; // size of SMA block item
+ int32_t days;
+ int8_t storageLevel;
+ SmaFsIter smaFsIter;
+} STSmaReadH;
+
+typedef enum {
+ SMA_STORAGE_LEVEL_TSDB = 0, // use days of self-defined e.g. vnode${N}/tsdb/tsma/sma_index_uid/v2f200.tsma
+ SMA_STORAGE_LEVEL_DFILESET = 1 // use days of TS data e.g. vnode${N}/tsdb/tsma/sma_index_uid/v2f1906.tsma
+} ESmaStorageLevel;
+
+// static func
+
+static int64_t tdGetIntervalByPrecision(int64_t interval, uint8_t intervalUnit, int8_t precision, bool adjusted);
+static int32_t tdGetSmaStorageLevel(STSmaKeepCfg *pCfg, int64_t interval);
+static int32_t tdInitTSmaWriteH(STSmaWriteH *pSmaH, SSma *pSma, const SArray *pDataBlocks, int64_t interval,
+ int8_t intervalUnit);
+static int32_t tdInitTSmaReadH(STSmaReadH *pSmaH, SSma *pSma, int64_t interval, int8_t intervalUnit);
+static void tdDestroyTSmaWriteH(STSmaWriteH *pSmaH);
+static int32_t tdGetTSmaDays(SSma *pSma, int64_t interval, int32_t storageLevel);
+static int32_t tdSetTSmaDataFile(STSmaWriteH *pSmaH, int64_t indexUid, int32_t fid);
+static int32_t tdInitTSmaFile(STSmaReadH *pSmaH, int64_t indexUid, TSKEY skey);
+static bool tdSetAndOpenTSmaFile(STSmaReadH *pReadH, TSKEY *queryKey);
+static int32_t tdInsertTSmaBlocks(STSmaWriteH *pSmaH, void *smaKey, int32_t keyLen, void *pData, int32_t dataLen,
+ TXN *txn);
+// expired window
+
+static int32_t tdSetExpiredWindow(SSma *pSma, SHashObj *pItemsHash, int64_t indexUid, int64_t winSKey, int64_t version);
+static int32_t tdResetExpiredWindow(SSma *pSma, SSmaStat *pStat, int64_t indexUid, TSKEY skey);
+static int32_t tdDropTSmaDataImpl(SSma *pSma, int64_t indexUid);
+
+/**
+ * @brief Judge the tsma file split days
+ *
+ * @param pCfg
+ * @param pCont
+ * @param contLen
+ * @param days unit is minute
+ * @return int32_t
+ */
+int32_t tdGetTSmaDaysImpl(SVnodeCfg *pCfg, void *pCont, uint32_t contLen, int32_t *days) {
+ SDecoder coder = {0};
+ tDecoderInit(&coder, pCont, contLen);
+
+ STSma tsma = {0};
+ if (tDecodeSVCreateTSmaReq(&coder, &tsma) < 0) {
+ terrno = TSDB_CODE_MSG_DECODE_ERROR;
+ goto _err;
+ }
+ STsdbCfg *pTsdbCfg = &pCfg->tsdbCfg;
+ int64_t mInterval = convertTimeFromPrecisionToUnit(tsma.interval, pTsdbCfg->precision, TIME_UNIT_MINUTE);
+ int64_t records = pTsdbCfg->days / mInterval;
+
+ if (records >= SMA_STORAGE_SPLIT_FACTOR) {
+ *days = pTsdbCfg->days;
+ } else {
+ int64_t daysPerFile = mInterval * SMA_STORAGE_MINUTES_DAY * 2;
+
+ if (daysPerFile > SMA_STORAGE_MINUTES_MAX) {
+ *days = SMA_STORAGE_MINUTES_MAX;
+ } else {
+ *days = (int32_t)daysPerFile;
+ }
+
+ if(*days < pTsdbCfg->days) {
+ *days = pTsdbCfg->days;
+ }
+ }
+ tDecoderClear(&coder);
+ return 0;
+_err:
+ tDecoderClear(&coder);
+ return -1;
+}
+
+// read data
+
+// implementation
+
+/**
+ * @brief
+ *
+ * @param pSmaH
+ * @param pSma
+ * @param interval
+ * @param intervalUnit
+ * @return int32_t
+ */
+static int32_t tdInitTSmaReadH(STSmaReadH *pSmaH, SSma *pSma, int64_t interval, int8_t intervalUnit) {
+ STSmaKeepCfg *pCfg = SMA_TSDB_CFG(pSma);
+ pSmaH->pSma = pSma;
+ pSmaH->interval = tdGetIntervalByPrecision(interval, intervalUnit, SMA_TSDB_CFG(pSma)->precision, true);
+ pSmaH->storageLevel = tdGetSmaStorageLevel(pCfg, interval);
+ pSmaH->days = tdGetTSmaDays(pSma, pSmaH->interval, pSmaH->storageLevel);
+ return TSDB_CODE_SUCCESS;
+}
+
+/**
+ * @brief Init of tSma FS
+ *
+ * @param pReadH
+ * @param indexUid
+ * @param skey
+ * @return int32_t
+ */
+static int32_t tdInitTSmaFile(STSmaReadH *pSmaH, int64_t indexUid, TSKEY skey) {
+ SSma *pSma = pSmaH->pSma;
+
+ int32_t fid = (int32_t)(TSDB_KEY_FID(skey, pSmaH->days, SMA_TSDB_CFG(pSma)->precision));
+ char tSmaFile[TSDB_FILENAME_LEN] = {0};
+ snprintf(tSmaFile, TSDB_FILENAME_LEN, "%" PRIi64 "%sv%df%d.tsma", indexUid, TD_DIRSEP, SMA_VID(pSma), fid);
+ pSmaH->dFile.path = strdup(tSmaFile);
+ pSmaH->smaFsIter.iter = 0;
+ pSmaH->smaFsIter.fid = fid;
+ return TSDB_CODE_SUCCESS;
+}
+
+/**
+ * @brief Set and open tSma file if it has key locates in queryWin.
+ *
+ * @param pReadH
+ * @param param
+ * @param queryWin
+ * @return true
+ * @return false
+ */
+static bool tdSetAndOpenTSmaFile(STSmaReadH *pReadH, TSKEY *queryKey) {
+ // SArray *smaFs = pReadH->pTsdb->fs->cstatus->sf;
+ // int32_t nSmaFs = taosArrayGetSize(smaFs);
+
+ smaCloseDBF(&pReadH->dFile);
+
+#if 0
+ while (pReadH->smaFsIter.iter < nSmaFs) {
+ void *pSmaFile = taosArrayGet(smaFs, pReadH->smaFsIter.iter);
+ if (pSmaFile) { // match(indexName, queryWindow)
+ // TODO: select the file by index_name ...
+ pReadH->dFile = pSmaFile;
+ ++pReadH->smaFsIter.iter;
+ break;
+ }
+ ++pReadH->smaFsIter.iter;
+ }
+
+ if (pReadH->pDFile) {
+ tdDebug("vg%d: smaFile %s matched", REPO_ID(pReadH->pTsdb), "[pSmaFile dir]");
+ return true;
+ }
+#endif
+
+ return false;
+}
+
+/**
+ * @brief Approximate value for week/month/year.
+ *
+ * @param interval
+ * @param intervalUnit
+ * @param precision
+ * @param adjusted Interval already adjusted according to DB precision
+ * @return int64_t
+ */
+static int64_t tdGetIntervalByPrecision(int64_t interval, uint8_t intervalUnit, int8_t precision, bool adjusted) {
+ if (adjusted) {
+ return interval;
+ }
+
+ switch (intervalUnit) {
+ case TIME_UNIT_YEAR: // approximate value
+ interval *= 365 * 86400 * 1e3;
+ break;
+ case TIME_UNIT_MONTH: // approximate value
+ interval *= 30 * 86400 * 1e3;
+ break;
+ case TIME_UNIT_WEEK: // approximate value
+ interval *= 7 * 86400 * 1e3;
+ break;
+ case TIME_UNIT_DAY: // the interval for tSma calculation must <= day
+ interval *= 86400 * 1e3;
+ break;
+ case TIME_UNIT_HOUR:
+ interval *= 3600 * 1e3;
+ break;
+ case TIME_UNIT_MINUTE:
+ interval *= 60 * 1e3;
+ break;
+ case TIME_UNIT_SECOND:
+ interval *= 1e3;
+ break;
+ default:
+ break;
+ }
+
+ switch (precision) {
+ case TSDB_TIME_PRECISION_MILLI:
+ if (TIME_UNIT_MICROSECOND == intervalUnit) { // us
+ return interval / 1e3;
+ } else if (TIME_UNIT_NANOSECOND == intervalUnit) { // nano second
+ return interval / 1e6;
+ } else { // ms
+ return interval;
+ }
+ break;
+ case TSDB_TIME_PRECISION_MICRO:
+ if (TIME_UNIT_MICROSECOND == intervalUnit) { // us
+ return interval;
+ } else if (TIME_UNIT_NANOSECOND == intervalUnit) { // ns
+ return interval / 1e3;
+ } else { // ms
+ return interval * 1e3;
+ }
+ break;
+ case TSDB_TIME_PRECISION_NANO:
+ if (TIME_UNIT_MICROSECOND == intervalUnit) { // us
+ return interval * 1e3;
+ } else if (TIME_UNIT_NANOSECOND == intervalUnit) { // ns
+ return interval;
+ } else { // ms
+ return interval * 1e6;
+ }
+ break;
+ default: // ms
+ if (TIME_UNIT_MICROSECOND == intervalUnit) { // us
+ return interval / 1e3;
+ } else if (TIME_UNIT_NANOSECOND == intervalUnit) { // ns
+ return interval / 1e6;
+ } else { // ms
+ return interval;
+ }
+ break;
+ }
+ return interval;
+}
+
+static int32_t tdInitTSmaWriteH(STSmaWriteH *pSmaH, SSma *pSma, const SArray *pDataBlocks, int64_t interval,
+ int8_t intervalUnit) {
+ pSmaH->pSma = pSma;
+ pSmaH->interval = tdGetIntervalByPrecision(interval, intervalUnit, SMA_TSDB_CFG(pSma)->precision, true);
+ pSmaH->pDataBlocks = pDataBlocks;
+ pSmaH->dFile.fid = SMA_IVLD_FID;
+ return TSDB_CODE_SUCCESS;
+}
+
+static void tdDestroyTSmaWriteH(STSmaWriteH *pSmaH) {
+ if (pSmaH) {
+ smaCloseDBF(&pSmaH->dFile);
+ }
+}
+
+static int32_t tdSetTSmaDataFile(STSmaWriteH *pSmaH, int64_t indexUid, int32_t fid) {
+ SSma *pSma = pSmaH->pSma;
+ ASSERT(!pSmaH->dFile.path && !pSmaH->dFile.pDB);
+
+ pSmaH->dFile.fid = fid;
+ char tSmaFile[TSDB_FILENAME_LEN] = {0};
+ snprintf(tSmaFile, TSDB_FILENAME_LEN, "%" PRIi64 "%sv%df%d.tsma", indexUid, TD_DIRSEP, SMA_VID(pSma), fid);
+ pSmaH->dFile.path = strdup(tSmaFile);
+
+ return TSDB_CODE_SUCCESS;
+}
+
+/**
+ * @brief
+ *
+ * @param pSma
+ * @param interval Interval calculated by DB's precision
+ * @param storageLevel
+ * @return int32_t
+ */
+static int32_t tdGetTSmaDays(SSma *pSma, int64_t interval, int32_t storageLevel) {
+ STsdbCfg *pCfg = SMA_TSDB_CFG(pSma);
+ int32_t daysPerFile = pCfg->days; // unit is minute
+
+ if (storageLevel == SMA_STORAGE_LEVEL_TSDB) {
+ int32_t minutes = SMA_STORAGE_TSDB_TIMES * (interval / tsTickPerMin[pCfg->precision]);
+ if (minutes > SMA_STORAGE_TSDB_MINUTES) {
+ daysPerFile = SMA_STORAGE_TSDB_MINUTES;
+ }
+ }
+
+ return daysPerFile;
+}
+
+/**
+ * @brief Judge the tSma storage level
+ *
+ * @param pCfg
+ * @param interval
+ * @return int32_t
+ */
+static int32_t tdGetSmaStorageLevel(STSmaKeepCfg *pCfg, int64_t interval) {
+ int64_t mInterval = convertTimeFromPrecisionToUnit(interval, pCfg->precision, TIME_UNIT_MINUTE);
+ if (pCfg->days / mInterval >= SMA_STORAGE_SPLIT_FACTOR) {
+ return SMA_STORAGE_LEVEL_DFILESET;
+ }
+ return SMA_STORAGE_LEVEL_TSDB;
+}
+
+/**
+ * @brief Insert/Update Time-range-wise SMA data.
+ * - If interval < SMA_STORAGE_SPLIT_HOURS(e.g. 24), save the SMA data as a part of DFileSet to e.g.
+ * v3f1900.tsma.${sma_index_name}. The days is the same with that for TS data files.
+ * - If interval >= SMA_STORAGE_SPLIT_HOURS, save the SMA data to e.g. vnode3/tsma/v3f632.tsma.${sma_index_name}. The
+ * days is 30 times of the interval, and the minimum days is SMA_STORAGE_TSDB_DAYS(30d).
+ * - The destination file of one data block for some interval is determined by its start TS key.
+ *
+ * @param pSma
+ * @param msg
+ * @return int32_t
+ */
+int32_t tdProcessTSmaInsertImpl(SSma *pSma, int64_t indexUid, const char *msg) {
+ STsdbCfg *pCfg = SMA_TSDB_CFG(pSma);
+ const SArray *pDataBlocks = (const SArray *)msg;
+ int64_t testSkey = TSKEY_INITIAL_VAL;
+
+ // TODO: destroy SSDataBlocks(msg)
+
+ // For super table aggregation, the sma data is stored in vgroup calculated from the hash value of stable name. Thus
+ // the sma data would arrive ahead of the update-expired-window msg.
+ if (tdCheckAndInitSmaEnv(pSma, TSDB_SMA_TYPE_TIME_RANGE) != TSDB_CODE_SUCCESS) {
+ terrno = TSDB_CODE_TDB_INIT_FAILED;
+ return TSDB_CODE_FAILED;
+ }
+
+ if (!pDataBlocks) {
+ terrno = TSDB_CODE_INVALID_PTR;
+ smaWarn("vgId:%d insert tSma data failed since pDataBlocks is NULL", SMA_VID(pSma));
+ return terrno;
+ }
+
+ if (taosArrayGetSize(pDataBlocks) <= 0) {
+ terrno = TSDB_CODE_INVALID_PARA;
+ smaWarn("vgId:%d insert tSma data failed since pDataBlocks is empty", SMA_VID(pSma));
+ return TSDB_CODE_FAILED;
+ }
+
+ SSmaEnv *pEnv = SMA_TSMA_ENV(pSma);
+ SSmaStat *pStat = SMA_ENV_STAT(pEnv);
+ SSmaStatItem *pItem = NULL;
+
+ tdRefSmaStat(pSma, pStat);
+
+ if (pStat && SMA_STAT_ITEMS(pStat)) {
+ pItem = taosHashGet(SMA_STAT_ITEMS(pStat), &indexUid, sizeof(indexUid));
+ }
+
+ if (!pItem || !(pItem = *(SSmaStatItem **)pItem) || tdSmaStatIsDropped(pItem)) {
+ terrno = TSDB_CODE_TDB_INVALID_SMA_STAT;
+ tdUnRefSmaStat(pSma, pStat);
+ return TSDB_CODE_FAILED;
+ }
+
+ STSma *pTSma = pItem->pTSma;
+ STSmaWriteH tSmaH = {0};
+
+ if (tdInitTSmaWriteH(&tSmaH, pSma, pDataBlocks, pTSma->interval, pTSma->intervalUnit) != 0) {
+ return TSDB_CODE_FAILED;
+ }
+
+ char rPath[TSDB_FILENAME_LEN] = {0};
+ char aPath[TSDB_FILENAME_LEN] = {0};
+ snprintf(rPath, TSDB_FILENAME_LEN, "%s%s%" PRIi64, SMA_ENV_PATH(pEnv), TD_DIRSEP, indexUid);
+ tfsAbsoluteName(SMA_TFS(pSma), SMA_ENV_DID(pEnv), rPath, aPath);
+ if (!taosCheckExistFile(aPath)) {
+ if (tfsMkdirRecurAt(SMA_TFS(pSma), rPath, SMA_ENV_DID(pEnv)) != TSDB_CODE_SUCCESS) {
+ tdUnRefSmaStat(pSma, pStat);
+ return TSDB_CODE_FAILED;
+ }
+ }
+
+ // Step 1: Judge the storage level and days
+ int32_t storageLevel = tdGetSmaStorageLevel(pCfg, tSmaH.interval);
+ int32_t minutePerFile = tdGetTSmaDays(pSma, tSmaH.interval, storageLevel);
+
+ char smaKey[SMA_KEY_LEN] = {0}; // key: skey + groupId
+ char dataBuf[512] = {0}; // val: aggr data // TODO: handle 512 buffer?
+ void *pDataBuf = NULL;
+ int32_t sz = taosArrayGetSize(pDataBlocks);
+ for (int32_t i = 0; i < sz; ++i) {
+ SSDataBlock *pDataBlock = taosArrayGet(pDataBlocks, i);
+ int32_t colNum = pDataBlock->info.numOfCols;
+ int32_t rows = pDataBlock->info.rows;
+ int32_t rowSize = pDataBlock->info.rowSize;
+ int64_t groupId = pDataBlock->info.groupId;
+ for (int32_t j = 0; j < rows; ++j) {
+ printf("|");
+ TSKEY skey = TSKEY_INITIAL_VAL; // the start key of TS window by interval
+ void *pSmaKey = &smaKey;
+ bool isStartKey = false;
+
+ int32_t tlen = 0; // reset the len
+ pDataBuf = &dataBuf; // reset the buf
+ for (int32_t k = 0; k < colNum; ++k) {
+ SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock->pDataBlock, k);
+ void *var = POINTER_SHIFT(pColInfoData->pData, j * pColInfoData->info.bytes);
+ switch (pColInfoData->info.type) {
+ case TSDB_DATA_TYPE_TIMESTAMP:
+ if (!isStartKey) {
+ isStartKey = true;
+ skey = *(TSKEY *)var;
+ testSkey = skey;
+ printf("= skey %" PRIi64 " groupId = %" PRIi64 "|", skey, groupId);
+ tdEncodeTSmaKey(groupId, skey, &pSmaKey);
+ } else {
+ printf(" %" PRIi64 " |", *(int64_t *)var);
+ tlen += taosEncodeFixedI64(&pDataBuf, *(int64_t *)var);
+ break;
+ }
+ break;
+ case TSDB_DATA_TYPE_BOOL:
+ case TSDB_DATA_TYPE_UTINYINT:
+ printf(" %15d |", *(uint8_t *)var);
+ tlen += taosEncodeFixedU8(&pDataBuf, *(uint8_t *)var);
+ break;
+ case TSDB_DATA_TYPE_TINYINT:
+ printf(" %15d |", *(int8_t *)var);
+ tlen += taosEncodeFixedI8(&pDataBuf, *(int8_t *)var);
+ break;
+ case TSDB_DATA_TYPE_SMALLINT:
+ printf(" %15d |", *(int16_t *)var);
+ tlen += taosEncodeFixedI16(&pDataBuf, *(int16_t *)var);
+ break;
+ case TSDB_DATA_TYPE_USMALLINT:
+ printf(" %15d |", *(uint16_t *)var);
+ tlen += taosEncodeFixedU16(&pDataBuf, *(uint16_t *)var);
+ break;
+ case TSDB_DATA_TYPE_INT:
+ printf(" %15d |", *(int32_t *)var);
+ tlen += taosEncodeFixedI32(&pDataBuf, *(int32_t *)var);
+ break;
+ case TSDB_DATA_TYPE_FLOAT:
+ printf(" %15f |", *(float *)var);
+ tlen += taosEncodeBinary(&pDataBuf, var, sizeof(float));
+ break;
+ case TSDB_DATA_TYPE_UINT:
+ printf(" %15u |", *(uint32_t *)var);
+ tlen += taosEncodeFixedU32(&pDataBuf, *(uint32_t *)var);
+ break;
+ case TSDB_DATA_TYPE_BIGINT:
+ printf(" %15ld |", *(int64_t *)var);
+ tlen += taosEncodeFixedI64(&pDataBuf, *(int64_t *)var);
+ break;
+ case TSDB_DATA_TYPE_DOUBLE:
+ printf(" %15lf |", *(double *)var);
+ tlen += taosEncodeBinary(&pDataBuf, var, sizeof(double));
+ case TSDB_DATA_TYPE_UBIGINT:
+ printf(" %15lu |", *(uint64_t *)var);
+ tlen += taosEncodeFixedU64(&pDataBuf, *(uint64_t *)var);
+ break;
+ case TSDB_DATA_TYPE_NCHAR: {
+ char tmpChar[100] = {0};
+ strncpy(tmpChar, varDataVal(var), varDataLen(var));
+ printf(" %s |", tmpChar);
+ tlen += taosEncodeBinary(&pDataBuf, varDataVal(var), varDataLen(var));
+ break;
+ }
+ case TSDB_DATA_TYPE_VARCHAR: { // TSDB_DATA_TYPE_BINARY
+ char tmpChar[100] = {0};
+ strncpy(tmpChar, varDataVal(var), varDataLen(var));
+ printf(" %s |", tmpChar);
+ tlen += taosEncodeBinary(&pDataBuf, varDataVal(var), varDataLen(var));
+ break;
+ }
+ case TSDB_DATA_TYPE_VARBINARY:
+ // TODO: add binary/varbinary
+ TASSERT(0);
+ default:
+ printf("the column type %" PRIi16 " is undefined\n", pColInfoData->info.type);
+ TASSERT(0);
+ break;
+ }
+ }
+ printf("\n");
+ // if ((tlen > 0) && (skey != TSKEY_INITIAL_VAL)) {
+ if (tlen > 0) {
+ int32_t fid = (int32_t)(TSDB_KEY_FID(skey, minutePerFile, pCfg->precision));
+
+ // Step 2: Set the DFile for storage of SMA index, and iterate/split the TSma data and store to B+Tree index
+ // file
+ // - Set and open the DFile or the B+Tree file
+ // TODO: tsdbStartTSmaCommit();
+ if (fid != tSmaH.dFile.fid) {
+ if (tSmaH.dFile.fid != SMA_IVLD_FID) {
+ tdSmaEndCommit(pEnv);
+ smaCloseDBF(&tSmaH.dFile);
+ }
+ tdSetTSmaDataFile(&tSmaH, indexUid, fid);
+ smaDebug("@@@ vgId:%d write to DBF %s, days:%d, interval:%" PRIi64 ", storageLevel:%" PRIi32
+ " queryKey:%" PRIi64,
+ SMA_VID(pSma), tSmaH.dFile.path, minutePerFile, tSmaH.interval, storageLevel, testSkey);
+ if (smaOpenDBF(pEnv->dbEnv, &tSmaH.dFile) != 0) {
+ smaWarn("vgId:%d open DB file %s failed since %s", SMA_VID(pSma),
+ tSmaH.dFile.path ? tSmaH.dFile.path : "path is NULL", tstrerror(terrno));
+ tdDestroyTSmaWriteH(&tSmaH);
+ tdUnRefSmaStat(pSma, pStat);
+ return TSDB_CODE_FAILED;
+ }
+ tdSmaBeginCommit(pEnv);
+ }
+
+ if (tdInsertTSmaBlocks(&tSmaH, &smaKey, SMA_KEY_LEN, dataBuf, tlen, &pEnv->txn) != 0) {
+ smaWarn("vgId:%d insert tsma data blocks fail for index %" PRIi64 ", skey %" PRIi64 ", groupId %" PRIi64
+ " since %s",
+ SMA_VID(pSma), indexUid, skey, groupId, tstrerror(terrno));
+ tdSmaEndCommit(pEnv);
+ tdDestroyTSmaWriteH(&tSmaH);
+ tdUnRefSmaStat(pSma, pStat);
+ return TSDB_CODE_FAILED;
+ }
+
+ smaDebug("vgId:%d insert tsma data blocks success for index %" PRIi64 ", skey %" PRIi64 ", groupId %" PRIi64,
+ SMA_VID(pSma), indexUid, skey, groupId);
+ // TODO:tsdbEndTSmaCommit();
+
+ // Step 3: reset the SSmaStat
+ tdResetExpiredWindow(pSma, pStat, indexUid, skey);
+ } else {
+ smaWarn("vgId:%d invalid data skey:%" PRIi64 ", tlen %" PRIi32 " during insert tSma data for %" PRIi64,
+ SMA_VID(pSma), skey, tlen, indexUid);
+ }
+ }
+ }
+ tdSmaEndCommit(pEnv); // TODO: not commit for every insert
+ tdDestroyTSmaWriteH(&tSmaH);
+ tdUnRefSmaStat(pSma, pStat);
+
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t tdDropTSmaData(SSma *pSma, int64_t indexUid) {
+ int32_t code = TSDB_CODE_SUCCESS;
+ if ((code = tdDropTSmaDataImpl(pSma, indexUid)) < 0) {
+ smaWarn("vgId:%d drop tSma data failed since %s", SMA_VID(pSma), tstrerror(terrno));
+ }
+ return code;
+}
+
+/**
+ * @brief Insert TSma data blocks to DB File build by B+Tree
+ *
+ * @param pSmaH
+ * @param smaKey tableUid-colId-skeyOfWindow(8-2-8)
+ * @param keyLen
+ * @param pData
+ * @param dataLen
+ * @return int32_t
+ */
+static int32_t tdInsertTSmaBlocks(STSmaWriteH *pSmaH, void *smaKey, int32_t keyLen, void *pData, int32_t dataLen,
+ TXN *txn) {
+ SDBFile *pDBFile = &pSmaH->dFile;
+
+ // TODO: insert tsma data blocks into B+Tree(TTB)
+ if (smaSaveSmaToDB(pDBFile, smaKey, keyLen, pData, dataLen, txn) != 0) {
+ smaWarn("vgId:%d insert tsma data blocks into %s: smaKey %" PRIx64 "-%" PRIx64 ", dataLen %" PRIu32 " fail",
+ SMA_VID(pSmaH->pSma), pDBFile->path, *(int64_t *)smaKey, *(int64_t *)POINTER_SHIFT(smaKey, 8), dataLen);
+ return TSDB_CODE_FAILED;
+ }
+ smaDebug("vgId:%d insert tsma data blocks into %s: smaKey %" PRIx64 "-%" PRIx64 ", dataLen %" PRIu32 " succeed",
+ SMA_VID(pSmaH->pSma), pDBFile->path, *(int64_t *)smaKey, *(int64_t *)POINTER_SHIFT(smaKey, 8), dataLen);
+
+#ifdef _TEST_SMA_PRINT_DEBUG_LOG_
+ uint32_t valueSize = 0;
+ void *data = tdGetSmaDataByKey(pDBFile, smaKey, keyLen, &valueSize);
+ ASSERT(data != NULL);
+ for (uint32_t v = 0; v < valueSize; v += 8) {
+ smaWarn("vgId:%d insert sma data val[%d] %" PRIi64, REPO_ID(pSmaH->pTsdb), v, *(int64_t *)POINTER_SHIFT(data, v));
+ }
+#endif
+ return TSDB_CODE_SUCCESS;
+}
+
+/**
+ * @brief When sma data received from stream computing, make the relative expired window valid.
+ *
+ * @param pSma
+ * @param pStat
+ * @param indexUid
+ * @param skey
+ * @return int32_t
+ */
+static int32_t tdResetExpiredWindow(SSma *pSma, SSmaStat *pStat, int64_t indexUid, TSKEY skey) {
+ SSmaStatItem *pItem = NULL;
+
+ tdRefSmaStat(pSma, pStat);
+
+ if (pStat && SMA_STAT_ITEMS(pStat)) {
+ pItem = taosHashGet(SMA_STAT_ITEMS(pStat), &indexUid, sizeof(indexUid));
+ }
+ if ((pItem) && ((pItem = *(SSmaStatItem **)pItem))) {
+ // pItem resides in hash buffer all the time unless drop sma index
+ // TODO: multithread protect
+ if (taosHashRemove(pItem->expiredWindows, &skey, sizeof(TSKEY)) != 0) {
+ // error handling
+ tdUnRefSmaStat(pSma, pStat);
+ smaWarn("vgId:%d remove skey %" PRIi64 " from expired window for sma index %" PRIi64 " fail", SMA_VID(pSma), skey,
+ indexUid);
+ return TSDB_CODE_FAILED;
+ }
+ smaDebug("vgId:%d remove skey %" PRIi64 " from expired window for sma index %" PRIi64 " succeed", SMA_VID(pSma),
+ skey, indexUid);
+ // TODO: use a standalone interface to received state upate notification from stream computing module.
+ /**
+ * @brief state
+ * - When SMA env init in TSDB, its status is TSDB_SMA_STAT_OK.
+ * - In startup phase of stream computing module, it should notify the SMA env in TSDB to expired if needed(e.g.
+ * when batch data caculation not finised)
+ * - When TSDB_SMA_STAT_OK, the stream computing module should also notify that to the SMA env in TSDB.
+ */
+ pItem->state = TSDB_SMA_STAT_OK;
+ } else {
+ // error handling
+ tdUnRefSmaStat(pSma, pStat);
+ smaWarn("vgId:%d expired window %" PRIi64 " not exists for sma index %" PRIi64, SMA_VID(pSma), skey, indexUid);
+ return TSDB_CODE_FAILED;
+ }
+
+ tdUnRefSmaStat(pSma, pStat);
+ return TSDB_CODE_SUCCESS;
+}
+
+/**
+ * @brief Drop tSma data and local cache
+ * - insert/query reference
+ * @param pSma
+ * @param msg
+ * @return int32_t
+ */
+static int32_t tdDropTSmaDataImpl(SSma *pSma, int64_t indexUid) {
+ SSmaEnv *pEnv = atomic_load_ptr(&SMA_TSMA_ENV(pSma));
+
+ // clear local cache
+ if (pEnv) {
+ smaDebug("vgId:%d drop tSma local cache for %" PRIi64, SMA_VID(pSma), indexUid);
+
+ SSmaStatItem *pItem = taosHashGet(SMA_ENV_STAT_ITEMS(pEnv), &indexUid, sizeof(indexUid));
+ if ((pItem) || ((pItem = *(SSmaStatItem **)pItem))) {
+ if (tdSmaStatIsDropped(pItem)) {
+ smaDebug("vgId:%d tSma stat is already dropped for %" PRIi64, SMA_VID(pSma), indexUid);
+ return TSDB_CODE_TDB_INVALID_ACTION; // TODO: duplicate drop msg would be intercepted by mnode
+ }
+
+ tdWLockSmaEnv(pEnv);
+ if (tdSmaStatIsDropped(pItem)) {
+ tdUnLockSmaEnv(pEnv);
+ smaDebug("vgId:%d tSma stat is already dropped for %" PRIi64, SMA_VID(pSma), indexUid);
+ return TSDB_CODE_TDB_INVALID_ACTION; // TODO: duplicate drop msg would be intercepted by mnode
+ }
+ tdSmaStatSetDropped(pItem);
+ tdUnLockSmaEnv(pEnv);
+
+ int32_t nSleep = 0;
+ int32_t refVal = INT32_MAX;
+ while (true) {
+ if ((refVal = T_REF_VAL_GET(SMA_ENV_STAT(pEnv))) <= 0) {
+ smaDebug("vgId:%d drop index %" PRIi64 " since refVal=%d", SMA_VID(pSma), indexUid, refVal);
+ break;
+ }
+ smaDebug("vgId:%d wait 1s to drop index %" PRIi64 " since refVal=%d", SMA_VID(pSma), indexUid, refVal);
+ taosSsleep(1);
+ if (++nSleep > SMA_DROP_EXPIRED_TIME) {
+ smaDebug("vgId:%d drop index %" PRIi64 " after wait %d (refVal=%d)", SMA_VID(pSma), indexUid, nSleep, refVal);
+ break;
+ };
+ }
+
+ tdFreeSmaStatItem(pItem);
+ smaDebug("vgId:%d getTSmaDataImpl failed since no index %" PRIi64 " in local cache", SMA_VID(pSma), indexUid);
+ }
+ }
+ // clear sma data files
+ // TODO:
+ return TSDB_CODE_SUCCESS;
+}
+
+/**
+ * @brief
+ *
+ * @param pSma Return the data between queryWin and fill the pData.
+ * @param pData
+ * @param indexUid
+ * @param pQuerySKey
+ * @param nMaxResult The query invoker should control the nMaxResult need to return to avoid OOM.
+ * @return int32_t
+ */
+int32_t tdGetTSmaDataImpl(SSma *pSma, char *pData, int64_t indexUid, TSKEY querySKey, int32_t nMaxResult) {
+ SSmaEnv *pEnv = atomic_load_ptr(&SMA_TSMA_ENV(pSma));
+ SSmaStat *pStat = NULL;
+
+ if (!pEnv) {
+ terrno = TSDB_CODE_INVALID_PTR;
+ smaWarn("vgId:%d getTSmaDataImpl failed since pTSmaEnv is NULL", SMA_VID(pSma));
+ return TSDB_CODE_FAILED;
+ }
+
+ pStat = SMA_ENV_STAT(pEnv);
+
+ tdRefSmaStat(pSma, pStat);
+ SSmaStatItem *pItem = taosHashGet(SMA_ENV_STAT_ITEMS(pEnv), &indexUid, sizeof(indexUid));
+ if (!pItem || !(pItem = *(SSmaStatItem **)pItem)) {
+ // Normally pItem should not be NULL, mark all windows as expired and notify query module to fetch raw TS data if
+ // it's NULL.
+ tdUnRefSmaStat(pSma, pStat);
+ terrno = TSDB_CODE_TDB_INVALID_ACTION;
+ smaDebug("vgId:%d getTSmaDataImpl failed since no index %" PRIi64, SMA_VID(pSma), indexUid);
+ return TSDB_CODE_FAILED;
+ }
+
+#if 0
+ int32_t nQueryWin = taosArrayGetSize(pQuerySKey);
+ for (int32_t n = 0; n < nQueryWin; ++n) {
+ TSKEY skey = taosArrayGet(pQuerySKey, n);
+ if (taosHashGet(pItem->expiredWindows, &skey, sizeof(TSKEY))) {
+ // TODO: mark this window as expired.
+ }
+ }
+#endif
+
+#if 1
+ int8_t smaStat = 0;
+ if (!tdSmaStatIsOK(pItem, &smaStat)) { // TODO: multiple check for large scale sma query
+ tdUnRefSmaStat(pSma, pStat);
+ terrno = TSDB_CODE_TDB_INVALID_SMA_STAT;
+ smaWarn("vgId:%d getTSmaDataImpl failed from index %" PRIi64 " since %s %" PRIi8, SMA_VID(pSma), indexUid,
+ tstrerror(terrno), smaStat);
+ return TSDB_CODE_FAILED;
+ }
+
+ if (taosHashGet(pItem->expiredWindows, &querySKey, sizeof(TSKEY))) {
+ // TODO: mark this window as expired.
+ smaDebug("vgId:%d skey %" PRIi64 " of window exists in expired window for index %" PRIi64, SMA_VID(pSma), querySKey,
+ indexUid);
+ } else {
+ smaDebug("vgId:%d skey %" PRIi64 " of window not in expired window for index %" PRIi64, SMA_VID(pSma), querySKey,
+ indexUid);
+ }
+
+ STSma *pTSma = pItem->pTSma;
+#endif
+
+#if 1
+ STSmaReadH tReadH = {0};
+ tdInitTSmaReadH(&tReadH, pSma, pTSma->interval, pTSma->intervalUnit);
+ smaCloseDBF(&tReadH.dFile);
+
+ tdUnRefSmaStat(pSma, pStat);
+
+ tdInitTSmaFile(&tReadH, indexUid, querySKey);
+ smaDebug("### vgId:%d read from DBF %s days:%d, interval:%" PRIi64 ", storageLevel:%" PRIi8 " queryKey:%" PRIi64,
+ SMA_VID(pSma), tReadH.dFile.path, tReadH.days, tReadH.interval, tReadH.storageLevel, querySKey);
+ if (smaOpenDBF(pEnv->dbEnv, &tReadH.dFile) != 0) {
+ smaWarn("vgId:%d open DBF %s failed since %s", SMA_VID(pSma), tReadH.dFile.path, tstrerror(terrno));
+ return TSDB_CODE_FAILED;
+ }
+
+ char smaKey[SMA_KEY_LEN] = {0};
+ void *pSmaKey = &smaKey;
+ int64_t queryGroupId = 0;
+ tdEncodeTSmaKey(queryGroupId, querySKey, (void **)&pSmaKey);
+
+ smaDebug("vgId:%d get sma data from %s: smaKey %" PRIx64 "-%" PRIx64 ", keyLen %d", SMA_VID(pSma), tReadH.dFile.path,
+ *(int64_t *)smaKey, *(int64_t *)POINTER_SHIFT(smaKey, 8), SMA_KEY_LEN);
+
+ void *result = NULL;
+ int32_t valueSize = 0;
+ if (!(result = smaGetSmaDataByKey(&tReadH.dFile, smaKey, SMA_KEY_LEN, &valueSize))) {
+ smaWarn("vgId:%d get sma data failed from smaIndex %" PRIi64 ", smaKey %" PRIx64 "-%" PRIx64 " since %s",
+ SMA_VID(pSma), indexUid, *(int64_t *)smaKey, *(int64_t *)POINTER_SHIFT(smaKey, 8), tstrerror(terrno));
+ smaCloseDBF(&tReadH.dFile);
+ return TSDB_CODE_FAILED;
+ }
+#endif
+
+#ifdef _TEST_SMA_PRINT_DEBUG_LOG_
+ for (uint32_t v = 0; v < valueSize; v += 8) {
+ smaWarn("vgId:%d get sma data v[%d]=%" PRIi64, SMA_VID(pSma), v, *(int64_t *)POINTER_SHIFT(result, v));
+ }
+#endif
+ taosMemoryFreeClear(result); // TODO: fill the result to output
+
+#if 0
+ int32_t nResult = 0;
+ int64_t lastKey = 0;
+
+ while (true) {
+ if (nResult >= nMaxResult) {
+ break;
+ }
+
+ // set and open the file according to the STSma param
+ if (tdSetAndOpenTSmaFile(&tReadH, queryWin)) {
+ char bTree[100] = "\0";
+ while (strncmp(bTree, "has more nodes", 100) == 0) {
+ if (nResult >= nMaxResult) {
+ break;
+ }
+ // tdGetDataFromBTree(bTree, queryWin, lastKey)
+ // fill the pData
+ ++nResult;
+ }
+ }
+ }
+#endif
+ // read data from file and fill the result
+ smaCloseDBF(&tReadH.dFile);
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t tdProcessTSmaCreateImpl(SSma *pSma, int64_t version, const char *pMsg) {
+ SSmaCfg *pCfg = (SSmaCfg *)pMsg;
+
+ if (metaCreateTSma(SMA_META(pSma), version, pCfg) < 0) {
+ return -1;
+ }
+
+ tdTSmaAdd(pSma, 1);
+ return 0;
+}
+
+int32_t tdDropTSma(SSma *pSma, char *pMsg) {
+#if 0
+ SVDropTSmaReq vDropSmaReq = {0};
+ if (!tDeserializeSVDropTSmaReq(pMsg, &vDropSmaReq)) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return -1;
+ }
+
+ // TODO: send msg to stream computing to drop tSma
+ // if ((send msg to stream computing) < 0) {
+ // tDestroyTSma(&vCreateSmaReq);
+ // return -1;
+ // }
+ //
+
+ if (metaDropTSma(SMA_META(pSma), vDropSmaReq.indexUid) < 0) {
+ // TODO: handle error
+ return -1;
+ }
+
+ if (tdDropTSmaData(pSma, vDropSmaReq.indexUid) < 0) {
+ // TODO: handle error
+ return -1;
+ }
+
+ tdTSmaSub(pSma, 1);
+#endif
+
+ // TODO: return directly or go on follow steps?
+ return TSDB_CODE_SUCCESS;
+}
+
+static SSmaStatItem *tdNewSmaStatItem(int8_t state) {
+ SSmaStatItem *pItem = NULL;
+
+ pItem = (SSmaStatItem *)taosMemoryCalloc(1, sizeof(SSmaStatItem));
+ if (!pItem) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return NULL;
+ }
+
+ pItem->state = state;
+ pItem->expiredWindows = taosHashInit(SMA_STATE_ITEM_HASH_SLOT, taosGetDefaultHashFunction(TSDB_DATA_TYPE_TIMESTAMP),
+ true, HASH_ENTRY_LOCK);
+ if (!pItem->expiredWindows) {
+ taosMemoryFreeClear(pItem);
+ return NULL;
+ }
+
+ return pItem;
+}
+
+static int32_t tdSetExpiredWindow(SSma *pSma, SHashObj *pItemsHash, int64_t indexUid, int64_t winSKey,
+ int64_t version) {
+ SSmaStatItem *pItem = taosHashGet(pItemsHash, &indexUid, sizeof(indexUid));
+ if (!pItem) {
+ // TODO: use TSDB_SMA_STAT_EXPIRED and update by stream computing later
+ pItem = tdNewSmaStatItem(TSDB_SMA_STAT_OK); // TODO use the real state
+ if (!pItem) {
+ // Response to stream computing: OOM
+ // For query, if the indexUid not found, the TSDB should tell query module to query raw TS data.
+ return TSDB_CODE_FAILED;
+ }
+
+ // cache smaMeta
+ STSma *pTSma = metaGetSmaInfoByIndex(SMA_META(pSma), indexUid);
+ if (!pTSma) {
+ terrno = TSDB_CODE_TDB_NO_SMA_INDEX_IN_META;
+ taosHashCleanup(pItem->expiredWindows);
+ taosMemoryFree(pItem);
+ smaWarn("vgId:%d set expire window, get tsma meta failed for smaIndex %" PRIi64 " since %s", SMA_VID(pSma),
+ indexUid, tstrerror(terrno));
+ return TSDB_CODE_FAILED;
+ }
+ pItem->pTSma = pTSma;
+
+ if (taosHashPut(pItemsHash, &indexUid, sizeof(indexUid), &pItem, sizeof(pItem)) != 0) {
+ // If error occurs during put smaStatItem, free the resources of pItem
+ taosHashCleanup(pItem->expiredWindows);
+ taosMemoryFree(pItem);
+ return TSDB_CODE_FAILED;
+ }
+ } else if (!(pItem = *(SSmaStatItem **)pItem)) {
+ terrno = TSDB_CODE_INVALID_PTR;
+ return TSDB_CODE_FAILED;
+ }
+
+ if (taosHashPut(pItem->expiredWindows, &winSKey, sizeof(TSKEY), &version, sizeof(version)) != 0) {
+ // If error occurs during taosHashPut expired windows, remove the smaIndex from pSma->pSmaStat, thus TSDB would
+ // tell query module to query raw TS data.
+ // N.B.
+ // 1) It is assumed to be extemely little probability event of fail to taosHashPut.
+ // 2) This would solve the inconsistency to some extent, but not completely, unless we record all expired
+ // windows failed to put into hash table.
+ taosHashCleanup(pItem->expiredWindows);
+ taosMemoryFreeClear(pItem->pTSma);
+ taosHashRemove(pItemsHash, &indexUid, sizeof(indexUid));
+ smaWarn("vgId:%d smaIndex %" PRIi64 ", put skey %" PRIi64 " to expire window fail", SMA_VID(pSma), indexUid,
+ winSKey);
+ return TSDB_CODE_FAILED;
+ }
+
+ smaDebug("vgId:%d smaIndex %" PRIi64 ", put skey %" PRIi64 " to expire window succeed", SMA_VID(pSma), indexUid,
+ winSKey);
+ return TSDB_CODE_SUCCESS;
+}
+
+/**
+ * @brief Update expired window according to msg from stream computing module.
+ *
+ * @param pSma
+ * @param msg SSubmitReq
+ * @return int32_t
+ */
+int32_t tdUpdateExpiredWindowImpl(SSma *pSma, const SSubmitReq *pMsg, int64_t version) {
+ // no time-range-sma, just return success
+ if (atomic_load_16(&SMA_TSMA_NUM(pSma)) <= 0) {
+ smaTrace("vgId:%d not update expire window since no tSma", SMA_VID(pSma));
+ return TSDB_CODE_SUCCESS;
+ }
+
+ if (!SMA_META(pSma)) {
+ terrno = TSDB_CODE_INVALID_PTR;
+ smaError("vgId:%d update expire window failed since no meta ptr", SMA_VID(pSma));
+ return TSDB_CODE_FAILED;
+ }
+
+ if (tdCheckAndInitSmaEnv(pSma, TSDB_SMA_TYPE_TIME_RANGE) < 0) {
+ smaError("vgId:%d init sma env failed since %s", SMA_VID(pSma), terrstr(terrno));
+ terrno = TSDB_CODE_TDB_INIT_FAILED;
+ return TSDB_CODE_FAILED;
+ }
+
+ // Firstly, assume that tSma can only be created on super table/normal table.
+ // getActiveTimeWindow
+
+ SSmaEnv *pEnv = SMA_TSMA_ENV(pSma);
+ SSmaStat *pStat = SMA_ENV_STAT(pEnv);
+ SHashObj *pItemsHash = SMA_ENV_STAT_ITEMS(pEnv);
+
+ TASSERT(pEnv && pStat && pItemsHash);
+
+ // basic procedure
+ // TODO: optimization
+ tdRefSmaStat(pSma, pStat);
+
+ SSubmitMsgIter msgIter = {0};
+ SSubmitBlk *pBlock = NULL;
+ SInterval interval = {0};
+ TSKEY lastWinSKey = INT64_MIN;
+
+ if (tInitSubmitMsgIter(pMsg, &msgIter) < 0) {
+ return TSDB_CODE_FAILED;
+ }
+
+ while (true) {
+ tGetSubmitMsgNext(&msgIter, &pBlock);
+ if (!pBlock) break;
+
+ STSmaWrapper *pSW = NULL;
+ STSma *pTSma = NULL;
+
+ SSubmitBlkIter blkIter = {0};
+ if (tInitSubmitBlkIter(&msgIter, pBlock, &blkIter) < 0) {
+ pSW = tFreeTSmaWrapper(pSW, false);
+ break;
+ }
+
+ while (true) {
+ STSRow *row = tGetSubmitBlkNext(&blkIter);
+ if (!row) {
+ pSW = tFreeTSmaWrapper(pSW, false);
+ break;
+ }
+ if (!pSW || (pTSma && (pTSma->tableUid != msgIter.suid))) {
+ if (pSW) {
+ pSW = tFreeTSmaWrapper(pSW, false);
+ }
+ if (!(pSW = metaGetSmaInfoByTable(SMA_META(pSma), msgIter.suid, false))) {
+ break;
+ }
+ if ((pSW->number) <= 0 || !pSW->tSma) {
+ pSW = tFreeTSmaWrapper(pSW, false);
+ break;
+ }
+
+ pTSma = pSW->tSma;
+
+ interval.interval = pTSma->interval;
+ interval.intervalUnit = pTSma->intervalUnit;
+ interval.offset = pTSma->offset;
+ interval.precision = SMA_TSDB_CFG(pSma)->precision;
+ interval.sliding = pTSma->sliding;
+ interval.slidingUnit = pTSma->slidingUnit;
+ }
+
+ // TODO: process multiple tsma for one table uid
+ TSKEY winSKey = taosTimeTruncate(TD_ROW_KEY(row), &interval, interval.precision);
+
+ if (lastWinSKey != winSKey) {
+ lastWinSKey = winSKey;
+ if (tdSetExpiredWindow(pSma, pItemsHash, pTSma->indexUid, winSKey, version) < 0) {
+ pSW = tFreeTSmaWrapper(pSW, false);
+ tdUnRefSmaStat(pSma, pStat);
+ return TSDB_CODE_FAILED;
+ }
+ } else {
+ smaDebug("vgId:%d smaIndex %" PRIi64 ", put skey %" PRIi64 " to expire window ignore as duplicated",
+ SMA_VID(pSma), pTSma->indexUid, winSKey);
+ }
+ }
+ }
+
+ tdUnRefSmaStat(pSma, pStat);
+
+ return TSDB_CODE_SUCCESS;
+}
\ No newline at end of file
diff --git a/source/dnode/vnode/src/tq/tq.c b/source/dnode/vnode/src/tq/tq.c
index 67651c2f78..310b59b2e8 100644
--- a/source/dnode/vnode/src/tq/tq.c
+++ b/source/dnode/vnode/src/tq/tq.c
@@ -81,12 +81,41 @@ void tqClose(STQ* pTq) {
// TODO
}
+int32_t tqSendPollRsp(STQ* pTq, const SRpcMsg* pMsg, const SMqPollReq* pReq, const SMqDataBlkRsp* pRsp) {
+ int32_t tlen = sizeof(SMqRspHead) + tEncodeSMqDataBlkRsp(NULL, pRsp);
+ void* buf = rpcMallocCont(tlen);
+ if (buf == NULL) {
+ return -1;
+ }
+
+ ((SMqRspHead*)buf)->mqMsgType = TMQ_MSG_TYPE__POLL_RSP;
+ ((SMqRspHead*)buf)->epoch = pReq->epoch;
+ ((SMqRspHead*)buf)->consumerId = pReq->consumerId;
+
+ void* abuf = POINTER_SHIFT(buf, sizeof(SMqRspHead));
+ tEncodeSMqDataBlkRsp(&abuf, pRsp);
+
+ SRpcMsg resp = {
+ .info = pMsg->info,
+ .pCont = buf,
+ .contLen = tlen,
+ .code = 0,
+ };
+ tmsgSendRsp(&resp);
+
+ tqDebug("vg %d from consumer %ld (epoch %d) send rsp, block num: %d, reqOffset: %ld, rspOffset: %ld",
+ TD_VID(pTq->pVnode), pReq->consumerId, pReq->epoch, pRsp->blockNum, pRsp->reqOffset, pRsp->rspOffset);
+
+ return 0;
+}
+
int32_t tqProcessPollReq(STQ* pTq, SRpcMsg* pMsg, int32_t workerId) {
SMqPollReq* pReq = pMsg->pCont;
int64_t consumerId = pReq->consumerId;
int64_t timeout = pReq->timeout;
int32_t reqEpoch = pReq->epoch;
int64_t fetchOffset;
+ int32_t code = 0;
// get offset to fetch message
if (pReq->currentOffset == TMQ_CONF__RESET_OFFSET__EARLIEAST) {
@@ -155,7 +184,9 @@ int32_t tqProcessPollReq(STQ* pTq, SRpcMsg* pMsg, int32_t workerId) {
if (pHead->msgType == TDMT_VND_SUBMIT) {
SSubmitReq* pCont = (SSubmitReq*)&pHead->body;
- tqDataExec(pTq, &pHandle->execHandle, pCont, &rsp, workerId);
+ if (tqDataExec(pTq, &pHandle->execHandle, pCont, &rsp, workerId) < 0) {
+ /*ASSERT(0);*/
+ }
} else {
// TODO
ASSERT(0);
@@ -180,31 +211,10 @@ int32_t tqProcessPollReq(STQ* pTq, SRpcMsg* pMsg, int32_t workerId) {
rsp.rspOffset = fetchOffset;
- int32_t tlen = sizeof(SMqRspHead) + tEncodeSMqDataBlkRsp(NULL, &rsp);
- void* buf = rpcMallocCont(tlen);
- if (buf == NULL) {
- pMsg->code = -1;
- return -1;
+ if (tqSendPollRsp(pTq, pMsg, pReq, &rsp) < 0) {
+ code = -1;
}
- ((SMqRspHead*)buf)->mqMsgType = TMQ_MSG_TYPE__POLL_RSP;
- ((SMqRspHead*)buf)->epoch = pReq->epoch;
- ((SMqRspHead*)buf)->consumerId = consumerId;
-
- void* abuf = POINTER_SHIFT(buf, sizeof(SMqRspHead));
- tEncodeSMqDataBlkRsp(&abuf, &rsp);
-
- SRpcMsg resp = {
- .info = pMsg->info,
- .pCont = buf,
- .contLen = tlen,
- .code = 0,
- };
- tmsgSendRsp(&resp);
-
- tqDebug("vg %d offset %ld from consumer %ld (epoch %d) send rsp, block num: %d, reqOffset: %ld, rspOffset: %ld",
- TD_VID(pTq->pVnode), fetchOffset, consumerId, pReq->epoch, rsp.blockNum, rsp.reqOffset, rsp.rspOffset);
-
// TODO wrap in destroy func
taosArrayDestroy(rsp.blockData);
taosArrayDestroy(rsp.blockDataLen);
@@ -217,7 +227,7 @@ int32_t tqProcessPollReq(STQ* pTq, SRpcMsg* pMsg, int32_t workerId) {
taosArrayDestroyP(rsp.blockTbName, (FDelete)taosMemoryFree);
}
- return 0;
+ return code;
}
int32_t tqProcessVgDeleteReq(STQ* pTq, char* msg, int32_t msgLen) {
@@ -250,18 +260,14 @@ int32_t tqProcessVgChangeReq(STQ* pTq, char* msg, int32_t msgLen) {
pHandle->epoch = -1;
pHandle->execHandle.subType = req.subType;
- /*pExec->withTbName = req.withTbName;*/
- /*pExec->withSchema = req.withSchema;*/
- /*pExec->withTag = req.withTag;*/
-
- pHandle->execHandle.exec.execCol.qmsg = req.qmsg;
- req.qmsg = NULL;
pHandle->pWalReader = walOpenReadHandle(pTq->pVnode->pWal);
for (int32_t i = 0; i < 5; i++) {
pHandle->execHandle.pExecReader[i] = tqInitSubmitMsgScanner(pTq->pVnode->pMeta);
}
if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) {
+ pHandle->execHandle.exec.execCol.qmsg = req.qmsg;
+ req.qmsg = NULL;
for (int32_t i = 0; i < 5; i++) {
SReadHandle handle = {
.reader = pHandle->execHandle.pExecReader[i],
@@ -276,6 +282,18 @@ int32_t tqProcessVgChangeReq(STQ* pTq, char* msg, int32_t msgLen) {
pHandle->execHandle.exec.execDb.pFilterOutTbUid =
taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
} else if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__TABLE) {
+ pHandle->execHandle.exec.execTb.suid = req.suid;
+ SArray* tbUidList = taosArrayInit(0, sizeof(int64_t));
+ tsdbGetCtbIdList(pTq->pVnode->pMeta, req.suid, tbUidList);
+ tqDebug("vg %d, tq try get suid: %ld", pTq->pVnode->config.vgId, req.suid);
+ for (int32_t i = 0; i < taosArrayGetSize(tbUidList); i++) {
+ int64_t tbUid = *(int64_t*)taosArrayGet(tbUidList, i);
+ tqDebug("vg %d, idx %d, uid: %ld", pTq->pVnode->config.vgId, i, tbUid);
+ }
+ for (int32_t i = 0; i < 5; i++) {
+ tqReadHandleSetTbUidList(pHandle->execHandle.pExecReader[i], tbUidList);
+ }
+ taosArrayDestroy(tbUidList);
}
taosHashPut(pTq->handles, req.subKey, strlen(req.subKey), pHandle, sizeof(STqHandle));
} else {
diff --git a/source/dnode/vnode/src/tq/tqPush.c b/source/dnode/vnode/src/tq/tqPush.c
index 2d9207a0de..d94c3e387a 100644
--- a/source/dnode/vnode/src/tq/tqPush.c
+++ b/source/dnode/vnode/src/tq/tqPush.c
@@ -20,22 +20,73 @@ void tqTmrRspFunc(void* param, void* tmrId) {
atomic_store_8(&pHandle->pushHandle.tmrStopped, 1);
}
+static int32_t tqLoopExecFromQueue(STQ* pTq, STqHandle* pHandle, SStreamDataSubmit** ppSubmit, SMqDataBlkRsp* pRsp) {
+ SStreamDataSubmit* pSubmit = *ppSubmit;
+ while (pSubmit != NULL) {
+ ASSERT(pSubmit->ver == pHandle->pushHandle.processedVer + 1);
+ if (tqDataExec(pTq, &pHandle->execHandle, pSubmit->data, pRsp, 0) < 0) {
+ /*ASSERT(0);*/
+ }
+ // update processed
+ atomic_store_64(&pHandle->pushHandle.processedVer, pSubmit->ver);
+ streamQSetSuccess(&pHandle->pushHandle.inputQ);
+ streamDataSubmitRefDec(pSubmit);
+ if (pRsp->blockNum > 0) {
+ *ppSubmit = pSubmit;
+ return 0;
+ } else {
+ pSubmit = streamQNextItem(&pHandle->pushHandle.inputQ);
+ }
+ }
+ *ppSubmit = pSubmit;
+ return -1;
+}
+
int32_t tqExecFromInputQ(STQ* pTq, STqHandle* pHandle) {
+ SMqDataBlkRsp rsp = {0};
// 1. guard and set status executing
- // 2. check processedVer
- // 2.1. if not missed, get msg from queue
- // 2.2. if missed, scan wal
- //
- // 3. exec, after each success, update processed ver
- // first run
- // set exec status closing
- // second run
- // set exec status idle
- //
+ int8_t execStatus =
+ atomic_val_compare_exchange_8(&pHandle->pushHandle.execStatus, TASK_STATUS__IDLE, TASK_STATUS__EXECUTING);
+ if (execStatus == TASK_STATUS__IDLE) {
+ SStreamDataSubmit* pSubmit = NULL;
+ // 2. check processedVer
+ // 2.1. if not missed, get msg from queue
+ // 2.2. if missed, scan wal
+ pSubmit = streamQNextItem(&pHandle->pushHandle.inputQ);
+ while (pHandle->pushHandle.processedVer <= pSubmit->ver) {
+ // read from wal
+ }
+ while (pHandle->pushHandle.processedVer > pSubmit->ver + 1) {
+ streamQSetSuccess(&pHandle->pushHandle.inputQ);
+ streamDataSubmitRefDec(pSubmit);
+ pSubmit = streamQNextItem(&pHandle->pushHandle.inputQ);
+ if (pSubmit == NULL) break;
+ }
+ // 3. exec, after each success, update processed ver
+ // first run
+ if (tqLoopExecFromQueue(pTq, pHandle, &pSubmit, &rsp) == 0) {
+ goto SEND_RSP;
+ }
+ // set exec status closing
+ atomic_store_8(&pHandle->pushHandle.execStatus, TASK_STATUS__CLOSING);
+ // second run
+ if (tqLoopExecFromQueue(pTq, pHandle, &pSubmit, &rsp) == 0) {
+ goto SEND_RSP;
+ }
+ // set exec status idle
+ atomic_store_8(&pHandle->pushHandle.execStatus, TASK_STATUS__IDLE);
+ }
+SEND_RSP:
// 4. if get result
// 4.1 set exec input status blocked and exec status idle
+ atomic_store_8(&pHandle->pushHandle.execStatus, TASK_STATUS__IDLE);
// 4.2 rpc send
+ rsp.rspOffset = pHandle->pushHandle.processedVer;
+ /*if (tqSendPollRsp(pTq, pMsg, pReq, &rsp) < 0) {*/
+ /*return -1;*/
+ /*}*/
// 4.3 clear rpc info
+ memset(&pHandle->pushHandle.rpcInfo, 0, sizeof(SRpcHandleInfo));
return 0;
}
diff --git a/source/dnode/vnode/src/tsdb/tsdbRead.c b/source/dnode/vnode/src/tsdb/tsdbRead.c
index f9c5fac536..61daa0c9b3 100644
--- a/source/dnode/vnode/src/tsdb/tsdbRead.c
+++ b/source/dnode/vnode/src/tsdb/tsdbRead.c
@@ -13,8 +13,8 @@
* along with this program. If not, see .
*/
-#include "vnode.h"
#include "tsdb.h"
+#include "vnode.h"
#define EXTRA_BYTES 2
#define ASCENDING_TRAVERSE(o) (o == TSDB_ORDER_ASC)
@@ -327,8 +327,8 @@ static void setQueryTimewindow(STsdbReadHandle* pTsdbReadHandle, SQueryTableData
if (updateTs) {
tsdbDebug("%p update the query time window, old:%" PRId64 " - %" PRId64 ", new:%" PRId64 " - %" PRId64 ", %s",
- pTsdbReadHandle, pCond->twindows[tWinIdx].skey, pCond->twindows[tWinIdx].ekey, pTsdbReadHandle->window.skey,
- pTsdbReadHandle->window.ekey, pTsdbReadHandle->idStr);
+ pTsdbReadHandle, pCond->twindows[tWinIdx].skey, pCond->twindows[tWinIdx].ekey,
+ pTsdbReadHandle->window.skey, pTsdbReadHandle->window.ekey, pTsdbReadHandle->idStr);
}
}
@@ -586,7 +586,8 @@ void tsdbResetReadHandle(tsdbReaderT queryHandle, SQueryTableDataCond* pCond, in
resetCheckInfo(pTsdbReadHandle);
}
-void tsdbResetQueryHandleForNewTable(tsdbReaderT queryHandle, SQueryTableDataCond* pCond, STableListInfo* tableList, int32_t tWinIdx) {
+void tsdbResetQueryHandleForNewTable(tsdbReaderT queryHandle, SQueryTableDataCond* pCond, STableListInfo* tableList,
+ int32_t tWinIdx) {
STsdbReadHandle* pTsdbReadHandle = queryHandle;
pTsdbReadHandle->order = pCond->order;
@@ -2845,6 +2846,22 @@ int32_t tsdbGetAllTableList(SMeta* pMeta, uint64_t uid, SArray* list) {
return TSDB_CODE_SUCCESS;
}
+int32_t tsdbGetCtbIdList(SMeta* pMeta, int64_t suid, SArray* list) {
+ SMCtbCursor* pCur = metaOpenCtbCursor(pMeta, suid);
+
+ while (1) {
+ tb_uid_t id = metaCtbCursorNext(pCur);
+ if (id == 0) {
+ break;
+ }
+
+ taosArrayPush(list, &id);
+ }
+
+ metaCloseCtbCursor(pCur);
+ return TSDB_CODE_SUCCESS;
+}
+
static void destroyHelper(void* param) {
if (param == NULL) {
return;
diff --git a/source/dnode/vnode/src/vnd/vnodeSvr.c b/source/dnode/vnode/src/vnd/vnodeSvr.c
index b66695f7c2..ab879c5dbb 100644
--- a/source/dnode/vnode/src/vnd/vnodeSvr.c
+++ b/source/dnode/vnode/src/vnd/vnodeSvr.c
@@ -251,6 +251,13 @@ void smaHandleRes(void *pVnode, int64_t smaId, const SArray *data) {
tdProcessTSmaInsert(((SVnode *)pVnode)->pSma, smaId, (const char *)data);
}
+void vnodeUpdateMetaRsp(SVnode *pVnode, STableMetaRsp *pMetaRsp) {
+ strcpy(pMetaRsp->dbFName, pVnode->config.dbname);
+ pMetaRsp->dbId = pVnode->config.dbId;
+ pMetaRsp->vgId = TD_VID(pVnode);
+ pMetaRsp->precision = pVnode->config.tsdbCfg.precision;
+}
+
int vnodeProcessSyncReq(SVnode *pVnode, SRpcMsg *pMsg, SRpcMsg **pRsp) {
int32_t ret = TAOS_SYNC_PROPOSE_OTHER_ERROR;
@@ -520,12 +527,13 @@ _exit:
}
static int vnodeProcessAlterTbReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp) {
- SVAlterTbReq vAlterTbReq = {0};
- SVAlterTbRsp vAlterTbRsp = {0};
- SDecoder dc = {0};
- int rcode = 0;
- int ret;
- SEncoder ec = {0};
+ SVAlterTbReq vAlterTbReq = {0};
+ SVAlterTbRsp vAlterTbRsp = {0};
+ SDecoder dc = {0};
+ int rcode = 0;
+ int ret;
+ SEncoder ec = {0};
+ STableMetaRsp vMetaRsp = {0};
pRsp->msgType = TDMT_VND_ALTER_TABLE_RSP;
pRsp->pCont = NULL;
@@ -543,7 +551,7 @@ static int vnodeProcessAlterTbReq(SVnode *pVnode, int64_t version, void *pReq, i
}
// process
- if (metaAlterTable(pVnode->pMeta, version, &vAlterTbReq) < 0) {
+ if (metaAlterTable(pVnode->pMeta, version, &vAlterTbReq, &vMetaRsp) < 0) {
vAlterTbRsp.code = TSDB_CODE_INVALID_MSG;
tDecoderClear(&dc);
rcode = -1;
@@ -551,6 +559,11 @@ static int vnodeProcessAlterTbReq(SVnode *pVnode, int64_t version, void *pReq, i
}
tDecoderClear(&dc);
+ if (NULL != vMetaRsp.pSchemas) {
+ vnodeUpdateMetaRsp(pVnode, &vMetaRsp);
+ vAlterTbRsp.pMeta = &vMetaRsp;
+ }
+
_exit:
tEncodeSize(tEncodeSVAlterTbRsp, &vAlterTbRsp, pRsp->contLen, ret);
pRsp->pCont = rpcMallocCont(pRsp->contLen);
diff --git a/source/dnode/vnode/test/tsdbSmaTest.cpp b/source/dnode/vnode/test/tsdbSmaTest.cpp
index 4d2741f751..3b8c94e413 100644
--- a/source/dnode/vnode/test/tsdbSmaTest.cpp
+++ b/source/dnode/vnode/test/tsdbSmaTest.cpp
@@ -147,8 +147,8 @@ TEST(testCase, tSma_Meta_Encode_Decode_Test) {
// resource release
taosMemoryFreeClear(pSW);
- tdDestroyTSma(&tSma);
- tdDestroyTSmaWrapper(&dstTSmaWrapper);
+ tDestroyTSma(&tSma);
+ tDestroyTSmaWrapper(&dstTSmaWrapper);
}
#endif
@@ -218,7 +218,7 @@ TEST(testCase, tSma_metaDB_Put_Get_Del_Test) {
printf("tagsFilter1 = %s\n", qSmaCfg->tagsFilter != NULL ? qSmaCfg->tagsFilter : "");
EXPECT_STRCASEEQ(qSmaCfg->indexName, smaIndexName1);
EXPECT_EQ(qSmaCfg->tableUid, tSma.tableUid);
- tdDestroyTSma(qSmaCfg);
+ tDestroyTSma(qSmaCfg);
taosMemoryFreeClear(qSmaCfg);
qSmaCfg = metaGetSmaInfoByIndex(pMeta, indexUid2, true);
@@ -229,7 +229,7 @@ TEST(testCase, tSma_metaDB_Put_Get_Del_Test) {
printf("tagsFilter2 = %s\n", qSmaCfg->tagsFilter != NULL ? qSmaCfg->tagsFilter : "");
EXPECT_STRCASEEQ(qSmaCfg->indexName, smaIndexName2);
EXPECT_EQ(qSmaCfg->interval, tSma.interval);
- tdDestroyTSma(qSmaCfg);
+ tDestroyTSma(qSmaCfg);
taosMemoryFreeClear(qSmaCfg);
// get index name by table uid
@@ -265,7 +265,7 @@ TEST(testCase, tSma_metaDB_Put_Get_Del_Test) {
EXPECT_EQ((pSW->tSma + 1)->indexUid, indexUid2);
EXPECT_EQ((pSW->tSma + 1)->tableUid, tbUid);
- tdDestroyTSmaWrapper(pSW);
+ tDestroyTSmaWrapper(pSW);
taosMemoryFreeClear(pSW);
// get all sma table uids
@@ -282,7 +282,7 @@ TEST(testCase, tSma_metaDB_Put_Get_Del_Test) {
metaRemoveSmaFromDb(pMeta, indexUid1);
metaRemoveSmaFromDb(pMeta, indexUid2);
- tdDestroyTSma(&tSma);
+ tDestroyTSma(&tSma);
metaClose(pMeta);
}
#endif
@@ -576,7 +576,7 @@ TEST(testCase, tSma_Data_Insert_Query_Test) {
taosArrayDestroy(pDataBlocks);
// release meta
- tdDestroyTSma(&tSma);
+ tDestroyTSma(&tSma);
tfsClose(pTsdb->pTfs);
tsdbClose(pTsdb);
metaClose(pMeta);
diff --git a/source/libs/catalog/inc/catalogInt.h b/source/libs/catalog/inc/catalogInt.h
index 57f651ed69..239d719fa8 100644
--- a/source/libs/catalog/inc/catalogInt.h
+++ b/source/libs/catalog/inc/catalogInt.h
@@ -302,7 +302,7 @@ typedef struct SCtgUpdateEpsetMsg {
typedef struct SCtgCacheOperation {
int32_t opId;
void *data;
- bool syncReq;
+ bool syncOp;
uint64_t seqId;
} SCtgCacheOperation;
diff --git a/source/libs/catalog/src/catalog.c b/source/libs/catalog/src/catalog.c
index a874764468..7e0efe22db 100644
--- a/source/libs/catalog/src/catalog.c
+++ b/source/libs/catalog/src/catalog.c
@@ -314,6 +314,36 @@ _return:
CTG_RET(code);
}
+int32_t ctgUpdateTbMeta(SCatalog* pCtg, STableMetaRsp *rspMsg, bool syncOp) {
+ STableMetaOutput *output = taosMemoryCalloc(1, sizeof(STableMetaOutput));
+ if (NULL == output) {
+ ctgError("malloc %d failed", (int32_t)sizeof(STableMetaOutput));
+ CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
+ }
+
+ int32_t code = 0;
+
+ strcpy(output->dbFName, rspMsg->dbFName);
+ strcpy(output->tbName, rspMsg->tbName);
+
+ output->dbId = rspMsg->dbId;
+
+ SET_META_TYPE_TABLE(output->metaType);
+
+ CTG_ERR_JRET(queryCreateTableMetaFromMsg(rspMsg, rspMsg->tableType == TSDB_SUPER_TABLE, &output->tbMeta));
+
+ CTG_ERR_JRET(ctgUpdateTbMetaEnqueue(pCtg, output, syncOp));
+
+ return TSDB_CODE_SUCCESS;
+
+_return:
+
+ taosMemoryFreeClear(output->tbMeta);
+ taosMemoryFreeClear(output);
+
+ CTG_RET(code);
+}
+
int32_t ctgChkAuth(SCatalog* pCtg, void *pTrans, const SEpSet* pMgmtEps, const char* user, const char* dbFName, AUTH_TYPE type, bool *pass) {
bool inCache = false;
@@ -779,38 +809,17 @@ int32_t catalogGetSTableMeta(SCatalog* pCtg, void * pTrans, const SEpSet* pMgmtE
CTG_API_LEAVE(ctgGetTbMeta(CTG_PARAMS_LIST(), &ctx, pTableMeta));
}
-int32_t catalogUpdateSTableMeta(SCatalog* pCtg, STableMetaRsp *rspMsg) {
+int32_t catalogUpdateTableMeta(SCatalog* pCtg, STableMetaRsp *pMsg) {
CTG_API_ENTER();
- if (NULL == pCtg || NULL == rspMsg) {
+ if (NULL == pCtg || NULL == pMsg) {
CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
}
- STableMetaOutput *output = taosMemoryCalloc(1, sizeof(STableMetaOutput));
- if (NULL == output) {
- ctgError("malloc %d failed", (int32_t)sizeof(STableMetaOutput));
- CTG_API_LEAVE(TSDB_CODE_CTG_MEM_ERROR);
- }
-
int32_t code = 0;
-
- strcpy(output->dbFName, rspMsg->dbFName);
- strcpy(output->tbName, rspMsg->tbName);
-
- output->dbId = rspMsg->dbId;
-
- SET_META_TYPE_TABLE(output->metaType);
-
- CTG_ERR_JRET(queryCreateTableMetaFromMsg(rspMsg, true, &output->tbMeta));
-
- CTG_ERR_JRET(ctgUpdateTbMetaEnqueue(pCtg, output, false));
-
- CTG_API_LEAVE(code);
+ CTG_ERR_JRET(ctgUpdateTbMeta(pCtg, pMsg, true));
_return:
-
- taosMemoryFreeClear(output->tbMeta);
- taosMemoryFreeClear(output);
CTG_API_LEAVE(code);
}
diff --git a/source/libs/catalog/src/ctgCache.c b/source/libs/catalog/src/ctgCache.c
index 2fbb8b499d..0f1344c343 100644
--- a/source/libs/catalog/src/ctgCache.c
+++ b/source/libs/catalog/src/ctgCache.c
@@ -552,7 +552,7 @@ int32_t ctgEnqueue(SCatalog* pCtg, SCtgCacheOperation *operation) {
ctgDebug("action [%s] added into queue", gCtgCacheOperation[operation->opId].name);
- if (operation->syncReq) {
+ if (operation->syncOp) {
ctgWaitOpDone(operation);
}
@@ -591,9 +591,9 @@ _return:
}
-int32_t ctgDropStbMetaEnqueue(SCatalog* pCtg, const char *dbFName, int64_t dbId, const char *stbName, uint64_t suid, bool syncReq) {
+int32_t ctgDropStbMetaEnqueue(SCatalog* pCtg, const char *dbFName, int64_t dbId, const char *stbName, uint64_t suid, bool syncOp) {
int32_t code = 0;
- SCtgCacheOperation action= {.opId = CTG_OP_DROP_STB_META, .syncReq = syncReq};
+ SCtgCacheOperation action= {.opId = CTG_OP_DROP_STB_META, .syncOp = syncOp};
SCtgRemoveStbMsg *msg = taosMemoryMalloc(sizeof(SCtgRemoveStbMsg));
if (NULL == msg) {
ctgError("malloc %d failed", (int32_t)sizeof(SCtgRemoveStbMsg));
@@ -620,9 +620,9 @@ _return:
-int32_t ctgDropTbMetaEnqueue(SCatalog* pCtg, const char *dbFName, int64_t dbId, const char *tbName, bool syncReq) {
+int32_t ctgDropTbMetaEnqueue(SCatalog* pCtg, const char *dbFName, int64_t dbId, const char *tbName, bool syncOp) {
int32_t code = 0;
- SCtgCacheOperation action= {.opId = CTG_OP_DROP_TB_META, .syncReq = syncReq};
+ SCtgCacheOperation action= {.opId = CTG_OP_DROP_TB_META, .syncOp = syncOp};
SCtgRemoveTblMsg *msg = taosMemoryMalloc(sizeof(SCtgRemoveTblMsg));
if (NULL == msg) {
ctgError("malloc %d failed", (int32_t)sizeof(SCtgRemoveTblMsg));
@@ -646,9 +646,9 @@ _return:
CTG_RET(code);
}
-int32_t ctgUpdateVgroupEnqueue(SCatalog* pCtg, const char *dbFName, int64_t dbId, SDBVgInfo* dbInfo, bool syncReq) {
+int32_t ctgUpdateVgroupEnqueue(SCatalog* pCtg, const char *dbFName, int64_t dbId, SDBVgInfo* dbInfo, bool syncOp) {
int32_t code = 0;
- SCtgCacheOperation action= {.opId = CTG_OP_UPDATE_VGROUP, .syncReq = syncReq};
+ SCtgCacheOperation action= {.opId = CTG_OP_UPDATE_VGROUP, .syncOp = syncOp};
SCtgUpdateVgMsg *msg = taosMemoryMalloc(sizeof(SCtgUpdateVgMsg));
if (NULL == msg) {
ctgError("malloc %d failed", (int32_t)sizeof(SCtgUpdateVgMsg));
@@ -679,9 +679,9 @@ _return:
CTG_RET(code);
}
-int32_t ctgUpdateTbMetaEnqueue(SCatalog* pCtg, STableMetaOutput *output, bool syncReq) {
+int32_t ctgUpdateTbMetaEnqueue(SCatalog* pCtg, STableMetaOutput *output, bool syncOp) {
int32_t code = 0;
- SCtgCacheOperation action= {.opId = CTG_OP_UPDATE_TB_META, .syncReq = syncReq};
+ SCtgCacheOperation action= {.opId = CTG_OP_UPDATE_TB_META, .syncOp = syncOp};
SCtgUpdateTblMsg *msg = taosMemoryMalloc(sizeof(SCtgUpdateTblMsg));
if (NULL == msg) {
ctgError("malloc %d failed", (int32_t)sizeof(SCtgUpdateTblMsg));
@@ -738,9 +738,9 @@ _return:
-int32_t ctgUpdateUserEnqueue(SCatalog* pCtg, SGetUserAuthRsp *pAuth, bool syncReq) {
+int32_t ctgUpdateUserEnqueue(SCatalog* pCtg, SGetUserAuthRsp *pAuth, bool syncOp) {
int32_t code = 0;
- SCtgCacheOperation action= {.opId = CTG_OP_UPDATE_USER, .syncReq = syncReq};
+ SCtgCacheOperation action= {.opId = CTG_OP_UPDATE_USER, .syncOp = syncOp};
SCtgUpdateUserMsg *msg = taosMemoryMalloc(sizeof(SCtgUpdateUserMsg));
if (NULL == msg) {
ctgError("malloc %d failed", (int32_t)sizeof(SCtgUpdateUserMsg));
@@ -1574,7 +1574,7 @@ void* ctgUpdateThreadFunc(void* param) {
gCtgMgmt.queue.seqDone = operation->seqId;
- if (operation->syncReq) {
+ if (operation->syncOp) {
tsem_post(&gCtgMgmt.queue.rspSem);
}
diff --git a/source/libs/catalog/test/catalogTests.cpp b/source/libs/catalog/test/catalogTests.cpp
index 19c5bb6dcd..e4ae2c004f 100644
--- a/source/libs/catalog/test/catalogTests.cpp
+++ b/source/libs/catalog/test/catalogTests.cpp
@@ -1380,7 +1380,7 @@ TEST(tableMeta, updateStbMeta) {
STableMetaRsp rsp = {0};
ctgTestBuildSTableMetaRsp(&rsp);
- code = catalogUpdateSTableMeta(pCtg, &rsp);
+ code = catalogUpdateTableMeta(pCtg, &rsp);
ASSERT_EQ(code, 0);
taosMemoryFreeClear(rsp.pSchemas);
diff --git a/source/libs/executor/inc/executil.h b/source/libs/executor/inc/executil.h
index 63c398618f..b8975854c9 100644
--- a/source/libs/executor/inc/executil.h
+++ b/source/libs/executor/inc/executil.h
@@ -75,15 +75,15 @@ typedef struct SResultRowInfo {
int32_t size; // number of result set
int32_t capacity; // max capacity
SResultRowPosition cur;
+ SList* openWindow;
} SResultRowInfo;
struct SqlFunctionCtx;
-size_t getResultRowSize(struct SqlFunctionCtx* pCtx, int32_t numOfOutput);
+size_t getResultRowSize(struct SqlFunctionCtx* pCtx, int32_t numOfOutput);
int32_t initResultRowInfo(SResultRowInfo* pResultRowInfo, int32_t size);
void cleanupResultRowInfo(SResultRowInfo* pResultRowInfo);
-int32_t numOfClosedResultRows(SResultRowInfo* pResultRowInfo);
void closeAllResultRows(SResultRowInfo* pResultRowInfo);
void initResultRow(SResultRow *pResultRow);
@@ -92,15 +92,6 @@ bool isResultRowClosed(SResultRow* pResultRow);
struct SResultRowEntryInfo* getResultCell(const SResultRow* pRow, int32_t index, const int32_t* offset);
-static FORCE_INLINE SResultRow *getResultRow(SDiskbasedBuf* pBuf, SResultRowInfo *pResultRowInfo, int32_t slot) {
- ASSERT(pResultRowInfo != NULL && slot >= 0 && slot < pResultRowInfo->size);
- SResultRowPosition* pos = &pResultRowInfo->pPosition[slot];
-
- SFilePage* bufPage = (SFilePage*) getBufPage(pBuf, pos->pageId);
- SResultRow* pRow = (SResultRow*)((char*)bufPage + pos->offset);
- return pRow;
-}
-
static FORCE_INLINE SResultRow *getResultRowByPos(SDiskbasedBuf* pBuf, SResultRowPosition* pos) {
SFilePage* bufPage = (SFilePage*) getBufPage(pBuf, pos->pageId);
SResultRow* pRow = (SResultRow*)((char*)bufPage + pos->offset);
diff --git a/source/libs/executor/inc/executorimpl.h b/source/libs/executor/inc/executorimpl.h
index 8139e71f63..e7a3390cf3 100644
--- a/source/libs/executor/inc/executorimpl.h
+++ b/source/libs/executor/inc/executorimpl.h
@@ -454,13 +454,14 @@ typedef struct SIntervalAggOperatorInfo {
STimeWindow win; // query time range
bool timeWindowInterpo; // interpolation needed or not
char** pRow; // previous row/tuple of already processed datablock
+ SArray* pInterpCols; // interpolation columns
STableQueryInfo* pCurrent; // current tableQueryInfo struct
int32_t order; // current SSDataBlock scan order
EOPTR_EXEC_MODEL execModel; // operator execution model [batch model|stream model]
SArray* pUpdatedWindow; // updated time window due to the input data block from the downstream operator.
STimeWindowAggSupp twAggSup;
- struct SFillInfo* pFillInfo; // fill info
bool invertible;
+ SArray* pPrevValues; // SArray used to keep the previous not null value for interpolation.
} SIntervalAggOperatorInfo;
typedef struct SStreamFinalIntervalOperatorInfo {
@@ -832,7 +833,7 @@ int32_t getNumOfRowsInTimeWindow(SDataBlockInfo* pDataBlockInfo, TSKEY* pPrimary
int32_t order);
int32_t binarySearchForKey(char* pValue, int num, TSKEY key, int order);
int32_t initStreamAggSupporter(SStreamAggSupporter* pSup, const char* pKey);
-SResultRow* getNewResultRow_rv(SDiskbasedBuf* pResultBuf, int64_t tableGroupId, int32_t interBufSize);
+SResultRow* getNewResultRow(SDiskbasedBuf* pResultBuf, int64_t tableGroupId, int32_t interBufSize);
SResultWindowInfo* getSessionTimeWindow(SArray* pWinInfos, TSKEY ts, int64_t gap,
int32_t* pIndex);
int32_t updateSessionWindowInfo(SResultWindowInfo* pWinInfo, TSKEY* pTs, int32_t rows,
diff --git a/source/libs/executor/src/executil.c b/source/libs/executor/src/executil.c
index aea9d70f31..1c45e38b63 100644
--- a/source/libs/executor/src/executil.c
+++ b/source/libs/executor/src/executil.c
@@ -101,20 +101,8 @@ void resetResultRowInfo(STaskRuntimeEnv *pRuntimeEnv, SResultRowInfo *pResultRow
pResultRowInfo->size = 0;
}
-int32_t numOfClosedResultRows(SResultRowInfo *pResultRowInfo) {
- int32_t i = 0;
-// while (i < pResultRowInfo->size && pResultRowInfo->pResult[i]->closed) {
-// ++i;
-// }
-
- return i;
-}
-
void closeAllResultRows(SResultRowInfo *pResultRowInfo) {
- assert(pResultRowInfo->size >= 0 && pResultRowInfo->capacity >= pResultRowInfo->size);
-
- for (int32_t i = 0; i < pResultRowInfo->size; ++i) {
- }
+// do nothing
}
bool isResultRowClosed(SResultRow* pRow) {
@@ -258,32 +246,6 @@ int32_t getNumOfTotalRes(SGroupResInfo* pGroupResInfo) {
return (int32_t) taosArrayGetSize(pGroupResInfo->pRows);
}
-static int64_t getNumOfResultWindowRes(STaskRuntimeEnv* pRuntimeEnv, SResultRowPosition *pos, int32_t* rowCellInfoOffset) {
- STaskAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
- ASSERT(0);
-
- for (int32_t j = 0; j < pQueryAttr->numOfOutput; ++j) {
- int32_t functionId = 0;//pQueryAttr->pExpr1[j].base.functionId;
-
- /*
- * ts, tag, tagprj function can not decide the output number of current query
- * the number of output result is decided by main output
- */
- if (functionId == FUNCTION_TS || functionId == FUNCTION_TAG || functionId == FUNCTION_TAGPRJ) {
- continue;
- }
-
-// SResultRowEntryInfo *pResultInfo = getResultCell(pResultRow, j, rowCellInfoOffset);
-// assert(pResultInfo != NULL);
-//
-// if (pResultInfo->numOfRes > 0) {
-// return pResultInfo->numOfRes;
-// }
- }
-
- return 0;
-}
-
static int32_t tableResultComparFn(const void *pLeft, const void *pRight, void *param) {
int32_t left = *(int32_t *)pLeft;
int32_t right = *(int32_t *)pRight;
@@ -381,7 +343,7 @@ static int32_t mergeIntoGroupResultImplRv(STaskRuntimeEnv *pRuntimeEnv, SGroupRe
}
- int64_t num = getNumOfResultWindowRes(pRuntimeEnv, &pResultRowCell->pos, rowCellInfoOffset);
+ int64_t num = 0;//getNumOfResultWindowRes(pRuntimeEnv, &pResultRowCell->pos, rowCellInfoOffset);
if (num <= 0) {
continue;
}
diff --git a/source/libs/executor/src/executorimpl.c b/source/libs/executor/src/executorimpl.c
index 6f2be4e14e..3c46f46e19 100644
--- a/source/libs/executor/src/executorimpl.c
+++ b/source/libs/executor/src/executorimpl.c
@@ -239,36 +239,6 @@ static bool hasNull(SColumn* pColumn, SColumnDataAgg* pStatis) {
return true;
}
-static void prepareResultListBuffer(SResultRowInfo* pResultRowInfo, jmp_buf env) {
- int64_t newCapacity = 0;
-
- // more than the capacity, reallocate the resources
- if (pResultRowInfo->size < pResultRowInfo->capacity) {
- return;
- }
-
- if (pResultRowInfo->capacity > 10000) {
- newCapacity = (int64_t)(pResultRowInfo->capacity * 1.25);
- } else {
- newCapacity = (int64_t)(pResultRowInfo->capacity * 1.5);
- }
-
- if (newCapacity <= pResultRowInfo->capacity) {
- newCapacity += 4;
- }
-
- char* p = taosMemoryRealloc(pResultRowInfo->pPosition, newCapacity * sizeof(SResultRowPosition));
- if (p == NULL) {
- longjmp(env, TSDB_CODE_OUT_OF_MEMORY);
- }
-
- pResultRowInfo->pPosition = (SResultRowPosition*)p;
-
- int32_t inc = (int32_t)newCapacity - pResultRowInfo->capacity;
- memset(&pResultRowInfo->pPosition[pResultRowInfo->capacity], 0, sizeof(SResultRowPosition) * inc);
- pResultRowInfo->capacity = (int32_t)newCapacity;
-}
-
static bool chkResultRowFromKey(STaskRuntimeEnv* pRuntimeEnv, SResultRowInfo* pResultRowInfo, char* pData,
int16_t bytes, bool masterscan, uint64_t uid) {
bool existed = false;
@@ -306,7 +276,7 @@ static bool chkResultRowFromKey(STaskRuntimeEnv* pRuntimeEnv, SResultRowInfo* pR
return p1 != NULL;
}
-SResultRow* getNewResultRow_rv(SDiskbasedBuf* pResultBuf, int64_t tableGroupId, int32_t interBufSize) {
+SResultRow* getNewResultRow(SDiskbasedBuf* pResultBuf, int64_t tableGroupId, int32_t interBufSize) {
SFilePage* pData = NULL;
// in the first scan, new space needed for results
@@ -375,6 +345,8 @@ SResultRow* doSetResultOutBufByKey(SDiskbasedBuf* pResultBuf, SResultRowInfo* pR
// In case of group by column query, the required SResultRow object must be existInCurrentResusltRowInfo in the
// pResultRowInfo object.
if (p1 != NULL) {
+
+ // todo
pResult = getResultRowByPos(pResultBuf, p1);
ASSERT(pResult->pageId == p1->pageId && pResult->offset == p1->offset);
}
@@ -383,34 +355,28 @@ SResultRow* doSetResultOutBufByKey(SDiskbasedBuf* pResultBuf, SResultRowInfo* pR
// 1. close current opened time window
if (pResultRowInfo->cur.pageId != -1 && ((pResult == NULL) || (pResult->pageId != pResultRowInfo->cur.pageId &&
pResult->offset != pResultRowInfo->cur.offset))) {
- // todo extract function
SResultRowPosition pos = pResultRowInfo->cur;
- SFilePage* pPage = getBufPage(pResultBuf, pos.pageId);
- SResultRow* pRow = (SResultRow*)((char*)pPage + pos.offset);
- closeResultRow(pRow);
+ SFilePage* pPage = getBufPage(pResultBuf, pos.pageId);
releaseBufPage(pResultBuf, pPage);
}
// allocate a new buffer page
- prepareResultListBuffer(pResultRowInfo, pTaskInfo->env);
if (pResult == NULL) {
ASSERT(pSup->resultRowSize > 0);
- pResult = getNewResultRow_rv(pResultBuf, groupId, pSup->resultRowSize);
+ pResult = getNewResultRow(pResultBuf, groupId, pSup->resultRowSize);
+
initResultRow(pResult);
// add a new result set for a new group
SResultRowPosition pos = {.pageId = pResult->pageId, .offset = pResult->offset};
- taosHashPut(pSup->pResultRowHashTable, pSup->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes), &pos,
- sizeof(SResultRowPosition));
+ taosHashPut(pSup->pResultRowHashTable, pSup->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes), &pos, sizeof(SResultRowPosition));
}
// 2. set the new time window to be the new active time window
- pResultRowInfo->pPosition[pResultRowInfo->size++] =
- (SResultRowPosition){.pageId = pResult->pageId, .offset = pResult->offset};
pResultRowInfo->cur = (SResultRowPosition){.pageId = pResult->pageId, .offset = pResult->offset};
// too many time window in query
- if (pResultRowInfo->size > MAX_INTERVAL_TIME_WINDOW) {
+ if (taosHashGetSize(pSup->pResultRowHashTable) > MAX_INTERVAL_TIME_WINDOW) {
longjmp(pTaskInfo->env, TSDB_CODE_QRY_TOO_MANY_TIMEWINDOW);
}
@@ -585,11 +551,13 @@ void initExecTimeWindowInfo(SColumnInfoData* pColData, STimeWindow* pQueryWindow
colDataAppendInt64(pColData, 4, &pQueryWindow->ekey);
}
+
void doApplyFunctions(SExecTaskInfo* taskInfo, SqlFunctionCtx* pCtx, STimeWindow* pWin,
SColumnInfoData* pTimeWindowData, int32_t offset, int32_t forwardStep, TSKEY* tsCol,
int32_t numOfTotal, int32_t numOfOutput, int32_t order) {
for (int32_t k = 0; k < numOfOutput; ++k) {
// keep it temporarily
+ // todo no need this??
bool hasAgg = pCtx[k].input.colDataAggIsSet;
int32_t numOfRows = pCtx[k].input.numOfRows;
int32_t startOffset = pCtx[k].input.startRowIndex;
@@ -609,7 +577,8 @@ void doApplyFunctions(SExecTaskInfo* taskInfo, SqlFunctionCtx* pCtx, STimeWindow
if (fmIsWindowPseudoColumnFunc(pCtx[k].functionId)) {
SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(&pCtx[k]);
- char* p = GET_ROWCELL_INTERBUF(pEntryInfo);
+
+ char* p = GET_ROWCELL_INTERBUF(pEntryInfo);
SColumnInfoData idata = {0};
idata.info.type = TSDB_DATA_TYPE_BIGINT;
@@ -620,22 +589,23 @@ void doApplyFunctions(SExecTaskInfo* taskInfo, SqlFunctionCtx* pCtx, STimeWindow
SScalarParam tw = {.numOfRows = 5, .columnData = pTimeWindowData};
pCtx[k].sfp.process(&tw, 1, &out);
pEntryInfo->numOfRes = 1;
- continue;
- }
- int32_t code = TSDB_CODE_SUCCESS;
- if (functionNeedToExecute(&pCtx[k]) && pCtx[k].fpSet.process != NULL) {
- code = pCtx[k].fpSet.process(&pCtx[k]);
- if (code != TSDB_CODE_SUCCESS) {
- qError("%s apply functions error, code: %s", GET_TASKID(taskInfo), tstrerror(code));
- taskInfo->code = code;
- longjmp(taskInfo->env, code);
- }
- }
+ } else {
+ int32_t code = TSDB_CODE_SUCCESS;
+ if (functionNeedToExecute(&pCtx[k]) && pCtx[k].fpSet.process != NULL) {
+ code = pCtx[k].fpSet.process(&pCtx[k]);
- // restore it
- pCtx[k].input.colDataAggIsSet = hasAgg;
- pCtx[k].input.startRowIndex = startOffset;
- pCtx[k].input.numOfRows = numOfRows;
+ if (code != TSDB_CODE_SUCCESS) {
+ qError("%s apply functions error, code: %s", GET_TASKID(taskInfo), tstrerror(code));
+ taskInfo->code = code;
+ longjmp(taskInfo->env, code);
+ }
+ }
+
+ // restore it
+ pCtx[k].input.colDataAggIsSet = hasAgg;
+ pCtx[k].input.startRowIndex = startOffset;
+ pCtx[k].input.numOfRows = numOfRows;
+ }
}
}
@@ -774,12 +744,14 @@ static int32_t doAggregateImpl(SOperatorInfo* pOperator, TSKEY startTs, SqlFunct
for (int32_t k = 0; k < pOperator->numOfExprs; ++k) {
if (functionNeedToExecute(&pCtx[k])) {
// todo add a dummy funtion to avoid process check
- if (pCtx[k].fpSet.process != NULL) {
- int32_t code = pCtx[k].fpSet.process(&pCtx[k]);
- if (code != TSDB_CODE_SUCCESS) {
- qError("%s aggregate function error happens, code: %s", GET_TASKID(pOperator->pTaskInfo), tstrerror(code));
- return code;
- }
+ if (pCtx[k].fpSet.process == NULL) {
+ continue;
+ }
+
+ int32_t code = pCtx[k].fpSet.process(&pCtx[k]);
+ if (code != TSDB_CODE_SUCCESS) {
+ qError("%s aggregate function error happens, code: %s", GET_TASKID(pOperator->pTaskInfo), tstrerror(code));
+ return code;
}
}
}
@@ -1218,7 +1190,6 @@ static void* destroySqlFunctionCtx(SqlFunctionCtx* pCtx, int32_t numOfOutput) {
taosVariantDestroy(&pCtx[i].param[j].param);
}
- taosVariantDestroy(&pCtx[i].tag);
taosMemoryFreeClear(pCtx[i].subsidiaries.pCtx);
taosMemoryFree(pCtx[i].input.pData);
taosMemoryFree(pCtx[i].input.pColumnDataAgg);
@@ -1248,9 +1219,9 @@ void setTaskKilled(SExecTaskInfo* pTaskInfo) { pTaskInfo->code = TSDB_CODE_TSC_Q
static bool isCachedLastQuery(STaskAttr* pQueryAttr) {
for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
int32_t functionId = getExprFunctionId(&pQueryAttr->pExpr1[i]);
- if (functionId == FUNCTION_LAST || functionId == FUNCTION_LAST_DST) {
- continue;
- }
+// if (functionId == FUNCTION_LAST || functionId == FUNCTION_LAST_DST) {
+// continue;
+// }
return false;
}
@@ -1300,7 +1271,7 @@ static int32_t updateBlockLoadStatus(STaskAttr* pQuery, int32_t status) {
for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
int32_t functionId = getExprFunctionId(&pQuery->pExpr1[i]);
-
+#if 0
if (functionId == FUNCTION_TS || functionId == FUNCTION_TS_DUMMY || functionId == FUNCTION_TAG ||
functionId == FUNCTION_TAG_DUMMY) {
continue;
@@ -1311,6 +1282,8 @@ static int32_t updateBlockLoadStatus(STaskAttr* pQuery, int32_t status) {
} else {
hasOtherFunc = true;
}
+#endif
+
}
if (hasFirstLastFunc && status == BLK_DATA_NOT_LOAD) {
@@ -1786,41 +1759,13 @@ void updateOutputBuf(SOptrBasicInfo* pBInfo, int32_t* bufCapacity, int32_t numOf
// set the correct pointer after the memory buffer reallocated.
int32_t functionId = pBInfo->pCtx[i].functionId;
-
+#if 0
if (functionId == FUNCTION_TOP || functionId == FUNCTION_BOTTOM || functionId == FUNCTION_DIFF ||
functionId == FUNCTION_DERIVATIVE) {
// if (i > 0) pBInfo->pCtx[i].pTsOutput = pBInfo->pCtx[i - 1].pOutput;
}
- }
-}
+#endif
-void copyTsColoum(SSDataBlock* pRes, SqlFunctionCtx* pCtx, int32_t numOfOutput) {
- bool needCopyTs = false;
- int32_t tsNum = 0;
- char* src = NULL;
- for (int32_t i = 0; i < numOfOutput; i++) {
- int32_t functionId = pCtx[i].functionId;
- if (functionId == FUNCTION_DIFF || functionId == FUNCTION_DERIVATIVE) {
- needCopyTs = true;
- if (i > 0 && pCtx[i - 1].functionId == FUNCTION_TS_DUMMY) {
- SColumnInfoData* pColRes = taosArrayGet(pRes->pDataBlock, i - 1); // find ts data
- src = pColRes->pData;
- }
- } else if (functionId == FUNCTION_TS_DUMMY) {
- tsNum++;
- }
- }
-
- if (!needCopyTs) return;
- if (tsNum < 2) return;
- if (src == NULL) return;
-
- for (int32_t i = 0; i < numOfOutput; i++) {
- int32_t functionId = pCtx[i].functionId;
- if (functionId == FUNCTION_TS_DUMMY) {
- SColumnInfoData* pColRes = taosArrayGet(pRes->pDataBlock, i);
- memcpy(pColRes->pData, src, pColRes->info.bytes * pRes->info.rows);
- }
}
}
@@ -2577,47 +2522,7 @@ int32_t setSDataBlockFromFetchRsp(SSDataBlock* pRes, SLoadRemoteDataInfo* pLoadI
int32_t compLen, int32_t numOfOutput, int64_t startTs, uint64_t* total,
SArray* pColList) {
if (pColList == NULL) { // data from other sources
- blockDataEnsureCapacity(pRes, numOfRows);
-
- int32_t dataLen = *(int32_t*)pData;
- pData += sizeof(int32_t);
-
- pRes->info.groupId = *(uint64_t*)pData;
- pData += sizeof(uint64_t);
-
- int32_t* colLen = (int32_t*)pData;
-
- char* pStart = pData + sizeof(int32_t) * numOfOutput;
- for (int32_t i = 0; i < numOfOutput; ++i) {
- colLen[i] = htonl(colLen[i]);
- ASSERT(colLen[i] >= 0);
-
- SColumnInfoData* pColInfoData = taosArrayGet(pRes->pDataBlock, i);
- if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
- pColInfoData->varmeta.length = colLen[i];
- pColInfoData->varmeta.allocLen = colLen[i];
-
- memcpy(pColInfoData->varmeta.offset, pStart, sizeof(int32_t) * numOfRows);
- pStart += sizeof(int32_t) * numOfRows;
-
- if (colLen[i] > 0) {
- taosMemoryFreeClear(pColInfoData->pData);
- pColInfoData->pData = taosMemoryMalloc(colLen[i]);
- }
- } else {
- memcpy(pColInfoData->nullbitmap, pStart, BitmapLen(numOfRows));
- pStart += BitmapLen(numOfRows);
- }
-
- if (colLen[i] > 0) {
- memcpy(pColInfoData->pData, pStart, colLen[i]);
- }
-
- // TODO setting this flag to true temporarily so aggregate function on stable will
- // examine NULL value for non-primary key column
- pColInfoData->hasNull = true;
- pStart += colLen[i];
- }
+ blockCompressDecode(pRes, numOfOutput, numOfRows, pData);
} else { // extract data according to pColList
ASSERT(numOfOutput == taosArrayGetSize(pColList));
char* pStart = pData;
@@ -3587,7 +3492,7 @@ int32_t aggDecodeResultRow(SOperatorInfo* pOperator, char* result) {
offset += sizeof(int32_t);
uint64_t tableGroupId = *(uint64_t*)(result + offset);
- SResultRow* resultRow = getNewResultRow_rv(pSup->pResultBuf, tableGroupId, pSup->resultRowSize);
+ SResultRow* resultRow = getNewResultRow(pSup->pResultBuf, tableGroupId, pSup->resultRowSize);
if (!resultRow) {
return TSDB_CODE_TSC_INVALID_INPUT;
}
@@ -3610,10 +3515,6 @@ int32_t aggDecodeResultRow(SOperatorInfo* pOperator, char* result) {
offset += valueLen;
initResultRow(resultRow);
- prepareResultListBuffer(&pInfo->resultRowInfo, pOperator->pTaskInfo->env);
- // pInfo->resultRowInfo.cur = pInfo->resultRowInfo.size;
- // pInfo->resultRowInfo.pPosition[pInfo->resultRowInfo.size++] =
- // (SResultRowPosition){.pageId = resultRow->pageId, .offset = resultRow->offset};
pInfo->resultRowInfo.cur = (SResultRowPosition){.pageId = resultRow->pageId, .offset = resultRow->offset};
}
@@ -3905,18 +3806,6 @@ static SSDataBlock* doFill(SOperatorInfo* pOperator) {
}
}
-// todo set the attribute of query scan count
-static int32_t getNumOfScanTimes(STaskAttr* pQueryAttr) {
- for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
- int32_t functionId = getExprFunctionId(&pQueryAttr->pExpr1[i]);
- if (functionId == FUNCTION_STDDEV || functionId == FUNCTION_PERCT) {
- return 2;
- }
- }
-
- return 1;
-}
-
static void destroyOperatorInfo(SOperatorInfo* pOperator) {
if (pOperator == NULL) {
return;
diff --git a/source/libs/executor/src/groupoperator.c b/source/libs/executor/src/groupoperator.c
index d388b802f3..8c3a0c0e6e 100644
--- a/source/libs/executor/src/groupoperator.c
+++ b/source/libs/executor/src/groupoperator.c
@@ -110,9 +110,11 @@ static bool groupKeyCompare(SArray* pGroupCols, SArray* pGroupColVals, SSDataBlo
return true;
}
-static void recordNewGroupKeys(SArray* pGroupCols, SArray* pGroupColVals, SSDataBlock* pBlock, int32_t rowIndex, int32_t numOfGroupCols) {
+static void recordNewGroupKeys(SArray* pGroupCols, SArray* pGroupColVals, SSDataBlock* pBlock, int32_t rowIndex) {
SColumnDataAgg* pColAgg = NULL;
+ size_t numOfGroupCols = taosArrayGetSize(pGroupCols);
+
for (int32_t i = 0; i < numOfGroupCols; ++i) {
SColumn* pCol = taosArrayGet(pGroupCols, i);
SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, pCol->slotId);
@@ -208,7 +210,7 @@ static void doHashGroupbyAgg(SOperatorInfo* pOperator, SSDataBlock* pBlock) {
for (int32_t j = 0; j < pBlock->info.rows; ++j) {
// Compare with the previous row of this column, and do not set the output buffer again if they are identical.
if (!pInfo->isInit) {
- recordNewGroupKeys(pInfo->pGroupCols, pInfo->pGroupColVals, pBlock, j, numOfGroupCols);
+ recordNewGroupKeys(pInfo->pGroupCols, pInfo->pGroupColVals, pBlock, j);
pInfo->isInit = true;
num++;
continue;
@@ -223,7 +225,7 @@ static void doHashGroupbyAgg(SOperatorInfo* pOperator, SSDataBlock* pBlock) {
// The first row of a new block does not belongs to the previous existed group
if (j == 0) {
num++;
- recordNewGroupKeys(pInfo->pGroupCols, pInfo->pGroupColVals, pBlock, j, numOfGroupCols);
+ recordNewGroupKeys(pInfo->pGroupCols, pInfo->pGroupColVals, pBlock, j);
continue;
}
@@ -238,7 +240,7 @@ static void doHashGroupbyAgg(SOperatorInfo* pOperator, SSDataBlock* pBlock) {
// assign the group keys or user input constant values if required
doAssignGroupKeys(pCtx, pOperator->numOfExprs, pBlock->info.rows, rowIndex);
- recordNewGroupKeys(pInfo->pGroupCols, pInfo->pGroupColVals, pBlock, j, numOfGroupCols);
+ recordNewGroupKeys(pInfo->pGroupCols, pInfo->pGroupColVals, pBlock, j);
num = 1;
}
@@ -409,7 +411,7 @@ static void doHashPartition(SOperatorInfo* pOperator, SSDataBlock* pBlock) {
int32_t numOfGroupCols = taosArrayGetSize(pInfo->pGroupCols);
for (int32_t j = 0; j < pBlock->info.rows; ++j) {
- recordNewGroupKeys(pInfo->pGroupCols, pInfo->pGroupColVals, pBlock, j, numOfGroupCols);
+ recordNewGroupKeys(pInfo->pGroupCols, pInfo->pGroupColVals, pBlock, j);
int32_t len = buildGroupKeys(pInfo->keyBuf, pInfo->pGroupColVals);
SDataGroupInfo* pGInfo = NULL;
diff --git a/source/libs/executor/src/scanoperator.c b/source/libs/executor/src/scanoperator.c
index c5d19981cf..348d85943e 100644
--- a/source/libs/executor/src/scanoperator.c
+++ b/source/libs/executor/src/scanoperator.c
@@ -327,8 +327,8 @@ void addTagPseudoColumnData(SReadHandle *pHandle, SExprInfo* pPseudoExpr, int32_
for (int32_t i = 0; i < pBlock->info.rows; ++i) {
colDataAppend(pColInfoData, i, data, (data == NULL));
}
- if(pColInfoData->info.type != TSDB_DATA_TYPE_JSON && p != NULL &&
- IS_VAR_DATA_TYPE(((const STagVal *)p)->type) && data){
+ if (data && (pColInfoData->info.type != TSDB_DATA_TYPE_JSON) && p != NULL &&
+ IS_VAR_DATA_TYPE(((const STagVal*)p)->type)) {
taosMemoryFree(data);
}
}
@@ -531,7 +531,7 @@ SOperatorInfo* createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode,
}
pInfo->scanInfo = (SScanInfo){.numOfAsc = pTableScanNode->scanSeq[0], .numOfDesc = pTableScanNode->scanSeq[1]};
- // pInfo->scanInfo = (SScanInfo){.numOfAsc = 0, .numOfDesc = 1}; // for debug purpose
+// pInfo->scanInfo = (SScanInfo){.numOfAsc = 0, .numOfDesc = 1}; // for debug purpose
pInfo->readHandle = *readHandle;
pInfo->interval = extractIntervalInfo(pTableScanNode);
diff --git a/source/libs/executor/src/timewindowoperator.c b/source/libs/executor/src/timewindowoperator.c
index 14344daf81..41037e9f16 100644
--- a/source/libs/executor/src/timewindowoperator.c
+++ b/source/libs/executor/src/timewindowoperator.c
@@ -1,3 +1,4 @@
+#include "function.h"
#include "executorimpl.h"
#include "functionMgt.h"
#include "tdatablock.h"
@@ -11,6 +12,11 @@ typedef enum SResultTsInterpType {
static SSDataBlock* doStreamFinalIntervalAgg(SOperatorInfo* pOperator);
static SSDataBlock* doStreamSessionWindowAgg(SOperatorInfo* pOperator);
+static int64_t* extractTsCol(SSDataBlock* pBlock, const SIntervalAggOperatorInfo* pInfo);
+
+static SResultRowPosition addToOpenWindowList(SResultRowInfo* pResultRowInfo, const SResultRow* pResult);
+static void doCloseWindow(SResultRowInfo* pResultRowInfo, const SIntervalAggOperatorInfo* pInfo, SResultRow* pResult);
+
/*
* There are two cases to handle:
*
@@ -21,47 +27,11 @@ static SSDataBlock* doStreamSessionWindowAgg(SOperatorInfo* pOperator);
* is a previous result generated or not.
*/
static void setIntervalQueryRange(STableQueryInfo* pTableQueryInfo, TSKEY key, STimeWindow* pQRange) {
- // SResultRowInfo* pResultRowInfo = &pTableQueryInfo->resInfo;
- // if (pResultRowInfo->curPos != -1) {
- // return;
- // }
-
- // pTableQueryInfo->win.skey = key;
- // STimeWindow win = {.skey = key, .ekey = pQRange->ekey};
-
- /**
- * In handling the both ascending and descending order super table query, we need to find the first qualified
- * timestamp of this table, and then set the first qualified start timestamp.
- * In ascending query, the key is the first qualified timestamp. However, in the descending order query, additional
- * operations involve.
- */
- // STimeWindow w = TSWINDOW_INITIALIZER;
- //
- // TSKEY sk = TMIN(win.skey, win.ekey);
- // TSKEY ek = TMAX(win.skey, win.ekey);
- // getAlignQueryTimeWindow(pQueryAttr, win.skey, sk, ek, &w);
-
- // if (pResultRowInfo->prevSKey == TSKEY_INITIAL_VAL) {
- // if (!QUERY_IS_ASC_QUERY(pQueryAttr)) {
- // assert(win.ekey == pQueryAttr->window.ekey);
- // }
- //
- // pResultRowInfo->prevSKey = w.skey;
- // }
-
- // pTableQueryInfo->lastKey = pTableQueryInfo->win.skey;
+ // do nothing
}
-static TSKEY getStartTsKey(STimeWindow* win, const TSKEY* tsCols, int32_t rows, bool ascQuery) {
- TSKEY ts = TSKEY_INITIAL_VAL;
- if (tsCols == NULL) {
- ts = ascQuery ? win->skey : win->ekey;
- } else {
-// int32_t offset = ascQuery ? 0 : rows - 1;
- ts = tsCols[0];
- }
-
- return ts;
+static TSKEY getStartTsKey(STimeWindow* win, const TSKEY* tsCols) {
+ return tsCols == NULL? win->skey:tsCols[0];
}
static void getInitialStartTimeWindow(SInterval* pInterval, int32_t precision, TSKEY ts, STimeWindow* w,
@@ -134,8 +104,10 @@ static int32_t setTimeWindowOutputBuf(SResultRowInfo* pResultRowInfo, STimeWindo
// set time window for current result
pResultRow->win = (*win);
+
*pResult = pResultRow;
setResultRowInitCtx(pResultRow, pCtx, numOfOutput, rowCellInfoOffset);
+
return TSDB_CODE_SUCCESS;
}
@@ -163,38 +135,38 @@ static void doKeepNewWindowStartInfo(SWindowRowsSup* pRowSup, const int64_t* tsL
static FORCE_INLINE int32_t getForwardStepsInBlock(int32_t numOfRows, __block_search_fn_t searchFn, TSKEY ekey,
int16_t pos, int16_t order, int64_t* pData) {
- int32_t forwardStep = 0;
+ int32_t forwardRows = 0;
if (order == TSDB_ORDER_ASC) {
int32_t end = searchFn((char*)&pData[pos], numOfRows - pos, ekey, order);
if (end >= 0) {
- forwardStep = end;
+ forwardRows = end;
if (pData[end + pos] == ekey) {
- forwardStep += 1;
+ forwardRows += 1;
}
}
} else {
int32_t end = searchFn((char*)&pData[pos], numOfRows - pos, ekey, order);
if (end >= 0) {
- forwardStep = end;
+ forwardRows = end;
if (pData[end + pos] == ekey) {
- forwardStep += 1;
+ forwardRows += 1;
}
}
// int32_t end = searchFn((char*)pData, pos + 1, ekey, order);
// if (end >= 0) {
-// forwardStep = pos - end;
+// forwardRows = pos - end;
//
// if (pData[end] == ekey) {
-// forwardStep += 1;
+// forwardRows += 1;
// }
// }
}
- assert(forwardStep >= 0);
- return forwardStep;
+ assert(forwardRows >= 0);
+ return forwardRows;
}
int32_t binarySearchForKey(char* pValue, int num, TSKEY key, int order) {
@@ -339,34 +311,40 @@ static void getNextTimeWindow(SInterval* pInterval, int32_t precision, int32_t o
tw->ekey -= 1;
}
-void doTimeWindowInterpolation(SOperatorInfo* pOperator, SOptrBasicInfo* pInfo, SArray* pDataBlock, TSKEY prevTs,
+void doTimeWindowInterpolation(SIntervalAggOperatorInfo *pInfo, int32_t numOfExprs, SArray* pDataBlock, TSKEY prevTs,
int32_t prevRowIndex, TSKEY curTs, int32_t curRowIndex, TSKEY windowKey, int32_t type) {
- SExprInfo* pExpr = pOperator->pExpr;
+ SqlFunctionCtx* pCtx = pInfo->binfo.pCtx;
- SqlFunctionCtx* pCtx = pInfo->pCtx;
+ int32_t index = 1;
+ for (int32_t k = 0; k < numOfExprs; ++k) {
- for (int32_t k = 0; k < pOperator->numOfExprs; ++k) {
- int32_t functionId = pCtx[k].functionId;
- if (functionId != FUNCTION_TWA && functionId != FUNCTION_INTERP) {
+ // todo use flag instead of function name
+ if (strcmp(pCtx[k].pExpr->pExpr->_function.functionName, "twa") != 0) {
pCtx[k].start.key = INT64_MIN;
continue;
}
- SColIndex* pColIndex = NULL /*&pExpr[k].base.colInfo*/;
- int16_t index = pColIndex->colIndex;
- SColumnInfoData* pColInfo = taosArrayGet(pDataBlock, index);
+// if (functionId != FUNCTION_TWA && functionId != FUNCTION_INTERP) {
+// pCtx[k].start.key = INT64_MIN;
+// continue;
+// }
+
+ SFunctParam* pParam = &pCtx[k].param[0];
+ SColumnInfoData* pColInfo = taosArrayGet(pDataBlock, pParam->pCol->slotId);
+
+ ASSERT(pColInfo->info.colId == pParam->pCol->colId && curTs != windowKey);
- // assert(pColInfo->info.colId == pColIndex->info.colId && curTs != windowKey);
double v1 = 0, v2 = 0, v = 0;
-
if (prevRowIndex == -1) {
- // GET_TYPED_DATA(v1, double, pColInfo->info.type, (char*)pRuntimeEnv->prevRow[index]);
+ SGroupKeys* p = taosArrayGet(pInfo->pPrevValues, index);
+ GET_TYPED_DATA(v1, double, pColInfo->info.type, p->pData);
} else {
- GET_TYPED_DATA(v1, double, pColInfo->info.type, (char*)pColInfo->pData + prevRowIndex * pColInfo->info.bytes);
+ GET_TYPED_DATA(v1, double, pColInfo->info.type, colDataGetData(pColInfo, prevRowIndex));
}
- GET_TYPED_DATA(v2, double, pColInfo->info.type, (char*)pColInfo->pData + curRowIndex * pColInfo->info.bytes);
+ GET_TYPED_DATA(v2, double, pColInfo->info.type, colDataGetData(pColInfo, curRowIndex));
+#if 0
if (functionId == FUNCTION_INTERP) {
if (type == RESULT_ROW_START_INTERP) {
pCtx[k].start.key = prevTs;
@@ -386,6 +364,8 @@ void doTimeWindowInterpolation(SOperatorInfo* pOperator, SOptrBasicInfo* pInfo,
}
}
} else if (functionId == FUNCTION_TWA) {
+#endif
+
SPoint point1 = (SPoint){.key = prevTs, .val = &v1};
SPoint point2 = (SPoint){.key = curTs, .val = &v2};
SPoint point = (SPoint){.key = windowKey, .val = &v};
@@ -399,8 +379,13 @@ void doTimeWindowInterpolation(SOperatorInfo* pOperator, SOptrBasicInfo* pInfo,
pCtx[k].end.key = point.key;
pCtx[k].end.val = v;
}
+
+ index += 1;
}
+#if 0
}
+#endif
+
}
static void setNotInterpoWindowKey(SqlFunctionCtx* pCtx, int32_t numOfOutput, int32_t type) {
@@ -415,62 +400,59 @@ static void setNotInterpoWindowKey(SqlFunctionCtx* pCtx, int32_t numOfOutput, in
}
}
-static bool setTimeWindowInterpolationStartTs(SOperatorInfo* pOperatorInfo, SqlFunctionCtx* pCtx, int32_t pos,
- int32_t numOfRows, SArray* pDataBlock, const TSKEY* tsCols,
- STimeWindow* win) {
- bool ascQuery = true;
+static bool setTimeWindowInterpolationStartTs(SIntervalAggOperatorInfo *pInfo, SqlFunctionCtx* pCtx, int32_t numOfExprs, int32_t pos,
+ SSDataBlock* pBlock, const TSKEY* tsCols, STimeWindow* win) {
+ bool ascQuery = (pInfo->order == TSDB_ORDER_ASC);
+
TSKEY curTs = tsCols[pos];
- TSKEY lastTs = 0; //*(TSKEY*)pRuntimeEnv->prevRow[0];
+
+ SGroupKeys* pTsKey = taosArrayGet(pInfo->pPrevValues, 0);
+ TSKEY lastTs = *(int64_t*) pTsKey->pData;
// lastTs == INT64_MIN and pos == 0 means this is the first time window, interpolation is not needed.
// start exactly from this point, no need to do interpolation
TSKEY key = ascQuery ? win->skey : win->ekey;
if (key == curTs) {
- setNotInterpoWindowKey(pCtx, pOperatorInfo->numOfExprs, RESULT_ROW_START_INTERP);
+ setNotInterpoWindowKey(pCtx, numOfExprs, RESULT_ROW_START_INTERP);
return true;
}
- if (lastTs == INT64_MIN && ((pos == 0 && ascQuery) || (pos == (numOfRows - 1) && !ascQuery))) {
- setNotInterpoWindowKey(pCtx, pOperatorInfo->numOfExprs, RESULT_ROW_START_INTERP);
- return true;
+ // it is the first time window, no need to do interpolation
+ if (pTsKey->isNull && pos == 0) {
+ setNotInterpoWindowKey(pCtx, numOfExprs, RESULT_ROW_START_INTERP);
+ } else {
+ TSKEY prevTs = ((pos == 0) ? lastTs : tsCols[pos - 1]);
+ doTimeWindowInterpolation(pInfo, numOfExprs, pBlock->pDataBlock, prevTs, pos - 1, curTs, pos, key,
+ RESULT_ROW_START_INTERP);
}
- int32_t step = 1; // GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
- TSKEY prevTs = ((pos == 0 && ascQuery) || (pos == (numOfRows - 1) && !ascQuery)) ? lastTs : tsCols[pos - step];
-
- doTimeWindowInterpolation(pOperatorInfo, pOperatorInfo->info, pDataBlock, prevTs, pos - step, curTs, pos, key,
- RESULT_ROW_START_INTERP);
return true;
}
-static bool setTimeWindowInterpolationEndTs(SOperatorInfo* pOperatorInfo, SqlFunctionCtx* pCtx, int32_t endRowIndex,
- SArray* pDataBlock, const TSKEY* tsCols, TSKEY blockEkey,
- STimeWindow* win) {
- int32_t order = TSDB_ORDER_ASC;
- int32_t numOfOutput = pOperatorInfo->numOfExprs;
+static bool setTimeWindowInterpolationEndTs(SIntervalAggOperatorInfo *pInfo, SqlFunctionCtx* pCtx, int32_t numOfExprs, int32_t endRowIndex,
+ SArray* pDataBlock, const TSKEY* tsCols, TSKEY blockEkey, STimeWindow* win) {
+ int32_t order = pInfo->order;
TSKEY actualEndKey = tsCols[endRowIndex];
- TSKEY key = order ? win->ekey : win->skey;
+ TSKEY key = (order == TSDB_ORDER_ASC) ? win->ekey : win->skey;
// not ended in current data block, do not invoke interpolation
- if ((key > blockEkey /*&& QUERY_IS_ASC_QUERY(pQueryAttr)*/) ||
- (key < blockEkey /*&& !QUERY_IS_ASC_QUERY(pQueryAttr)*/)) {
- setNotInterpoWindowKey(pCtx, numOfOutput, RESULT_ROW_END_INTERP);
+ if ((key > blockEkey && (order == TSDB_ORDER_ASC)) || (key < blockEkey && (order == TSDB_ORDER_DESC))) {
+ setNotInterpoWindowKey(pCtx, numOfExprs, RESULT_ROW_END_INTERP);
return false;
}
- // there is actual end point of current time window, no interpolation need
+ // there is actual end point of current time window, no interpolation needs
if (key == actualEndKey) {
- setNotInterpoWindowKey(pCtx, numOfOutput, RESULT_ROW_END_INTERP);
+ setNotInterpoWindowKey(pCtx, numOfExprs, RESULT_ROW_END_INTERP);
return true;
}
- int32_t step = GET_FORWARD_DIRECTION_FACTOR(order);
- int32_t nextRowIndex = endRowIndex + step;
+ int32_t nextRowIndex = endRowIndex + 1;
assert(nextRowIndex >= 0);
TSKEY nextKey = tsCols[nextRowIndex];
- doTimeWindowInterpolation(pOperatorInfo, pOperatorInfo->info, pDataBlock, actualEndKey, endRowIndex, nextKey,
+ doTimeWindowInterpolation(pInfo, numOfExprs, pDataBlock, actualEndKey, endRowIndex, nextKey,
nextRowIndex, key, RESULT_ROW_END_INTERP);
return true;
}
@@ -542,8 +524,8 @@ static int32_t getNextQualifiedWindow(SInterval* pInterval, STimeWindow* pNext,
return startPos;
}
-static bool resultRowInterpolated(SResultRow* pResult, SResultTsInterpType type) {
- assert(pResult != NULL && (type == RESULT_ROW_START_INTERP || type == RESULT_ROW_END_INTERP));
+static bool isResultRowInterpolated(SResultRow* pResult, SResultTsInterpType type) {
+ ASSERT(pResult != NULL && (type == RESULT_ROW_START_INTERP || type == RESULT_ROW_END_INTERP));
if (type == RESULT_ROW_START_INTERP) {
return pResult->startInterp == true;
} else {
@@ -560,34 +542,29 @@ static void setResultRowInterpo(SResultRow* pResult, SResultTsInterpType type) {
}
}
-static void doWindowBorderInterpolation(SOperatorInfo* pOperatorInfo, SSDataBlock* pBlock, SqlFunctionCtx* pCtx,
- SResultRow* pResult, STimeWindow* win, int32_t startPos, int32_t forwardStep,
- int32_t order, bool timeWindowInterpo) {
- if (!timeWindowInterpo) {
+static void doWindowBorderInterpolation(SIntervalAggOperatorInfo *pInfo, SSDataBlock* pBlock, int32_t numOfExprs, SqlFunctionCtx* pCtx,
+ SResultRow* pResult, STimeWindow* win, int32_t startPos, int32_t forwardRows) {
+ if (!pInfo->timeWindowInterpo) {
return;
}
- assert(pBlock != NULL);
- int32_t step = GET_FORWARD_DIRECTION_FACTOR(order);
-
+ ASSERT(pBlock != NULL);
if (pBlock->pDataBlock == NULL) {
// tscError("pBlock->pDataBlock == NULL");
return;
}
- SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);
+ SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, pInfo->primaryTsIndex);
TSKEY* tsCols = (TSKEY*)(pColInfo->pData);
- bool done = resultRowInterpolated(pResult, RESULT_ROW_START_INTERP);
+ bool done = isResultRowInterpolated(pResult, RESULT_ROW_START_INTERP);
if (!done) { // it is not interpolated, now start to generated the interpolated value
- int32_t startRowIndex = startPos;
- bool interp = setTimeWindowInterpolationStartTs(pOperatorInfo, pCtx, startRowIndex, pBlock->info.rows,
- pBlock->pDataBlock, tsCols, win);
+ bool interp = setTimeWindowInterpolationStartTs(pInfo, pCtx, numOfExprs, startPos, pBlock, tsCols, win);
if (interp) {
setResultRowInterpo(pResult, RESULT_ROW_START_INTERP);
}
} else {
- setNotInterpoWindowKey(pCtx, pOperatorInfo->numOfExprs, RESULT_ROW_START_INTERP);
+ setNotInterpoWindowKey(pCtx, numOfExprs, RESULT_ROW_START_INTERP);
}
// point interpolation does not require the end key time window interpolation.
@@ -596,29 +573,106 @@ static void doWindowBorderInterpolation(SOperatorInfo* pOperatorInfo, SSDataBloc
// }
// interpolation query does not generate the time window end interpolation
- done = resultRowInterpolated(pResult, RESULT_ROW_END_INTERP);
+ done = isResultRowInterpolated(pResult, RESULT_ROW_END_INTERP);
if (!done) {
- int32_t endRowIndex = startPos + (forwardStep - 1) * step;
+ int32_t endRowIndex = startPos + forwardRows - 1;
- TSKEY endKey = (order == TSDB_ORDER_ASC) ? pBlock->info.window.ekey : pBlock->info.window.skey;
+ TSKEY endKey = (pInfo->order == TSDB_ORDER_ASC) ? pBlock->info.window.ekey : pBlock->info.window.skey;
bool interp =
- setTimeWindowInterpolationEndTs(pOperatorInfo, pCtx, endRowIndex, pBlock->pDataBlock, tsCols, endKey, win);
+ setTimeWindowInterpolationEndTs(pInfo, pCtx, numOfExprs, endRowIndex, pBlock->pDataBlock, tsCols, endKey, win);
if (interp) {
setResultRowInterpo(pResult, RESULT_ROW_END_INTERP);
}
} else {
- setNotInterpoWindowKey(pCtx, pOperatorInfo->numOfExprs, RESULT_ROW_END_INTERP);
+ setNotInterpoWindowKey(pCtx, numOfExprs, RESULT_ROW_END_INTERP);
}
}
-static void saveDataBlockLastRow(char** pRow, SArray* pDataBlock, int32_t rowIndex, int32_t numOfCols) {
- if (pDataBlock == NULL) {
+static void saveDataBlockLastRow(SArray* pPrevKeys, const SSDataBlock* pBlock, SArray* pCols) {
+ if (pBlock->pDataBlock == NULL) {
return;
}
- for (int32_t k = 0; k < numOfCols; ++k) {
- SColumnInfoData* pColInfo = taosArrayGet(pDataBlock, k);
- memcpy(pRow[k], ((char*)pColInfo->pData) + (pColInfo->info.bytes * rowIndex), pColInfo->info.bytes);
+ size_t num = taosArrayGetSize(pPrevKeys);
+ for (int32_t k = 0; k < num; ++k) {
+ SColumn* pc = taosArrayGet(pCols, k);
+
+ SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, pc->slotId);
+
+ SGroupKeys* pkey = taosArrayGet(pPrevKeys, k);
+ for(int32_t i = pBlock->info.rows - 1; i >= 0; --i) {
+ if (colDataIsNull_s(pColInfo, i)) {
+ continue;
+ }
+
+ char* val = colDataGetData(pColInfo, i);
+ if (IS_VAR_DATA_TYPE(pkey->type)) {
+ memcpy(pkey->pData, val, varDataTLen(val));
+ ASSERT(varDataTLen(val) <= pkey->bytes);
+ } else {
+ memcpy(pkey->pData, val, pkey->bytes);
+ }
+
+ break;
+ }
+ }
+}
+
+static void doInterpUnclosedTimeWindow(SOperatorInfo* pOperatorInfo, int32_t numOfExprs, SResultRowInfo* pResultRowInfo,
+ SSDataBlock* pBlock, int32_t scanFlag, int64_t* tsCols, SResultRowPosition* p) {
+ SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;
+
+ SIntervalAggOperatorInfo* pInfo = (SIntervalAggOperatorInfo*)pOperatorInfo->info;
+
+ int32_t startPos = 0;
+ int32_t numOfOutput = pOperatorInfo->numOfExprs;
+ uint64_t groupId = pBlock->info.groupId;
+
+ SResultRow* pResult = NULL;
+
+ while (1) {
+ SListNode* pn = tdListGetHead(pResultRowInfo->openWindow);
+
+ SResultRowPosition* p1 = (SResultRowPosition*)pn->data;
+ if (p->pageId == p1->pageId && p->offset == p1->offset) {
+ break;
+ }
+
+ SResultRow* pr = getResultRowByPos(pInfo->aggSup.pResultBuf, p1);
+ ASSERT(pr->offset == p1->offset && pr->pageId == p1->pageId);
+
+ if (pr->closed) {
+ ASSERT(isResultRowInterpolated(pr, RESULT_ROW_START_INTERP) && isResultRowInterpolated(pr, RESULT_ROW_END_INTERP));
+ tdListPopHead(pResultRowInfo->openWindow);
+ continue;
+ }
+
+ STimeWindow w = pr->win;
+ int32_t ret = setTimeWindowOutputBuf(pResultRowInfo, &w, (scanFlag == MAIN_SCAN), &pResult, groupId, pInfo->binfo.pCtx,
+ numOfOutput, pInfo->binfo.rowCellInfoOffset, &pInfo->aggSup, pTaskInfo);
+ if (ret != TSDB_CODE_SUCCESS) {
+ longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
+ }
+
+ ASSERT(!isResultRowInterpolated(pResult, RESULT_ROW_END_INTERP));
+
+ SGroupKeys *pTsKey = taosArrayGet(pInfo->pPrevValues, 0);
+ int64_t prevTs = *(int64_t*) pTsKey->pData;
+ doTimeWindowInterpolation(pInfo, numOfOutput, pBlock->pDataBlock, prevTs, -1, tsCols[startPos], startPos,
+ w.ekey, RESULT_ROW_END_INTERP);
+
+ setResultRowInterpo(pResult, RESULT_ROW_END_INTERP);
+ setNotInterpoWindowKey(pInfo->binfo.pCtx, numOfExprs, RESULT_ROW_START_INTERP);
+
+ doApplyFunctions(pTaskInfo, pInfo->binfo.pCtx, &w, &pInfo->twAggSup.timeWindowData, startPos, 0, tsCols,
+ pBlock->info.rows, numOfExprs, pInfo->order);
+
+ if (isResultRowInterpolated(pResult, RESULT_ROW_END_INTERP)) {
+ closeResultRow(pr);
+ tdListPopHead(pResultRowInfo->openWindow);
+ } else { // the remains are can not be closed yet.
+ break;
+ }
}
}
@@ -698,7 +752,7 @@ static int32_t saveResult(SResultRow* result, uint64_t groupId, SArray* pUpdated
return TSDB_CODE_SUCCESS;
}
}
-
+
SResKeyPos* newPos = taosMemoryMalloc(sizeof(SResKeyPos) + sizeof(uint64_t));
if (newPos == NULL) {
return TSDB_CODE_OUT_OF_MEMORY;
@@ -713,36 +767,23 @@ static int32_t saveResult(SResultRow* result, uint64_t groupId, SArray* pUpdated
}
static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResultRowInfo, SSDataBlock* pBlock,
- uint64_t tableGroupId, SArray* pUpdated) {
+ int32_t scanFlag, SArray* pUpdated) {
SIntervalAggOperatorInfo* pInfo = (SIntervalAggOperatorInfo*)pOperatorInfo->info;
SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;
- int32_t numOfOutput = pOperatorInfo->numOfExprs;
- int32_t step = 1;
- bool ascScan = (pInfo->order == TSDB_ORDER_ASC);
-
- // int32_t prevIndex = pResultRowInfo->curPos;
-
- TSKEY* tsCols = NULL;
- if (pBlock->pDataBlock != NULL) {
- SColumnInfoData* pColDataInfo = taosArrayGet(pBlock->pDataBlock, pInfo->primaryTsIndex);
- tsCols = (int64_t*)pColDataInfo->pData;
-
- if (tsCols != NULL) {
- blockDataUpdateTsWindow(pBlock, pInfo->primaryTsIndex);
- }
- }
-
- int32_t startPos = 0;
- TSKEY ts = getStartTsKey(&pBlock->info.window, tsCols, pBlock->info.rows, ascScan);
+ int32_t startPos = 0;
+ int32_t numOfOutput = pOperatorInfo->numOfExprs;
+ int64_t *tsCols = extractTsCol(pBlock, pInfo);
+ uint64_t tableGroupId = pBlock->info.groupId;
+ bool ascScan = (pInfo->order == TSDB_ORDER_ASC);
+ TSKEY ts = getStartTsKey(&pBlock->info.window, tsCols);
+ SResultRow* pResult = NULL;
STimeWindow win = getActiveTimeWindow(pInfo->aggSup.pResultBuf, pResultRowInfo, ts, &pInfo->interval,
pInfo->interval.precision, &pInfo->win);
- bool masterScan = true;
- SResultRow* pResult = NULL;
- int32_t ret = setTimeWindowOutputBuf(pResultRowInfo, &win, masterScan, &pResult, tableGroupId, pInfo->binfo.pCtx,
+ int32_t ret = setTimeWindowOutputBuf(pResultRowInfo, &win, (scanFlag == MAIN_SCAN), &pResult, tableGroupId, pInfo->binfo.pCtx,
numOfOutput, pInfo->binfo.rowCellInfoOffset, &pInfo->aggSup, pTaskInfo);
if (ret != TSDB_CODE_SUCCESS || pResult == NULL) {
longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
@@ -758,63 +799,35 @@ static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResul
}
}
- int32_t forwardStep = 0;
TSKEY ekey = ascScan? win.ekey:win.skey;
- forwardStep =
- getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, pInfo->order);
- ASSERT(forwardStep > 0);
+ int32_t forwardRows = getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, pInfo->order);
+ ASSERT(forwardRows > 0);
// prev time window not interpolation yet.
- // int32_t curIndex = pResultRowInfo->curPos;
-
-#if 0
- if (prevIndex != -1 && prevIndex < curIndex && pInfo->timeWindowInterpo) {
- for (int32_t j = prevIndex; j < curIndex; ++j) { // previous time window may be all closed already.
- SResultRow* pRes = getResultRow(pResultRowInfo, j);
- if (pRes->closed) {
- assert(resultRowInterpolated(pRes, RESULT_ROW_START_INTERP) && resultRowInterpolated(pRes, RESULT_ROW_END_INTERP));
- continue;
- }
-
- STimeWindow w = pRes->win;
- ret = setTimeWindowOutputBuf(pResultRowInfo, pBlock->info.uid, &w, masterScan, &pResult, tableGroupId,
- pInfo->binfo.pCtx, numOfOutput, pInfo->binfo.rowCellInfoOffset, &pInfo->aggSup,
- pTaskInfo);
- if (ret != TSDB_CODE_SUCCESS) {
- longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
- }
-
- assert(!resultRowInterpolated(pResult, RESULT_ROW_END_INTERP));
- doTimeWindowInterpolation(pOperatorInfo, &pInfo->binfo, pBlock->pDataBlock, *(TSKEY*)pInfo->pRow[0], -1,
- tsCols[startPos], startPos, w.ekey, RESULT_ROW_END_INTERP);
-
- setResultRowInterpo(pResult, RESULT_ROW_END_INTERP);
- setNotInterpoWindowKey(pInfo->binfo.pCtx, pOperatorInfo->numOfExprs, RESULT_ROW_START_INTERP);
-
- doApplyFunctions(pInfo->binfo.pCtx, &w, &pInfo->timeWindowData, startPos, 0, tsCols, pBlock->info.rows, numOfOutput, TSDB_ORDER_ASC);
- }
+ if (pInfo->timeWindowInterpo) {
+ SResultRowPosition pos = addToOpenWindowList(pResultRowInfo, pResult);
+ doInterpUnclosedTimeWindow(pOperatorInfo, numOfOutput, pResultRowInfo, pBlock, scanFlag, tsCols, &pos);
// restore current time window
- ret = setTimeWindowOutputBuf(pResultRowInfo, pBlock->info.uid, &win, masterScan, &pResult, tableGroupId,
- pInfo->binfo.pCtx, numOfOutput, pInfo->binfo.rowCellInfoOffset, &pInfo->aggSup,
- pTaskInfo);
+ ret = setTimeWindowOutputBuf(pResultRowInfo, &win, (scanFlag == MAIN_SCAN), &pResult, tableGroupId, pInfo->binfo.pCtx,
+ numOfOutput, pInfo->binfo.rowCellInfoOffset, &pInfo->aggSup, pTaskInfo);
if (ret != TSDB_CODE_SUCCESS) {
longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
}
- }
-#endif
- // window start key interpolation
- doWindowBorderInterpolation(pOperatorInfo, pBlock, pInfo->binfo.pCtx, pResult, &win, startPos, forwardStep,
- pInfo->order, false);
+ // window start key interpolation
+ doWindowBorderInterpolation(pInfo, pBlock, numOfOutput, pInfo->binfo.pCtx, pResult, &win, startPos, forwardRows);
+ }
updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &win, true);
- doApplyFunctions(pTaskInfo, pInfo->binfo.pCtx, &win, &pInfo->twAggSup.timeWindowData, startPos, forwardStep, tsCols,
- pBlock->info.rows, numOfOutput, TSDB_ORDER_ASC);
+ doApplyFunctions(pTaskInfo, pInfo->binfo.pCtx, &win, &pInfo->twAggSup.timeWindowData, startPos, forwardRows, tsCols,
+ pBlock->info.rows, numOfOutput, pInfo->order);
+
+ doCloseWindow(pResultRowInfo, pInfo, pResult);
STimeWindow nextWin = win;
while (1) {
- int32_t prevEndPos = (forwardStep - 1) * step + startPos;
+ int32_t prevEndPos = forwardRows - 1 + startPos;
startPos = getNextQualifiedWindow(&pInfo->interval, &nextWin, &pBlock->info, tsCols, prevEndPos, pInfo->order);
if (startPos < 0) {
break;
@@ -822,12 +835,13 @@ static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResul
// null data, failed to allocate more memory buffer
int32_t code =
- setTimeWindowOutputBuf(pResultRowInfo, &nextWin, masterScan, &pResult, tableGroupId, pInfo->binfo.pCtx,
+ setTimeWindowOutputBuf(pResultRowInfo, &nextWin, (scanFlag == MAIN_SCAN), &pResult, tableGroupId, pInfo->binfo.pCtx,
numOfOutput, pInfo->binfo.rowCellInfoOffset, &pInfo->aggSup, pTaskInfo);
if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
}
+
if (pInfo->execModel == OPTR_EXEC_MODEL_STREAM) {
if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE ||
pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE_SMA) {
@@ -839,24 +853,59 @@ static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResul
}
ekey = ascScan? nextWin.ekey:nextWin.skey;
- forwardStep =
+ forwardRows =
getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, pInfo->order);
// window start(end) key interpolation
- doWindowBorderInterpolation(pOperatorInfo, pBlock, pInfo->binfo.pCtx, pResult, &nextWin, startPos, forwardStep,
- pInfo->order, false);
+ doWindowBorderInterpolation(pInfo, pBlock, numOfOutput, pInfo->binfo.pCtx, pResult, &nextWin, startPos, forwardRows);
updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &nextWin, true);
- doApplyFunctions(pTaskInfo, pInfo->binfo.pCtx, &nextWin, &pInfo->twAggSup.timeWindowData, startPos, forwardStep, tsCols,
- pBlock->info.rows, numOfOutput, TSDB_ORDER_ASC);
+ doApplyFunctions(pTaskInfo, pInfo->binfo.pCtx, &nextWin, &pInfo->twAggSup.timeWindowData, startPos, forwardRows, tsCols,
+ pBlock->info.rows, numOfOutput, pInfo->order);
+ doCloseWindow(pResultRowInfo, pInfo, pResult);
}
if (pInfo->timeWindowInterpo) {
- int32_t rowIndex = ascScan ? (pBlock->info.rows - 1) : 0;
- saveDataBlockLastRow(pInfo->pRow, pBlock->pDataBlock, rowIndex, pBlock->info.numOfCols);
+ saveDataBlockLastRow(pInfo->pPrevValues, pBlock, pInfo->pInterpCols);
+ }
+}
+
+void doCloseWindow(SResultRowInfo* pResultRowInfo, const SIntervalAggOperatorInfo* pInfo, SResultRow* pResult) {
+ // current result is done in computing final results.
+ if (pInfo->timeWindowInterpo && isResultRowInterpolated(pResult, RESULT_ROW_END_INTERP)) {
+ closeResultRow(pResult);
+ tdListPopHead(pResultRowInfo->openWindow);
+ }
+}
+
+SResultRowPosition addToOpenWindowList(SResultRowInfo* pResultRowInfo, const SResultRow* pResult) {
+ SResultRowPosition pos = (SResultRowPosition){.pageId = pResult->pageId, .offset = pResult->offset};
+ SListNode* pn = tdListGetTail(pResultRowInfo->openWindow);
+ if (pn == NULL) {
+ tdListAppend(pResultRowInfo->openWindow, &pos);
+ return pos;
}
- // updateResultRowInfoActiveIndex(pResultRowInfo, &pInfo->win, pRuntimeEnv->current->lastKey, true, false);
+ SResultRowPosition* px = (SResultRowPosition*)pn->data;
+ if (px->pageId != pos.pageId || px->offset != pos.offset) {
+ tdListAppend(pResultRowInfo->openWindow, &pos);
+ }
+
+ return pos;
+}
+
+int64_t* extractTsCol(SSDataBlock* pBlock, const SIntervalAggOperatorInfo* pInfo) {
+ TSKEY* tsCols = NULL;
+ if (pBlock->pDataBlock != NULL) {
+ SColumnInfoData* pColDataInfo = taosArrayGet(pBlock->pDataBlock, pInfo->primaryTsIndex);
+ tsCols = (int64_t*)pColDataInfo->pData;
+
+ if (tsCols != NULL) {
+ blockDataUpdateTsWindow(pBlock, pInfo->primaryTsIndex);
+ }
+ }
+
+ return tsCols;
}
static int32_t doOpenIntervalAgg(SOperatorInfo* pOperator) {
@@ -885,7 +934,7 @@ static int32_t doOpenIntervalAgg(SOperatorInfo* pOperator) {
STableQueryInfo* pTableQueryInfo = pInfo->pCurrent;
setIntervalQueryRange(pTableQueryInfo, pBlock->info.window.skey, &pTaskInfo->window);
- hashIntervalAgg(pOperator, &pInfo->binfo.resultRowInfo, pBlock, pBlock->info.groupId, NULL);
+ hashIntervalAgg(pOperator, &pInfo->binfo.resultRowInfo, pBlock, scanFlag, NULL);
#if 0 // test for encode/decode result info
if(pOperator->fpSet.encodeResultRow){
@@ -1016,8 +1065,9 @@ static SSDataBlock* doStateWindowAgg(SOperatorInfo* pOperator) {
}
SStateWindowOperatorInfo* pInfo = pOperator->info;
- SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
- SOptrBasicInfo* pBInfo = &pInfo->binfo;
+
+ SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
+ SOptrBasicInfo* pBInfo = &pInfo->binfo;
if (pOperator->status == OP_RES_TO_RETURN) {
doBuildResultDatablock(pOperator, pBInfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
@@ -1126,8 +1176,7 @@ static void setInverFunction(SqlFunctionCtx* pCtx, int32_t num, EStreamType type
}
}
-void doClearWindowImpl(SResultRowPosition* p1, SDiskbasedBuf* pResultBuf,
- SOptrBasicInfo* pBinfo, int32_t numOfOutput) {
+void doClearWindowImpl(SResultRowPosition* p1, SDiskbasedBuf* pResultBuf, SOptrBasicInfo* pBinfo, int32_t numOfOutput) {
SResultRow* pResult = getResultRowByPos(pResultBuf, p1);
SqlFunctionCtx* pCtx = pBinfo->pCtx;
for (int32_t i = 0; i < numOfOutput; ++i) {
@@ -1243,7 +1292,7 @@ static SSDataBlock* doStreamIntervalAgg(SOperatorInfo* pOperator) {
break;
}
- // The timewindows that overlaps the timestamps of the input pBlock need to be recalculated and return to the
+ // The timewindow that overlaps the timestamps of the input pBlock need to be recalculated and return to the
// caller. Note that all the time window are not close till now.
// the pDataBlock are always the same one, no need to call this again
setInputDataBlock(pOperator, pInfo->binfo.pCtx, pBlock, pInfo->order, MAIN_SCAN, true);
@@ -1258,9 +1307,10 @@ static SSDataBlock* doStreamIntervalAgg(SOperatorInfo* pOperator) {
continue;
}
- hashIntervalAgg(pOperator, &pInfo->binfo.resultRowInfo, pBlock, pBlock->info.groupId, pUpdated);
pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
+ hashIntervalAgg(pOperator, &pInfo->binfo.resultRowInfo, pBlock, MAIN_SCAN, pUpdated);
}
+
closeIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup,
&pInfo->interval, pClosed);
finalizeUpdatedResult(pOperator->numOfExprs, pInfo->aggSup.pResultBuf, pClosed,
@@ -1269,9 +1319,9 @@ static SSDataBlock* doStreamIntervalAgg(SOperatorInfo* pOperator) {
pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE_SMA) {
taosArrayAddAll(pUpdated, pClosed);
}
+
taosArrayDestroy(pClosed);
- finalizeUpdatedResult(pOperator->numOfExprs, pInfo->aggSup.pResultBuf, pUpdated,
- pInfo->binfo.rowCellInfoOffset);
+ finalizeUpdatedResult(pOperator->numOfExprs, pInfo->aggSup.pResultBuf, pUpdated, pInfo->binfo.rowCellInfoOffset);
initMultiResInfoFromArrayList(&pInfo->groupResInfo, pUpdated);
blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
@@ -1309,7 +1359,7 @@ void destroyStreamFinalIntervalOperatorInfo(void* param, int32_t numOfOutput) {
}
}
-bool allInvertible(SqlFunctionCtx* pFCtx, int32_t numOfCols) {
+static bool allInvertible(SqlFunctionCtx* pFCtx, int32_t numOfCols) {
for (int32_t i = 0; i < numOfCols; i++) {
if (!fmIsInvertible(pFCtx[i].functionId)) {
return false;
@@ -1318,6 +1368,50 @@ bool allInvertible(SqlFunctionCtx* pFCtx, int32_t numOfCols) {
return true;
}
+static bool timeWindowinterpNeeded(SqlFunctionCtx* pCtx, int32_t numOfCols, SIntervalAggOperatorInfo* pInfo) {
+ // the primary timestamp column
+ bool needed = false;
+ pInfo->pInterpCols = taosArrayInit(4, sizeof(SColumn));
+ pInfo->pPrevValues = taosArrayInit(4, sizeof(SGroupKeys));
+
+ { // ts column
+ SColumn c = {0};
+ c.colId = 1;
+ c.slotId = pInfo->primaryTsIndex;
+ c.type = TSDB_DATA_TYPE_TIMESTAMP;
+ c.bytes = sizeof(int64_t);
+ taosArrayPush(pInfo->pInterpCols, &c);
+
+ SGroupKeys key = {0};
+ key.bytes = c.bytes;
+ key.type = c.type;
+ key.isNull = true; // to denote no value is assigned yet
+ key.pData = taosMemoryCalloc(1, c.bytes);
+ taosArrayPush(pInfo->pPrevValues, &key);
+ }
+
+ for(int32_t i = 0; i < numOfCols; ++i) {
+ SExprInfo* pExpr = pCtx[i].pExpr;
+
+ if (strcmp(pExpr->pExpr->_function.functionName, "twa") == 0) {
+ SFunctParam* pParam = &pExpr->base.pParam[0];
+
+ SColumn c = *pParam->pCol;
+ taosArrayPush(pInfo->pInterpCols, &c);
+ needed = true;
+
+ SGroupKeys key = {0};
+ key.bytes = c.bytes;
+ key.type = c.type;
+ key.isNull = false;
+ key.pData = taosMemoryCalloc(1, c.bytes);
+ taosArrayPush(pInfo->pPrevValues, &key);
+ }
+ }
+
+ return needed;
+}
+
SOperatorInfo* createIntervalOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExprInfo, int32_t numOfCols,
SSDataBlock* pResBlock, SInterval* pInterval, int32_t primaryTsSlotId,
STimeWindowAggSupp* pTwAggSupp, SExecTaskInfo* pTaskInfo) {
@@ -1327,11 +1421,12 @@ SOperatorInfo* createIntervalOperatorInfo(SOperatorInfo* downstream, SExprInfo*
goto _error;
}
- pInfo->order = TSDB_ORDER_ASC;
- pInfo->interval = *pInterval;
+ pInfo->win = pTaskInfo->window;
+ pInfo->order = TSDB_ORDER_ASC;
+ pInfo->interval = *pInterval;
pInfo->execModel = pTaskInfo->execModel;
- pInfo->win = pTaskInfo->window;
- pInfo->twAggSup = *pTwAggSupp;
+ pInfo->twAggSup = *pTwAggSupp;
+
pInfo->primaryTsIndex = primaryTsSlotId;
size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
@@ -1341,23 +1436,30 @@ SOperatorInfo* createIntervalOperatorInfo(SOperatorInfo* downstream, SExprInfo*
initAggInfo(&pInfo->binfo, &pInfo->aggSup, pExprInfo, numOfCols, pResBlock, keyBufSize, pTaskInfo->id.str);
initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pInfo->win);
+
pInfo->invertible = allInvertible(pInfo->binfo.pCtx, numOfCols);
pInfo->invertible = false; // Todo(liuyao): Dependent TSDB API
- if (code != TSDB_CODE_SUCCESS) {
+ pInfo->timeWindowInterpo = timeWindowinterpNeeded(pInfo->binfo.pCtx, numOfCols, pInfo);
+ if (pInfo->timeWindowInterpo) {
+ pInfo->binfo.resultRowInfo.openWindow = tdListNew(sizeof(SResultRowPosition));
+ }
+
+ // pInfo->pTableQueryInfo = initTableQueryInfo(pTableGroupInfo);
+ if (code != TSDB_CODE_SUCCESS /* || pInfo->pTableQueryInfo == NULL*/) {
goto _error;
}
initResultRowInfo(&pInfo->binfo.resultRowInfo, (int32_t)1);
- pOperator->name = "TimeIntervalAggOperator";
+ pOperator->name = "TimeIntervalAggOperator";
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_INTERVAL;
- pOperator->blocking = true;
- pOperator->status = OP_NOT_OPENED;
- pOperator->pExpr = pExprInfo;
- pOperator->pTaskInfo = pTaskInfo;
- pOperator->numOfExprs = numOfCols;
- pOperator->info = pInfo;
+ pOperator->blocking = true;
+ pOperator->status = OP_NOT_OPENED;
+ pOperator->pExpr = pExprInfo;
+ pOperator->pTaskInfo = pTaskInfo;
+ pOperator->numOfExprs = numOfCols;
+ pOperator->info = pInfo;
pOperator->fpSet = createOperatorFpSet(doOpenIntervalAgg, doBuildIntervalResult, doStreamIntervalAgg, NULL,
destroyIntervalOperatorInfo, aggEncodeResultRow, aggDecodeResultRow, NULL);
@@ -1816,7 +1918,7 @@ static SArray* doHashInterval(SOperatorInfo* pOperatorInfo, SSDataBlock* pSDataB
bool ascScan = true;
TSKEY* tsCols = NULL;
SResultRow* pResult = NULL;
- int32_t forwardStep = 0;
+ int32_t forwardRows = 0;
if (pSDataBlock->pDataBlock != NULL) {
SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
@@ -1826,7 +1928,7 @@ static SArray* doHashInterval(SOperatorInfo* pOperatorInfo, SSDataBlock* pSDataB
}
int32_t startPos = ascScan ? 0 : (pSDataBlock->info.rows - 1);
- TSKEY ts = getStartTsKey(&pSDataBlock->info.window, tsCols, pSDataBlock->info.rows, ascScan);
+ TSKEY ts = getStartTsKey(&pSDataBlock->info.window, tsCols);
STimeWindow nextWin = getActiveTimeWindow(pInfo->aggSup.pResultBuf, pResultRowInfo, ts,
&pInfo->interval, pInfo->interval.precision, NULL);
while (1) {
@@ -1841,15 +1943,15 @@ static SArray* doHashInterval(SOperatorInfo* pOperatorInfo, SSDataBlock* pSDataB
pos->pos = (SResultRowPosition){.pageId = pResult->pageId, .offset = pResult->offset};
*(int64_t*)pos->key = pResult->win.skey;
taosArrayPush(pUpdated, &pos);
- forwardStep =
+ forwardRows =
getNumOfRowsInTimeWindow(&pSDataBlock->info, tsCols, startPos, nextWin.ekey, binarySearchForKey, NULL, TSDB_ORDER_ASC);
// window start(end) key interpolation
- doWindowBorderInterpolation(pOperatorInfo, pSDataBlock, pInfo->binfo.pCtx, pResult, &nextWin, startPos, forwardStep,
- pInfo->order, false);
+ // disable it temporarily
+// doWindowBorderInterpolation(pInfo, pSDataBlock, numOfOutput, pInfo->binfo.pCtx, pResult, &nextWin, startPos, forwardRows);
updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &nextWin, true);
- doApplyFunctions(pTaskInfo, pInfo->binfo.pCtx, &nextWin, &pInfo->twAggSup.timeWindowData, startPos, forwardStep, tsCols,
+ doApplyFunctions(pTaskInfo, pInfo->binfo.pCtx, &nextWin, &pInfo->twAggSup.timeWindowData, startPos, forwardRows, tsCols,
pSDataBlock->info.rows, numOfOutput, TSDB_ORDER_ASC);
- int32_t prevEndPos = (forwardStep - 1) * step + startPos;
+ int32_t prevEndPos = (forwardRows - 1) * step + startPos;
startPos = getNextQualifiedWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, prevEndPos, pInfo->order);
if (startPos < 0) {
break;
@@ -2165,7 +2267,7 @@ static int32_t setWindowOutputBuf(SResultWindowInfo* pWinInfo, SResultRow** pRes
}
if (pWinInfo->pos.pageId == -1) {
- *pResult = getNewResultRow_rv(pAggSup->pResultBuf, groupId, pAggSup->resultRowSize);
+ *pResult = getNewResultRow(pAggSup->pResultBuf, groupId, pAggSup->resultRowSize);
if (*pResult == NULL) {
return TSDB_CODE_OUT_OF_MEMORY;
}
@@ -2300,7 +2402,7 @@ static void doStreamSessionWindowAggImpl(SOperatorInfo* pOperator,
longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
}
// window start(end) key interpolation
- // doWindowBorderInterpolation(pOperatorInfo, pSDataBlock, pInfo->binfo.pCtx, pResult, &nextWin, startPos, forwardStep,
+ // doWindowBorderInterpolation(pOperatorInfo, pSDataBlock, pInfo->binfo.pCtx, pResult, &nextWin, startPos, forwardRows,
// pInfo->order, false);
int32_t winNum = getNumCompactWindow(pAggSup->pResultRows, winIndex, gap);
if (winNum > 0) {
@@ -2497,7 +2599,7 @@ static SSDataBlock* doStreamSessionWindowAgg(SOperatorInfo* pOperator) {
}
// restore the value
pOperator->status = OP_RES_TO_RETURN;
-
+
SArray* pClosed = taosArrayInit(16, POINTER_BYTES);
closeSessionWindow(pInfo->streamAggSup.pResultRows, &pInfo->twAggSup, pClosed,
pInfo->twAggSup.calTrigger);
diff --git a/source/libs/function/inc/builtins.h b/source/libs/function/inc/builtins.h
index 3bd0f35bf5..bc91875006 100644
--- a/source/libs/function/inc/builtins.h
+++ b/source/libs/function/inc/builtins.h
@@ -26,22 +26,24 @@ typedef int32_t (*FTranslateFunc)(SFunctionNode* pFunc, char* pErrBuf, int32_t l
typedef EFuncDataRequired (*FFuncDataRequired)(SFunctionNode* pFunc, STimeWindow* pTimeWindow);
typedef struct SBuiltinFuncDefinition {
- char name[FUNCTION_NAME_MAX_LENGTH];
- EFunctionType type;
- uint64_t classification;
- FTranslateFunc translateFunc;
- FFuncDataRequired dataRequiredFunc;
- FExecGetEnv getEnvFunc;
- FExecInit initFunc;
- FExecProcess processFunc;
+ const char* name;
+ EFunctionType type;
+ uint64_t classification;
+ FTranslateFunc translateFunc;
+ FFuncDataRequired dataRequiredFunc;
+ FExecGetEnv getEnvFunc;
+ FExecInit initFunc;
+ FExecProcess processFunc;
FScalarExecProcess sprocessFunc;
- FExecFinalize finalizeFunc;
- FExecProcess invertFunc;
- FExecCombine combineFunc;
+ FExecFinalize finalizeFunc;
+ FExecProcess invertFunc;
+ FExecCombine combineFunc;
+ const char* pPartialFunc;
+ const char* pMergeFunc;
} SBuiltinFuncDefinition;
extern const SBuiltinFuncDefinition funcMgtBuiltins[];
-extern const int funcMgtBuiltinsNum;
+extern const int funcMgtBuiltinsNum;
#ifdef __cplusplus
}
diff --git a/source/libs/function/inc/builtinsimpl.h b/source/libs/function/inc/builtinsimpl.h
index cac86be917..68b83f4a19 100644
--- a/source/libs/function/inc/builtinsimpl.h
+++ b/source/libs/function/inc/builtinsimpl.h
@@ -140,6 +140,10 @@ bool uniqueFunctionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo)
int32_t uniqueFunction(SqlFunctionCtx *pCtx);
//int32_t uniqueFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock);
+bool getTwaFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv);
+bool twaFunctionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo);
+int32_t twaFunction(SqlFunctionCtx *pCtx);
+int32_t twaFinalize(struct SqlFunctionCtx *pCtx, SSDataBlock* pBlock);
bool getSelectivityFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv);
diff --git a/source/libs/function/inc/taggfunction.h b/source/libs/function/inc/taggfunction.h
index d779cf50f4..c3d61d426d 100644
--- a/source/libs/function/inc/taggfunction.h
+++ b/source/libs/function/inc/taggfunction.h
@@ -52,13 +52,6 @@ typedef struct SInterpInfoDetail {
int8_t primaryCol;
} SInterpInfoDetail;
-typedef struct STwaInfo {
- int8_t hasResult; // flag to denote has value
- double dOutput;
- SPoint1 p;
- STimeWindow win;
-} STwaInfo;
-
bool topbot_datablock_filter(SqlFunctionCtx *pCtx, const char *minval, const char *maxval);
/**
diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c
index 6165a16711..d68d774a6b 100644
--- a/source/libs/function/src/builtins.c
+++ b/source/libs/function/src/builtins.c
@@ -18,7 +18,6 @@
#include "querynodes.h"
#include "scalar.h"
#include "taoserror.h"
-#include "tdatablock.h"
static int32_t buildFuncErrMsg(char* pErrBuf, int32_t len, int32_t errCode, const char* pFormat, ...) {
va_list vArgList;
@@ -103,6 +102,28 @@ static int32_t translateInOutStr(SFunctionNode* pFunc, char* pErrBuf, int32_t le
return TSDB_CODE_SUCCESS;
}
+static int32_t translateLogarithm(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
+ int32_t numOfParams = LIST_LENGTH(pFunc->pParameterList);
+ if (1 != numOfParams && 2 != numOfParams) {
+ return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
+ }
+
+ uint8_t para1Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
+ if (!IS_NUMERIC_TYPE(para1Type)) {
+ return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
+ }
+
+ if (2 == numOfParams) {
+ uint8_t para2Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 1))->resType.type;
+ if (!IS_NUMERIC_TYPE(para2Type)) {
+ return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
+ }
+ }
+
+ pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes, .type = TSDB_DATA_TYPE_DOUBLE};
+ return TSDB_CODE_SUCCESS;
+}
+
static int32_t translateCount(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
if (1 != LIST_LENGTH(pFunc->pParameterList)) {
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
@@ -156,14 +177,14 @@ static int32_t translatePercentile(SFunctionNode* pFunc, char* pErrBuf, int32_t
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
}
- //param0
+ // param0
SNode* pParamNode0 = nodesListGetNode(pFunc->pParameterList, 0);
if (nodeType(pParamNode0) != QUERY_NODE_COLUMN) {
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
"The first parameter of PERCENTILE function can only be column");
}
- //param1
+ // param1
SValueNode* pValue = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
if (pValue->datum.i < 0 || pValue->datum.i > 100) {
@@ -178,7 +199,7 @@ static int32_t translatePercentile(SFunctionNode* pFunc, char* pErrBuf, int32_t
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
}
- //set result type
+ // set result type
pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes, .type = TSDB_DATA_TYPE_DOUBLE};
return TSDB_CODE_SUCCESS;
}
@@ -197,14 +218,14 @@ static int32_t translateApercentile(SFunctionNode* pFunc, char* pErrBuf, int32_t
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
}
- //param0
+ // param0
SNode* pParamNode0 = nodesListGetNode(pFunc->pParameterList, 0);
if (nodeType(pParamNode0) != QUERY_NODE_COLUMN) {
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
"The first parameter of APERCENTILE function can only be column");
}
- //param1
+ // param1
SNode* pParamNode1 = nodesListGetNode(pFunc->pParameterList, 1);
if (nodeType(pParamNode1) != QUERY_NODE_VALUE) {
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
@@ -223,7 +244,7 @@ static int32_t translateApercentile(SFunctionNode* pFunc, char* pErrBuf, int32_t
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
}
- //param2
+ // param2
if (3 == numOfParams) {
uint8_t para3Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 2))->resType.type;
if (!IS_VAR_DATA_TYPE(para3Type)) {
@@ -263,14 +284,14 @@ static int32_t translateTop(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
}
- //param0
+ // param0
SNode* pParamNode0 = nodesListGetNode(pFunc->pParameterList, 0);
if (nodeType(pParamNode0) != QUERY_NODE_COLUMN) {
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
"The first parameter of TOP/BOTTOM function can only be column");
}
- //param1
+ // param1
SNode* pParamNode1 = nodesListGetNode(pFunc->pParameterList, 1);
if (nodeType(pParamNode1) != QUERY_NODE_VALUE) {
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
@@ -287,7 +308,7 @@ static int32_t translateTop(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
pValue->notReserved = true;
- //set result type
+ // set result type
SDataType* pType = &((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType;
pFunc->node.resType = (SDataType){.bytes = pType->bytes, .type = pType->type};
return TSDB_CODE_SUCCESS;
@@ -340,7 +361,7 @@ static int32_t translateElapsed(SFunctionNode* pFunc, char* pErrBuf, int32_t len
pValue->notReserved = true;
- uint8_t paraType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 1))->resType.type;
+ paraType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 1))->resType.type;
if (!IS_INTEGER_TYPE(paraType)) {
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
}
@@ -434,7 +455,7 @@ static int32_t translateHLL(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
"The input parameter of HYPERLOGLOG function can only be column");
}
- pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_UBIGINT].bytes, .type = TSDB_DATA_TYPE_UBIGINT};
+ pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes, .type = TSDB_DATA_TYPE_BIGINT};
return TSDB_CODE_SUCCESS;
}
@@ -687,8 +708,8 @@ static int32_t translateTail(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
if (pValue->datum.i < ((i > 1) ? 0 : 1) || pValue->datum.i > 100) {
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
- "TAIL function second parameter should be in range [1, 100], "
- "third parameter should be in range [0, 100]");
+ "TAIL function second parameter should be in range [1, 100], "
+ "third parameter should be in range [0, 100]");
}
pValue->notReserved = true;
@@ -749,7 +770,7 @@ static int32_t translateDiff(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
}
- //param0
+ // param0
SNode* pParamNode0 = nodesListGetNode(pFunc->pParameterList, 0);
if (nodeType(pParamNode0) != QUERY_NODE_COLUMN) {
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
@@ -757,12 +778,11 @@ static int32_t translateDiff(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
}
uint8_t colType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
- if (!IS_SIGNED_NUMERIC_TYPE(colType) && !IS_FLOAT_TYPE(colType) &&
- TSDB_DATA_TYPE_BOOL != colType) {
+ if (!IS_SIGNED_NUMERIC_TYPE(colType) && !IS_FLOAT_TYPE(colType) && TSDB_DATA_TYPE_BOOL != colType) {
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
}
- //param1
+ // param1
if (numOfParams == 2) {
uint8_t paraType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 1))->resType.type;
if (!IS_INTEGER_TYPE(paraType)) {
@@ -817,11 +837,20 @@ static int32_t translateConcatImpl(SFunctionNode* pFunc, char* pErrBuf, int32_t
int32_t resultBytes = 0;
int32_t sepBytes = 0;
+ //concat_ws separator should be constant string
+ if (hasSep) {
+ SNode* pPara = nodesListGetNode(pFunc->pParameterList, 0);
+ if (nodeType(pPara) != QUERY_NODE_VALUE) {
+ return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
+ "The first parameter of CONCAT_WS function can only be constant string");
+ }
+ }
+
/* For concat/concat_ws function, if params have NCHAR type, promote the final result to NCHAR */
for (int32_t i = 0; i < numOfParams; ++i) {
SNode* pPara = nodesListGetNode(pFunc->pParameterList, i);
uint8_t paraType = ((SExprNode*)pPara)->resType.type;
- if (!IS_VAR_DATA_TYPE(paraType)) {
+ if (!IS_VAR_DATA_TYPE(paraType) && TSDB_DATA_TYPE_NULL != paraType) {
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
}
if (TSDB_DATA_TYPE_NCHAR == paraType) {
@@ -880,7 +909,7 @@ static int32_t translateSubstr(SFunctionNode* pFunc, char* pErrBuf, int32_t len)
if (3 == numOfParams) {
SExprNode* p2 = (SExprNode*)nodesListGetNode(pFunc->pParameterList, 2);
- uint8_t para2Type = p2->resType.type;
+ uint8_t para2Type = p2->resType.type;
if (!IS_INTEGER_TYPE(para2Type)) {
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
}
@@ -1113,6 +1142,8 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
.finalizeFunc = functionFinalize,
.invertFunc = countInvertFunction,
.combineFunc = combineFunction,
+ // .pPartialFunc = "count",
+ // .pMergeFunc = "sum"
},
{
.name = "sum",
@@ -1280,6 +1311,16 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
.finalizeFunc = firstLastFinalize,
.combineFunc = lastCombine,
},
+ {
+ .name = "twa",
+ .type = FUNCTION_TYPE_TWA,
+ .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_TIMELINE_FUNC,
+ .translateFunc = translateInNumOutDou,
+ .getEnvFunc = getTwaFuncEnv,
+ .initFunc = twaFunctionSetup,
+ .processFunc = twaFunction,
+ .finalizeFunc = twaFinalize
+ },
{
.name = "histogram",
.type = FUNCTION_TYPE_HISTOGRAM,
@@ -1394,7 +1435,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
.name = "log",
.type = FUNCTION_TYPE_LOG,
.classification = FUNC_MGT_SCALAR_FUNC,
- .translateFunc = translateIn2NumOutDou,
+ .translateFunc = translateLogarithm,
.getEnvFunc = NULL,
.initFunc = NULL,
.sprocessFunc = logFunction,
diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c
index a7e93246b7..be18150234 100644
--- a/source/libs/function/src/builtinsimpl.c
+++ b/source/libs/function/src/builtinsimpl.c
@@ -14,6 +14,7 @@
*/
#include "builtinsimpl.h"
+#include "tglobal.h"
#include "cJSON.h"
#include "function.h"
#include "querynodes.h"
@@ -300,7 +301,7 @@ int32_t functionFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
- //pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
+ pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
char* in = GET_ROWCELL_INTERBUF(pResInfo);
colDataAppend(pCol, pBlock->info.rows, in, pResInfo->isNullRes);
@@ -357,7 +358,7 @@ bool getCountFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
return true;
}
-static FORCE_INLINE int32_t getNumofElem(SqlFunctionCtx* pCtx) {
+static FORCE_INLINE int32_t getNumOfElems(SqlFunctionCtx* pCtx) {
int32_t numOfElem = 0;
/*
@@ -392,11 +393,12 @@ static FORCE_INLINE int32_t getNumofElem(SqlFunctionCtx* pCtx) {
* count function does not use the pCtx->interResBuf to keep the intermediate buffer
*/
int32_t countFunction(SqlFunctionCtx* pCtx) {
- int32_t numOfElem = getNumofElem(pCtx);
- SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
+ int32_t numOfElem = getNumOfElems(pCtx);
+ SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
SInputColumnInfoData* pInput = &pCtx->input;
- int32_t type = pInput->pData[0]->info.type;
+
+ int32_t type = pInput->pData[0]->info.type;
char* buf = GET_ROWCELL_INTERBUF(pResInfo);
if (IS_NULL_TYPE(type)) {
@@ -407,12 +409,17 @@ int32_t countFunction(SqlFunctionCtx* pCtx) {
*((int64_t*)buf) += numOfElem;
}
- SET_VAL(pResInfo, numOfElem, 1);
+ if (tsCountAlwaysReturnValue) {
+ pResInfo->numOfRes = 1;
+ } else {
+ SET_VAL(pResInfo, 1, 1);
+ }
+
return TSDB_CODE_SUCCESS;
}
int32_t countInvertFunction(SqlFunctionCtx* pCtx) {
- int32_t numOfElem = getNumofElem(pCtx);
+ int32_t numOfElem = getNumOfElems(pCtx);
SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
char* buf = GET_ROWCELL_INTERBUF(pResInfo);
@@ -829,8 +836,10 @@ int32_t avgCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
int32_t avgFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
SInputColumnInfoData* pInput = &pCtx->input;
- int32_t type = pInput->pData[0]->info.type;
- SAvgRes* pAvgRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
+
+ int32_t type = pInput->pData[0]->info.type;
+ SAvgRes* pAvgRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
+
if (IS_INTEGER_TYPE(type)) {
pAvgRes->result = pAvgRes->sum.isum / ((double)pAvgRes->count);
} else {
@@ -1832,7 +1841,7 @@ bool percentileFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultI
}
int32_t percentileFunction(SqlFunctionCtx* pCtx) {
- int32_t notNullElems = 0;
+ int32_t numOfElems = 0;
SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
SInputColumnInfoData* pInput = &pCtx->input;
@@ -1910,11 +1919,11 @@ int32_t percentileFunction(SqlFunctionCtx* pCtx) {
}
char* data = colDataGetData(pCol, i);
- notNullElems += 1;
+ numOfElems += 1;
tMemBucketPut(pInfo->pMemBucket, data, 1);
}
- SET_VAL(pResInfo, notNullElems, 1);
+ SET_VAL(pResInfo, numOfElems, 1);
}
return TSDB_CODE_SUCCESS;
@@ -1988,7 +1997,7 @@ bool apercentileFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResult
}
int32_t apercentileFunction(SqlFunctionCtx* pCtx) {
- int32_t notNullElems = 0;
+ int32_t numOfElems = 0;
SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
SInputColumnInfoData* pInput = &pCtx->input;
@@ -2005,7 +2014,7 @@ int32_t apercentileFunction(SqlFunctionCtx* pCtx) {
if (colDataIsNull_f(pCol->nullbitmap, i)) {
continue;
}
- notNullElems += 1;
+ numOfElems += 1;
char* data = colDataGetData(pCol, i);
double v = 0; // value
@@ -2018,7 +2027,7 @@ int32_t apercentileFunction(SqlFunctionCtx* pCtx) {
if (colDataIsNull_f(pCol->nullbitmap, i)) {
continue;
}
- notNullElems += 1;
+ numOfElems += 1;
char* data = colDataGetData(pCol, i);
double v = 0;
@@ -2027,7 +2036,7 @@ int32_t apercentileFunction(SqlFunctionCtx* pCtx) {
}
}
- SET_VAL(pResInfo, notNullElems, 1);
+ SET_VAL(pResInfo, numOfElems, 1);
return TSDB_CODE_SUCCESS;
}
@@ -3240,13 +3249,13 @@ static uint64_t hllCountCnt(uint8_t *buckets) {
z += buckethisto[j];
z *= 0.5;
}
+
z += m * hllSigma(buckethisto[0]/(double)m);
double E = (double)llroundl(HLL_ALPHA_INF*m*m/z);
return (uint64_t) E;
}
-
int32_t hllFunction(SqlFunctionCtx *pCtx) {
SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
@@ -3279,7 +3288,6 @@ int32_t hllFunction(SqlFunctionCtx *pCtx) {
if (count > oldcount) {
pInfo->buckets[index] = count;
}
-
}
SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
@@ -3287,9 +3295,13 @@ int32_t hllFunction(SqlFunctionCtx *pCtx) {
}
int32_t hllFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
- SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
+ SResultRowEntryInfo *pInfo = GET_RES_INFO(pCtx);
- pInfo->result = hllCountCnt(pInfo->buckets);
+ SHLLInfo* pHllInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
+ pHllInfo->result = hllCountCnt(pHllInfo->buckets);
+ if (tsCountAlwaysReturnValue && pHllInfo->result == 0) {
+ pInfo->numOfRes = 1;
+ }
return functionFinalize(pCtx, pBlock);
}
@@ -3695,7 +3707,6 @@ int32_t sampleFunction(SqlFunctionCtx* pCtx) {
TSKEY* tsList = (int64_t*)pInput->pPTS->pData;
SColumnInfoData* pInputCol = pInput->pData[0];
- SColumnInfoData* pTsOutput = pCtx->pTsOutput;
SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
int32_t startOffset = pCtx->offset;
@@ -3718,24 +3729,6 @@ int32_t sampleFunction(SqlFunctionCtx* pCtx) {
return pInfo->numSampled;
}
-//int32_t sampleFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
-// SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
-// SSampleInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
-// int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
-// SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
-//
-// //int32_t currentRow = pBlock->info.rows;
-// pResInfo->numOfRes = pInfo->numSampled;
-//
-// for (int32_t i = 0; i < pInfo->numSampled; ++i) {
-// colDataAppend(pCol, i, pInfo->data + i * pInfo->colBytes, false);
-// //TODO: handle ts output
-// }
-//
-// return pResInfo->numOfRes;
-//}
-
-
bool getTailFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
SValueNode* pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
@@ -3812,7 +3805,6 @@ int32_t tailFunction(SqlFunctionCtx* pCtx) {
TSKEY* tsList = (int64_t*)pInput->pPTS->pData;
SColumnInfoData* pInputCol = pInput->pData[0];
- SColumnInfoData* pTsOutput = pCtx->pTsOutput;
SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
int32_t startOffset = pCtx->offset;
@@ -3879,7 +3871,6 @@ bool uniqueFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
pInfo->numOfPoints = 0;
pInfo->colType = pCtx->resDataInfo.type;
pInfo->colBytes = pCtx->resDataInfo.bytes;
- pInfo->hasNull = false;
if (pInfo->pHash != NULL) {
taosHashClear(pInfo->pHash);
} else {
@@ -3917,8 +3908,6 @@ static void doUniqueAdd(SUniqueInfo* pInfo, char *data, TSKEY ts, bool isNull) {
} else if (pHashItem->timestamp > ts) {
pHashItem->timestamp = ts;
}
-
- return;
}
int32_t uniqueFunction(SqlFunctionCtx* pCtx) {
@@ -3960,7 +3949,7 @@ int32_t uniqueFunction(SqlFunctionCtx* pCtx) {
int32_t uniqueFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
- SUniqueInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
+ SUniqueInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
@@ -3973,3 +3962,260 @@ int32_t uniqueFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
return pResInfo->numOfRes;
}
+typedef struct STwaInfo {
+ double dOutput;
+ SPoint1 p;
+ STimeWindow win;
+} STwaInfo;
+
+bool getTwaFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
+ pEnv->calcMemSize = sizeof(STwaInfo);
+ return true;
+}
+
+bool twaFunctionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo) {
+ if (!functionSetup(pCtx, pResultInfo)) {
+ return false;
+ }
+
+ STwaInfo *pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
+ pInfo->p.key = INT64_MIN;
+ pInfo->win = TSWINDOW_INITIALIZER;
+ return true;
+}
+
+static double twa_get_area(SPoint1 s, SPoint1 e) {
+ if ((s.val >= 0 && e.val >= 0)|| (s.val <=0 && e.val <= 0)) {
+ return (s.val + e.val) * (e.key - s.key) / 2;
+ }
+
+ double x = (s.key * e.val - e.key * s.val)/(e.val - s.val);
+ double val = (s.val * (x - s.key) + e.val * (e.key - x)) / 2;
+ return val;
+}
+
+#define INIT_INTP_POINT(_p, _k, _v) \
+ do { \
+ (_p).key = (_k); \
+ (_p).val = (_v); \
+ } while (0)
+
+int32_t twaFunction(SqlFunctionCtx* pCtx) {
+ SInputColumnInfoData* pInput = &pCtx->input;
+ SColumnInfoData* pInputCol = pInput->pData[0];
+
+ TSKEY* tsList = (int64_t*)pInput->pPTS->pData;
+
+ SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx);
+
+ STwaInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo);
+ SPoint1 *last = &pInfo->p;
+ int32_t numOfElems = 0;
+
+ int32_t i = pInput->startRowIndex;
+ if (pCtx->start.key != INT64_MIN) {
+ ASSERT((pCtx->start.key < tsList[i] && pCtx->order == TSDB_ORDER_ASC) ||
+ (pCtx->start.key > tsList[i] && pCtx->order == TSDB_ORDER_DESC));
+
+ ASSERT(last->key == INT64_MIN);
+ last->key = tsList[i];
+
+ GET_TYPED_DATA(last->val, double, pInputCol->info.type, colDataGetData(pInputCol, i));
+
+ pInfo->dOutput += twa_get_area(pCtx->start, *last);
+ pInfo->win.skey = pCtx->start.key;
+ numOfElems++;
+ i += 1;
+ } else if (pInfo->p.key == INT64_MIN) {
+ last->key = tsList[i];
+ GET_TYPED_DATA(last->val, double, pInputCol->info.type, colDataGetData(pInputCol, i));
+
+ pInfo->win.skey = last->key;
+ numOfElems++;
+ i += 1;
+ }
+
+ SPoint1 st = {0};
+
+ // calculate the value of
+ switch(pInputCol->info.type) {
+ case TSDB_DATA_TYPE_TINYINT: {
+ int8_t *val = (int8_t*) colDataGetData(pInputCol, 0);
+ for (; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
+ if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
+ continue;
+ }
+
+ INIT_INTP_POINT(st, tsList[i], val[i]);
+ pInfo->dOutput += twa_get_area(pInfo->p, st);
+ pInfo->p = st;
+ }
+ break;
+ }
+
+ case TSDB_DATA_TYPE_SMALLINT: {
+ int16_t *val = (int16_t*) colDataGetData(pInputCol, 0);
+ for (; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
+ if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
+ continue;
+ }
+
+ INIT_INTP_POINT(st, tsList[i], val[i]);
+ pInfo->dOutput += twa_get_area(pInfo->p, st);
+ pInfo->p = st;
+ }
+ break;
+ }
+ case TSDB_DATA_TYPE_INT: {
+ int32_t *val = (int32_t*) colDataGetData(pInputCol, 0);
+ for (; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
+ if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
+ continue;
+ }
+
+ INIT_INTP_POINT(st, tsList[i], val[i]);
+ pInfo->dOutput += twa_get_area(pInfo->p, st);
+ pInfo->p = st;
+ }
+ break;
+ }
+ case TSDB_DATA_TYPE_BIGINT: {
+ int64_t *val = (int64_t*) colDataGetData(pInputCol, 0);
+ for (; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
+ if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
+ continue;
+ }
+
+ INIT_INTP_POINT(st, tsList[i], val[i]);
+ pInfo->dOutput += twa_get_area(pInfo->p, st);
+ pInfo->p = st;
+ }
+ break;
+ }
+ case TSDB_DATA_TYPE_FLOAT: {
+ float *val = (float*) colDataGetData(pInputCol, 0);
+ for (; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
+ if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
+ continue;
+ }
+
+ INIT_INTP_POINT(st, tsList[i], val[i]);
+ pInfo->dOutput += twa_get_area(pInfo->p, st);
+ pInfo->p = st;
+ }
+ break;
+ }
+ case TSDB_DATA_TYPE_DOUBLE: {
+ double *val = (double*) colDataGetData(pInputCol, 0);
+ for (; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
+ if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
+ continue;
+ }
+
+ INIT_INTP_POINT(st, tsList[i], val[i]);
+ pInfo->dOutput += twa_get_area(pInfo->p, st);
+ pInfo->p = st;
+ }
+ break;
+ }
+ case TSDB_DATA_TYPE_UTINYINT: {
+ uint8_t *val = (uint8_t*) colDataGetData(pInputCol, 0);
+ for (; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
+ if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
+ continue;
+ }
+
+ INIT_INTP_POINT(st, tsList[i], val[i]);
+ pInfo->dOutput += twa_get_area(pInfo->p, st);
+ pInfo->p = st;
+ }
+ break;
+ }
+ case TSDB_DATA_TYPE_USMALLINT: {
+ uint16_t *val = (uint16_t*) colDataGetData(pInputCol, 0);
+ for (; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
+ if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
+ continue;
+ }
+
+ INIT_INTP_POINT(st, tsList[i], val[i]);
+ pInfo->dOutput += twa_get_area(pInfo->p, st);
+ pInfo->p = st;
+ }
+ break;
+ }
+ case TSDB_DATA_TYPE_UINT: {
+ uint32_t *val = (uint32_t*) colDataGetData(pInputCol, 0);
+ for (; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
+ if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
+ continue;
+ }
+
+ INIT_INTP_POINT(st, tsList[i], val[i]);
+ pInfo->dOutput += twa_get_area(pInfo->p, st);
+ pInfo->p = st;
+ }
+ break;
+ }
+ case TSDB_DATA_TYPE_UBIGINT: {
+ uint64_t *val = (uint64_t*) colDataGetData(pInputCol, 0);
+ for (; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
+ if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
+ continue;
+ }
+
+ INIT_INTP_POINT(st, tsList[i], val[i]);
+ pInfo->dOutput += twa_get_area(pInfo->p, st);
+ pInfo->p = st;
+ }
+ break;
+ }
+
+ default: ASSERT(0);
+ }
+
+ // the last interpolated time window value
+ if (pCtx->end.key != INT64_MIN) {
+ pInfo->dOutput += twa_get_area(pInfo->p, pCtx->end);
+ pInfo->p = pCtx->end;
+ }
+
+ pInfo->win.ekey = pInfo->p.key;
+
+ SET_VAL(pResInfo, numOfElems, 1);
+ return TSDB_CODE_SUCCESS;
+}
+
+/*
+ * To copy the input to interResBuf to avoid the input buffer space be over writen
+ * by next input data. The TWA function only applies to each table, so no merge procedure
+ * is required, we simply copy to the resut ot interResBuffer.
+ */
+//void twa_function_copy(SQLFunctionCtx *pCtx) {
+// assert(pCtx->inputType == TSDB_DATA_TYPE_BINARY);
+// SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx);
+//
+// memcpy(GET_ROWCELL_INTERBUF(pResInfo), pCtx->pInput, (size_t)pCtx->inputBytes);
+// pResInfo->hasResult = ((STwaInfo *)pCtx->pInput)->hasResult;
+//}
+
+int32_t twaFinalize(struct SqlFunctionCtx *pCtx, SSDataBlock* pBlock) {
+ SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx);
+
+ STwaInfo *pInfo = (STwaInfo *)GET_ROWCELL_INTERBUF(pResInfo);
+ if (pResInfo->numOfRes == 0) {
+ pResInfo->isNullRes = 1;
+ } else {
+ // assert(pInfo->win.ekey == pInfo->p.key && pInfo->hasResult == pResInfo->hasResult);
+ if (pInfo->win.ekey == pInfo->win.skey) {
+ pInfo->dOutput = pInfo->p.val;
+ } else {
+ pInfo->dOutput = pInfo->dOutput / (pInfo->win.ekey - pInfo->win.skey);
+ }
+
+ pResInfo->numOfRes = 1;
+ }
+
+ return functionFinalize(pCtx, pBlock);
+}
+
diff --git a/source/libs/function/src/functionMgt.c b/source/libs/function/src/functionMgt.c
index c2b325bc92..611ae8d81f 100644
--- a/source/libs/function/src/functionMgt.c
+++ b/source/libs/function/src/functionMgt.c
@@ -199,3 +199,81 @@ bool fmIsInvertible(int32_t funcId) {
}
return res;
}
+
+static SFunctionNode* createFunction(const char* pName, SNodeList* pParameterList) {
+ SFunctionNode* pFunc = nodesMakeNode(QUERY_NODE_FUNCTION);
+ if (NULL == pFunc) {
+ return NULL;
+ }
+ strcpy(pFunc->functionName, pName);
+ pFunc->pParameterList = pParameterList;
+ char msg[64] = {0};
+ if (TSDB_CODE_SUCCESS != fmGetFuncInfo(pFunc, msg, sizeof(msg))) {
+ nodesDestroyNode(pFunc);
+ return NULL;
+ }
+ return pFunc;
+}
+
+static SColumnNode* createColumnByFunc(const SFunctionNode* pFunc) {
+ SColumnNode* pCol = nodesMakeNode(QUERY_NODE_COLUMN);
+ if (NULL == pCol) {
+ return NULL;
+ }
+ strcpy(pCol->colName, pFunc->node.aliasName);
+ pCol->node.resType = pFunc->node.resType;
+ return pCol;
+}
+
+bool fmIsDistExecFunc(int32_t funcId) {
+ if (!fmIsVectorFunc(funcId)) {
+ return true;
+ }
+ return (NULL != funcMgtBuiltins[funcId].pPartialFunc && NULL != funcMgtBuiltins[funcId].pMergeFunc);
+}
+
+static int32_t createPartialFunction(const SFunctionNode* pSrcFunc, SFunctionNode** pPartialFunc) {
+ SNodeList* pParameterList = nodesCloneList(pSrcFunc->pParameterList);
+ if (NULL == pParameterList) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ *pPartialFunc = createFunction(funcMgtBuiltins[pSrcFunc->funcId].pPartialFunc, pParameterList);
+ if (NULL == *pPartialFunc) {
+ nodesDestroyList(pParameterList);
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ snprintf((*pPartialFunc)->node.aliasName, sizeof((*pPartialFunc)->node.aliasName), "%s.%p",
+ (*pPartialFunc)->functionName, pSrcFunc);
+ return TSDB_CODE_SUCCESS;
+}
+
+static int32_t createMergeFunction(const SFunctionNode* pSrcFunc, const SFunctionNode* pPartialFunc,
+ SFunctionNode** pMergeFunc) {
+ SNodeList* pParameterList = NULL;
+ nodesListMakeStrictAppend(&pParameterList, createColumnByFunc(pPartialFunc));
+ *pMergeFunc = createFunction(funcMgtBuiltins[pSrcFunc->funcId].pMergeFunc, pParameterList);
+ if (NULL == *pMergeFunc) {
+ nodesDestroyList(pParameterList);
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ strcpy((*pMergeFunc)->node.aliasName, pSrcFunc->node.aliasName);
+ return TSDB_CODE_SUCCESS;
+}
+
+int32_t fmGetDistMethod(const SFunctionNode* pFunc, SFunctionNode** pPartialFunc, SFunctionNode** pMergeFunc) {
+ if (!fmIsDistExecFunc(pFunc->funcId)) {
+ return TSDB_CODE_FAILED;
+ }
+
+ int32_t code = createPartialFunction(pFunc, pPartialFunc);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = createMergeFunction(pFunc, *pPartialFunc, pMergeFunc);
+ }
+
+ if (TSDB_CODE_SUCCESS != code) {
+ nodesDestroyNode(*pPartialFunc);
+ nodesDestroyNode(*pMergeFunc);
+ }
+
+ return code;
+}
diff --git a/source/libs/function/src/taggfunction.c b/source/libs/function/src/taggfunction.c
index 950655e480..e683a38cbd 100644
--- a/source/libs/function/src/taggfunction.c
+++ b/source/libs/function/src/taggfunction.c
@@ -236,7 +236,7 @@ bool isRowEntryCompleted(struct SResultRowEntryInfo* pEntry) {
bool isRowEntryInitialized(struct SResultRowEntryInfo* pEntry) {
return pEntry->initialized;
}
-
+#if 0
int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionId, int32_t param, SResultDataInfo* pInfo, int16_t extLength,
bool isSuperTable/*, SUdfInfo* pUdfInfo*/) {
if (!isValidDataType(dataType)) {
@@ -470,6 +470,7 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI
return TSDB_CODE_SUCCESS;
}
+#endif
static bool function_setup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo) {
if (pResultInfo->initialized) {
diff --git a/source/libs/function/src/texpr.c b/source/libs/function/src/texpr.c
index b91af2d157..703b19ced7 100644
--- a/source/libs/function/src/texpr.c
+++ b/source/libs/function/src/texpr.c
@@ -36,12 +36,7 @@ void tExprTreeDestroy(tExprNode *pNode, void (*fp)(void *)) {
if (pNode->nodeType == TEXPR_BINARYEXPR_NODE || pNode->nodeType == TEXPR_UNARYEXPR_NODE) {
doExprTreeDestroy(&pNode, fp);
- } else if (pNode->nodeType == TEXPR_VALUE_NODE) {
- taosVariantDestroy(pNode->pVal);
- } else if (pNode->nodeType == TEXPR_COL_NODE) {
- taosMemoryFreeClear(pNode->pSchema);
}
-
taosMemoryFree(pNode);
}
@@ -49,15 +44,6 @@ static void doExprTreeDestroy(tExprNode **pExpr, void (*fp)(void *)) {
if (*pExpr == NULL) {
return;
}
-
- int32_t type = (*pExpr)->nodeType;
- if (type == TEXPR_VALUE_NODE) {
- taosVariantDestroy((*pExpr)->pVal);
- taosMemoryFree((*pExpr)->pVal);
- } else if (type == TEXPR_COL_NODE) {
- taosMemoryFree((*pExpr)->pSchema);
- }
-
taosMemoryFree(*pExpr);
*pExpr = NULL;
}
diff --git a/source/libs/nodes/src/nodesCloneFuncs.c b/source/libs/nodes/src/nodesCloneFuncs.c
index e2c9f91af4..94661388cb 100644
--- a/source/libs/nodes/src/nodesCloneFuncs.c
+++ b/source/libs/nodes/src/nodesCloneFuncs.c
@@ -373,7 +373,14 @@ static SNode* logicVnodeModifCopy(const SVnodeModifLogicNode* pSrc, SVnodeModifL
static SNode* logicExchangeCopy(const SExchangeLogicNode* pSrc, SExchangeLogicNode* pDst) {
COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
COPY_SCALAR_FIELD(srcGroupId);
- COPY_SCALAR_FIELD(precision);
+ return (SNode*)pDst;
+}
+
+static SNode* logicMergeCopy(const SMergeLogicNode* pSrc, SMergeLogicNode* pDst) {
+ COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
+ CLONE_NODE_LIST_FIELD(pMergeKeys);
+ COPY_SCALAR_FIELD(numOfChannels);
+ COPY_SCALAR_FIELD(srcGroupId);
return (SNode*)pDst;
}
@@ -537,6 +544,8 @@ SNodeptr nodesCloneNode(const SNodeptr pNode) {
return logicVnodeModifCopy((const SVnodeModifLogicNode*)pNode, (SVnodeModifLogicNode*)pDst);
case QUERY_NODE_LOGIC_PLAN_EXCHANGE:
return logicExchangeCopy((const SExchangeLogicNode*)pNode, (SExchangeLogicNode*)pDst);
+ case QUERY_NODE_LOGIC_PLAN_MERGE:
+ return logicMergeCopy((const SMergeLogicNode*)pNode, (SMergeLogicNode*)pDst);
case QUERY_NODE_LOGIC_PLAN_WINDOW:
return logicWindowCopy((const SWindowLogicNode*)pNode, (SWindowLogicNode*)pDst);
case QUERY_NODE_LOGIC_PLAN_FILL:
diff --git a/source/libs/nodes/src/nodesCodeFuncs.c b/source/libs/nodes/src/nodesCodeFuncs.c
index c0c8168eb1..4bce6381cd 100644
--- a/source/libs/nodes/src/nodesCodeFuncs.c
+++ b/source/libs/nodes/src/nodesCodeFuncs.c
@@ -190,6 +190,8 @@ const char* nodesNodeName(ENodeType type) {
return "LogicVnodeModif";
case QUERY_NODE_LOGIC_PLAN_EXCHANGE:
return "LogicExchange";
+ case QUERY_NODE_LOGIC_PLAN_MERGE:
+ return "LogicMerge";
case QUERY_NODE_LOGIC_PLAN_WINDOW:
return "LogicWindow";
case QUERY_NODE_LOGIC_PLAN_FILL:
@@ -220,6 +222,8 @@ const char* nodesNodeName(ENodeType type) {
return "PhysiAgg";
case QUERY_NODE_PHYSICAL_PLAN_EXCHANGE:
return "PhysiExchange";
+ case QUERY_NODE_PHYSICAL_PLAN_MERGE:
+ return "PhysiMerge";
case QUERY_NODE_PHYSICAL_PLAN_SORT:
return "PhysiSort";
case QUERY_NODE_PHYSICAL_PLAN_INTERVAL:
@@ -596,7 +600,6 @@ static int32_t jsonToLogicProjectNode(const SJson* pJson, void* pObj) {
}
static const char* jkExchangeLogicPlanSrcGroupId = "SrcGroupId";
-static const char* jkExchangeLogicPlanSrcPrecision = "Precision";
static int32_t logicExchangeNodeToJson(const void* pObj, SJson* pJson) {
const SExchangeLogicNode* pNode = (const SExchangeLogicNode*)pObj;
@@ -605,9 +608,6 @@ static int32_t logicExchangeNodeToJson(const void* pObj, SJson* pJson) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkExchangeLogicPlanSrcGroupId, pNode->srcGroupId);
}
- if (TSDB_CODE_SUCCESS == code) {
- code = tjsonAddIntegerToObject(pJson, jkExchangeLogicPlanSrcPrecision, pNode->precision);
- }
return code;
}
@@ -619,8 +619,144 @@ static int32_t jsonToLogicExchangeNode(const SJson* pJson, void* pObj) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetIntValue(pJson, jkExchangeLogicPlanSrcGroupId, &pNode->srcGroupId);
}
+
+ return code;
+}
+
+static const char* jkMergeLogicPlanMergeKeys = "MergeKeys";
+static const char* jkMergeLogicPlanNumOfChannels = "NumOfChannels";
+static const char* jkMergeLogicPlanSrcGroupId = "SrcGroupId";
+
+static int32_t logicMergeNodeToJson(const void* pObj, SJson* pJson) {
+ const SMergeLogicNode* pNode = (const SMergeLogicNode*)pObj;
+
+ int32_t code = logicPlanNodeToJson(pObj, pJson);
if (TSDB_CODE_SUCCESS == code) {
- code = tjsonGetUTinyIntValue(pJson, jkExchangeLogicPlanSrcPrecision, &pNode->precision);
+ code = nodeListToJson(pJson, jkMergeLogicPlanMergeKeys, pNode->pMergeKeys);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkMergeLogicPlanNumOfChannels, pNode->numOfChannels);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkMergeLogicPlanSrcGroupId, pNode->srcGroupId);
+ }
+
+ return code;
+}
+
+static int32_t jsonToLogicMergeNode(const SJson* pJson, void* pObj) {
+ SMergeLogicNode* pNode = (SMergeLogicNode*)pObj;
+
+ int32_t code = jsonToLogicPlanNode(pJson, pObj);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = jsonToNodeList(pJson, jkMergeLogicPlanMergeKeys, &pNode->pMergeKeys);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetIntValue(pJson, jkMergeLogicPlanNumOfChannels, &pNode->numOfChannels);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetIntValue(pJson, jkMergeLogicPlanSrcGroupId, &pNode->srcGroupId);
+ }
+
+ return code;
+}
+
+static const char* jkWindowLogicPlanWinType = "WinType";
+static const char* jkWindowLogicPlanFuncs = "Funcs";
+static const char* jkWindowLogicPlanInterval = "Interval";
+static const char* jkWindowLogicPlanOffset = "Offset";
+static const char* jkWindowLogicPlanSliding = "Sliding";
+static const char* jkWindowLogicPlanIntervalUnit = "IntervalUnit";
+static const char* jkWindowLogicPlanSlidingUnit = "SlidingUnit";
+static const char* jkWindowLogicPlanSessionGap = "SessionGap";
+static const char* jkWindowLogicPlanTspk = "Tspk";
+static const char* jkWindowLogicPlanStateExpr = "StateExpr";
+static const char* jkWindowLogicPlanTriggerType = "TriggerType";
+static const char* jkWindowLogicPlanWatermark = "Watermark";
+
+static int32_t logicWindowNodeToJson(const void* pObj, SJson* pJson) {
+ const SWindowLogicNode* pNode = (const SWindowLogicNode*)pObj;
+
+ int32_t code = logicPlanNodeToJson(pObj, pJson);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkWindowLogicPlanWinType, pNode->winType);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = nodeListToJson(pJson, jkWindowLogicPlanFuncs, pNode->pFuncs);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkWindowLogicPlanInterval, pNode->interval);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkWindowLogicPlanOffset, pNode->offset);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkWindowLogicPlanSliding, pNode->sliding);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkWindowLogicPlanIntervalUnit, pNode->intervalUnit);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkWindowLogicPlanSlidingUnit, pNode->slidingUnit);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkWindowLogicPlanSessionGap, pNode->sessionGap);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddObject(pJson, jkWindowLogicPlanTspk, nodeToJson, pNode->pTspk);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddObject(pJson, jkWindowLogicPlanStateExpr, nodeToJson, pNode->pStateExpr);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkWindowLogicPlanTriggerType, pNode->triggerType);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkWindowLogicPlanWatermark, pNode->watermark);
+ }
+
+ return code;
+}
+
+static int32_t jsonToLogicWindowNode(const SJson* pJson, void* pObj) {
+ SWindowLogicNode* pNode = (SWindowLogicNode*)pObj;
+
+ int32_t code = jsonToLogicPlanNode(pJson, pObj);
+ if (TSDB_CODE_SUCCESS == code) {
+ tjsonGetNumberValue(pJson, jkWindowLogicPlanWinType, pNode->winType, code);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = jsonToNodeList(pJson, jkWindowLogicPlanFuncs, &pNode->pFuncs);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetBigIntValue(pJson, jkWindowLogicPlanInterval, &pNode->interval);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetBigIntValue(pJson, jkWindowLogicPlanOffset, &pNode->offset);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetBigIntValue(pJson, jkWindowLogicPlanSliding, &pNode->sliding);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetTinyIntValue(pJson, jkWindowLogicPlanIntervalUnit, &pNode->intervalUnit);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetTinyIntValue(pJson, jkWindowLogicPlanSlidingUnit, &pNode->slidingUnit);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetBigIntValue(pJson, jkWindowLogicPlanSessionGap, &pNode->sessionGap);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = jsonToNodeObject(pJson, jkWindowLogicPlanTspk, &pNode->pTspk);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = jsonToNodeObject(pJson, jkWindowLogicPlanStateExpr, &pNode->pStateExpr);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetTinyIntValue(pJson, jkWindowLogicPlanTriggerType, &pNode->triggerType);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetBigIntValue(pJson, jkWindowLogicPlanWatermark, &pNode->watermark);
}
return code;
@@ -1459,6 +1595,44 @@ static int32_t jsonToPhysiExchangeNode(const SJson* pJson, void* pObj) {
return code;
}
+static const char* jkMergePhysiPlanMergeKeys = "MergeKeys";
+static const char* jkMergePhysiPlanNumOfChannels = "NumOfChannels";
+static const char* jkMergePhysiPlanSrcGroupId = "SrcGroupId";
+
+static int32_t physiMergeNodeToJson(const void* pObj, SJson* pJson) {
+ const SMergePhysiNode* pNode = (const SMergePhysiNode*)pObj;
+
+ int32_t code = physicPlanNodeToJson(pObj, pJson);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = nodeListToJson(pJson, jkMergePhysiPlanMergeKeys, pNode->pMergeKeys);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkMergePhysiPlanNumOfChannels, pNode->numOfChannels);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkMergePhysiPlanSrcGroupId, pNode->srcGroupId);
+ }
+
+ return code;
+}
+
+static int32_t jsonToPhysiMergeNode(const SJson* pJson, void* pObj) {
+ SMergePhysiNode* pNode = (SMergePhysiNode*)pObj;
+
+ int32_t code = jsonToPhysicPlanNode(pJson, pObj);
+ if (TSDB_CODE_SUCCESS == code) {
+ code = jsonToNodeList(pJson, jkMergePhysiPlanMergeKeys, &pNode->pMergeKeys);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetIntValue(pJson, jkMergePhysiPlanNumOfChannels, &pNode->numOfChannels);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetIntValue(pJson, jkMergePhysiPlanSrcGroupId, &pNode->srcGroupId);
+ }
+
+ return code;
+}
+
static const char* jkSortPhysiPlanExprs = "Exprs";
static const char* jkSortPhysiPlanSortKeys = "SortKeys";
static const char* jkSortPhysiPlanTargets = "Targets";
@@ -3401,6 +3575,10 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
break;
case QUERY_NODE_LOGIC_PLAN_EXCHANGE:
return logicExchangeNodeToJson(pObj, pJson);
+ case QUERY_NODE_LOGIC_PLAN_MERGE:
+ return logicMergeNodeToJson(pObj, pJson);
+ case QUERY_NODE_LOGIC_PLAN_WINDOW:
+ return logicWindowNodeToJson(pObj, pJson);
case QUERY_NODE_LOGIC_PLAN_FILL:
return logicFillNodeToJson(pObj, pJson);
case QUERY_NODE_LOGIC_PLAN_SORT:
@@ -3427,6 +3605,8 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
return physiAggNodeToJson(pObj, pJson);
case QUERY_NODE_PHYSICAL_PLAN_EXCHANGE:
return physiExchangeNodeToJson(pObj, pJson);
+ case QUERY_NODE_PHYSICAL_PLAN_MERGE:
+ return physiMergeNodeToJson(pObj, pJson);
case QUERY_NODE_PHYSICAL_PLAN_SORT:
return physiSortNodeToJson(pObj, pJson);
case QUERY_NODE_PHYSICAL_PLAN_INTERVAL:
@@ -3512,6 +3692,10 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) {
return jsonToLogicProjectNode(pJson, pObj);
case QUERY_NODE_LOGIC_PLAN_EXCHANGE:
return jsonToLogicExchangeNode(pJson, pObj);
+ case QUERY_NODE_LOGIC_PLAN_MERGE:
+ return jsonToLogicMergeNode(pJson, pObj);
+ case QUERY_NODE_LOGIC_PLAN_WINDOW:
+ return jsonToLogicWindowNode(pJson, pObj);
case QUERY_NODE_LOGIC_PLAN_FILL:
return jsonToLogicFillNode(pJson, pObj);
case QUERY_NODE_LOGIC_PLAN_SORT:
@@ -3538,6 +3722,8 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) {
return jsonToPhysiAggNode(pJson, pObj);
case QUERY_NODE_PHYSICAL_PLAN_EXCHANGE:
return jsonToPhysiExchangeNode(pJson, pObj);
+ case QUERY_NODE_PHYSICAL_PLAN_MERGE:
+ return jsonToPhysiMergeNode(pJson, pObj);
case QUERY_NODE_PHYSICAL_PLAN_SORT:
return jsonToPhysiSortNode(pJson, pObj);
case QUERY_NODE_PHYSICAL_PLAN_INTERVAL:
diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c
index d29e89d266..51111ad864 100644
--- a/source/libs/nodes/src/nodesUtilFuncs.c
+++ b/source/libs/nodes/src/nodesUtilFuncs.c
@@ -220,6 +220,8 @@ SNodeptr nodesMakeNode(ENodeType type) {
return makeNode(type, sizeof(SVnodeModifLogicNode));
case QUERY_NODE_LOGIC_PLAN_EXCHANGE:
return makeNode(type, sizeof(SExchangeLogicNode));
+ case QUERY_NODE_LOGIC_PLAN_MERGE:
+ return makeNode(type, sizeof(SMergeLogicNode));
case QUERY_NODE_LOGIC_PLAN_WINDOW:
return makeNode(type, sizeof(SWindowLogicNode));
case QUERY_NODE_LOGIC_PLAN_FILL:
@@ -250,6 +252,8 @@ SNodeptr nodesMakeNode(ENodeType type) {
return makeNode(type, sizeof(SAggPhysiNode));
case QUERY_NODE_PHYSICAL_PLAN_EXCHANGE:
return makeNode(type, sizeof(SExchangePhysiNode));
+ case QUERY_NODE_PHYSICAL_PLAN_MERGE:
+ return makeNode(type, sizeof(SMergePhysiNode));
case QUERY_NODE_PHYSICAL_PLAN_SORT:
return makeNode(type, sizeof(SSortPhysiNode));
case QUERY_NODE_PHYSICAL_PLAN_INTERVAL:
diff --git a/source/libs/parser/inc/parInt.h b/source/libs/parser/inc/parInt.h
index 3efe6700d2..8ec20cde5a 100644
--- a/source/libs/parser/inc/parInt.h
+++ b/source/libs/parser/inc/parInt.h
@@ -32,6 +32,7 @@ int32_t authenticate(SParseContext* pParseCxt, SQuery* pQuery);
int32_t translate(SParseContext* pParseCxt, SQuery* pQuery);
int32_t extractResultSchema(const SNode* pRoot, int32_t* numOfCols, SSchema** pSchema);
int32_t calculateConstant(SParseContext* pParseCxt, SQuery* pQuery);
+int32_t isNotSchemalessDb(SParseContext* pContext, char *dbName);
#ifdef __cplusplus
}
diff --git a/source/libs/parser/src/parInsert.c b/source/libs/parser/src/parInsert.c
index 5c656b969b..422c480397 100644
--- a/source/libs/parser/src/parInsert.c
+++ b/source/libs/parser/src/parInsert.c
@@ -60,6 +60,7 @@ typedef struct SInsertParseContext {
SHashObj* pSubTableHashObj; // global
SArray* pVgDataBlocks; // global
SHashObj* pTableNameHashObj; // global
+ SHashObj* pDbFNameHashObj; // global
int32_t totalNum;
SVnodeModifOpStmt* pOutput;
SStmtCallback* pStmtCb;
@@ -1153,6 +1154,10 @@ static int parseOneRow(SInsertParseContext* pCxt, STableDataBlocks* pDataBlocks,
continue;
}
+ if (TK_NK_RP == sToken.type) {
+ return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMNS_NUM);
+ }
+
if (isParseBindParam) {
return buildInvalidOperationMsg(&pCxt->msg, "no mix usage for ? and values");
}
@@ -1271,6 +1276,7 @@ static void destroyInsertParseContext(SInsertParseContext* pCxt) {
taosHashCleanup(pCxt->pVgroupsHashObj);
taosHashCleanup(pCxt->pSubTableHashObj);
taosHashCleanup(pCxt->pTableNameHashObj);
+ taosHashCleanup(pCxt->pDbFNameHashObj);
destroyBlockHashmap(pCxt->pTableBlockHashObj);
destroyBlockArrayList(pCxt->pVgDataBlocks);
@@ -1329,8 +1335,13 @@ static int32_t parseInsertBody(SInsertParseContext* pCxt) {
SName name;
CHECK_CODE(createSName(&name, &tbnameToken, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg));
+ CHECK_CODE(isNotSchemalessDb(pCxt->pComCxt, name.dbname));
+
tNameExtractFullName(&name, tbFName);
CHECK_CODE(taosHashPut(pCxt->pTableNameHashObj, tbFName, strlen(tbFName), &name, sizeof(SName)));
+ char dbFName[TSDB_DB_FNAME_LEN];
+ tNameGetFullDbName(&name, dbFName);
+ CHECK_CODE(taosHashPut(pCxt->pDbFNameHashObj, dbFName, strlen(dbFName), dbFName, sizeof(dbFName)));
// USING clause
if (TK_USING == sToken.type) {
@@ -1338,8 +1349,6 @@ static int32_t parseInsertBody(SInsertParseContext* pCxt) {
NEXT_TOKEN(pCxt->pSql, sToken);
autoCreateTbl = true;
} else {
- char dbFName[TSDB_DB_FNAME_LEN];
- tNameGetFullDbName(&name, dbFName);
CHECK_CODE(getTableMeta(pCxt, &name, dbFName));
}
@@ -1404,6 +1413,23 @@ static int32_t parseInsertBody(SInsertParseContext* pCxt) {
return buildOutput(pCxt);
}
+int32_t isNotSchemalessDb(SParseContext* pContext, char *dbName){
+ SName name;
+ tNameSetDbName(&name, pContext->acctId, dbName, strlen(dbName));
+ char dbFname[TSDB_DB_FNAME_LEN] = {0};
+ tNameGetFullDbName(&name, dbFname);
+ SDbCfgInfo pInfo = {0};
+ int32_t code = catalogGetDBCfg(pContext->pCatalog, pContext->pTransporter, &pContext->mgmtEpSet, dbFname, &pInfo);
+ if (code != TSDB_CODE_SUCCESS) {
+ parserError("catalogGetDBCfg error, code:%s, dbFName:%s", tstrerror(code), dbFname);
+ return code;
+ }
+ if (pInfo.schemaless){
+ parserError("can not insert into schemaless db:%s", dbFname);
+ return TSDB_CODE_SML_INVALID_DB_CONF;
+ }
+ return TSDB_CODE_SUCCESS;
+}
// INSERT INTO
// tb_name
// [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...)]
@@ -1418,6 +1444,7 @@ int32_t parseInsertSql(SParseContext* pContext, SQuery** pQuery) {
.pTableMeta = NULL,
.pSubTableHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK),
.pTableNameHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK),
+ .pDbFNameHashObj = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), true, HASH_NO_LOCK),
.totalNum = 0,
.pOutput = (SVnodeModifOpStmt*)nodesMakeNode(QUERY_NODE_VNODE_MODIF_STMT),
.pStmtCb = pContext->pStmtCb};
@@ -1432,7 +1459,7 @@ int32_t parseInsertSql(SParseContext* pContext, SQuery** pQuery) {
}
if (NULL == context.pVgroupsHashObj || NULL == context.pTableBlockHashObj || NULL == context.pSubTableHashObj ||
- NULL == context.pTableNameHashObj || NULL == context.pOutput) {
+ NULL == context.pTableNameHashObj || NULL == context.pDbFNameHashObj || NULL == context.pOutput) {
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
@@ -1458,6 +1485,13 @@ int32_t parseInsertSql(SParseContext* pContext, SQuery** pQuery) {
}
}
+ if (NULL == (*pQuery)->pDbList) {
+ (*pQuery)->pDbList = taosArrayInit(taosHashGetSize(context.pDbFNameHashObj), TSDB_DB_FNAME_LEN);
+ if (NULL == (*pQuery)->pDbList) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ }
+
context.pOutput->payloadType = PAYLOAD_TYPE_KV;
int32_t code = skipInsertInto(&context.pSql, &context.msg);
@@ -1470,6 +1504,12 @@ int32_t parseInsertSql(SParseContext* pContext, SQuery** pQuery) {
taosArrayPush((*pQuery)->pTableList, pTable);
pTable = taosHashIterate(context.pTableNameHashObj, pTable);
}
+
+ char* pDb = taosHashIterate(context.pDbFNameHashObj, NULL);
+ while (NULL != pDb) {
+ taosArrayPush((*pQuery)->pDbList, pDb);
+ pDb = taosHashIterate(context.pDbFNameHashObj, pDb);
+ }
}
destroyInsertParseContext(&context);
return code;
diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c
index 6fc9680c09..f0cba6ddc9 100644
--- a/source/libs/parser/src/parTranslater.c
+++ b/source/libs/parser/src/parTranslater.c
@@ -2646,6 +2646,11 @@ static int32_t checkCreateTable(STranslateContext* pCxt, SCreateTableStmt* pStmt
if (TSDB_CODE_SUCCESS == code) {
code = checkTableSchema(pCxt, pStmt);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ if(pCxt->pParseCxt->schemalessType == 0){
+ code = isNotSchemalessDb(pCxt->pParseCxt, pStmt->dbName);
+ }
+ }
return code;
}
@@ -4424,6 +4429,7 @@ static SArray* serializeVgroupsCreateTableBatch(int32_t acctId, SHashObj* pVgrou
}
static int32_t rewriteCreateMultiTable(STranslateContext* pCxt, SQuery* pQuery) {
+
SCreateMultiTableStmt* pStmt = (SCreateMultiTableStmt*)pQuery->pRoot;
SHashObj* pVgroupHashmap = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
@@ -4434,6 +4440,10 @@ static int32_t rewriteCreateMultiTable(STranslateContext* pCxt, SQuery* pQuery)
int32_t code = TSDB_CODE_SUCCESS;
SNode* pNode;
FOREACH(pNode, pStmt->pSubTables) {
+ if(pCxt->pParseCxt->schemalessType == 0 &&
+ (code = isNotSchemalessDb(pCxt->pParseCxt, ((SCreateSubTableClause*)pNode)->dbName)) != TSDB_CODE_SUCCESS){
+ return code;
+ }
code = rewriteCreateSubTable(pCxt, (SCreateSubTableClause*)pNode, pVgroupHashmap);
if (TSDB_CODE_SUCCESS != code) {
taosHashCleanup(pVgroupHashmap);
@@ -4845,9 +4855,14 @@ static int32_t buildModifyVnodeArray(STranslateContext* pCxt, SAlterTableStmt* p
static int32_t rewriteAlterTable(STranslateContext* pCxt, SQuery* pQuery) {
SAlterTableStmt* pStmt = (SAlterTableStmt*)pQuery->pRoot;
+ int32_t code = TSDB_CODE_SUCCESS;
+ if(pCxt->pParseCxt->schemalessType == 0 &&
+ (code = isNotSchemalessDb(pCxt->pParseCxt, pStmt->dbName)) != TSDB_CODE_SUCCESS){
+ return code;
+ }
STableMeta* pTableMeta = NULL;
- int32_t code = getTableMeta(pCxt, pStmt->dbName, pStmt->tableName, &pTableMeta);
+ code = getTableMeta(pCxt, pStmt->dbName, pStmt->tableName, &pTableMeta);
if (TSDB_CODE_SUCCESS != code) {
return code;
}
@@ -4936,6 +4951,47 @@ static int32_t rewriteQuery(STranslateContext* pCxt, SQuery* pQuery) {
return code;
}
+static int32_t toMsgType(ENodeType type) {
+ switch (type) {
+ case QUERY_NODE_CREATE_TABLE_STMT:
+ return TDMT_VND_CREATE_TABLE;
+ case QUERY_NODE_ALTER_TABLE_STMT:
+ return TDMT_VND_ALTER_TABLE;
+ case QUERY_NODE_DROP_TABLE_STMT:
+ return TDMT_VND_DROP_TABLE;
+ default:
+ break;
+ }
+ return TDMT_VND_CREATE_TABLE;
+}
+
+static int32_t setRefreshMate(STranslateContext* pCxt, SQuery* pQuery) {
+ if (NULL != pCxt->pDbs) {
+ pQuery->pDbList = taosArrayInit(taosHashGetSize(pCxt->pDbs), TSDB_DB_FNAME_LEN);
+ if (NULL == pQuery->pDbList) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ SFullDatabaseName* pDb = taosHashIterate(pCxt->pDbs, NULL);
+ while (NULL != pDb) {
+ taosArrayPush(pQuery->pDbList, pDb->fullDbName);
+ pDb = taosHashIterate(pCxt->pDbs, pDb);
+ }
+ }
+
+ if (NULL != pCxt->pTables) {
+ pQuery->pTableList = taosArrayInit(taosHashGetSize(pCxt->pTables), sizeof(SName));
+ if (NULL == pQuery->pTableList) {
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+ SName* pTable = taosHashIterate(pCxt->pTables, NULL);
+ while (NULL != pTable) {
+ taosArrayPush(pQuery->pTableList, pTable);
+ pTable = taosHashIterate(pCxt->pTables, pTable);
+ }
+ }
+ return TSDB_CODE_SUCCESS;
+}
+
static int32_t setQuery(STranslateContext* pCxt, SQuery* pQuery) {
switch (nodeType(pQuery->pRoot)) {
case QUERY_NODE_SELECT_STMT:
@@ -4947,7 +5003,7 @@ static int32_t setQuery(STranslateContext* pCxt, SQuery* pQuery) {
break;
case QUERY_NODE_VNODE_MODIF_STMT:
pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE;
- pQuery->msgType = TDMT_VND_CREATE_TABLE;
+ pQuery->msgType = toMsgType(((SVnodeModifOpStmt*)pQuery->pRoot)->sqlNodeType);
break;
case QUERY_NODE_DESCRIBE_STMT:
pQuery->execMode = QUERY_EXEC_MODE_LOCAL;
@@ -4975,30 +5031,6 @@ static int32_t setQuery(STranslateContext* pCxt, SQuery* pQuery) {
}
}
- if (NULL != pCxt->pDbs) {
- pQuery->pDbList = taosArrayInit(taosHashGetSize(pCxt->pDbs), TSDB_DB_FNAME_LEN);
- if (NULL == pQuery->pDbList) {
- return TSDB_CODE_OUT_OF_MEMORY;
- }
- SFullDatabaseName* pDb = taosHashIterate(pCxt->pDbs, NULL);
- while (NULL != pDb) {
- taosArrayPush(pQuery->pDbList, pDb->fullDbName);
- pDb = taosHashIterate(pCxt->pDbs, pDb);
- }
- }
-
- if (NULL != pCxt->pTables) {
- pQuery->pTableList = taosArrayInit(taosHashGetSize(pCxt->pTables), sizeof(SName));
- if (NULL == pQuery->pTableList) {
- return TSDB_CODE_OUT_OF_MEMORY;
- }
- SName* pTable = taosHashIterate(pCxt->pTables, NULL);
- while (NULL != pTable) {
- taosArrayPush(pQuery->pTableList, pTable);
- pTable = taosHashIterate(pCxt->pTables, pTable);
- }
- }
-
return TSDB_CODE_SUCCESS;
}
@@ -5018,6 +5050,7 @@ int32_t translate(SParseContext* pParseCxt, SQuery* pQuery) {
if (TSDB_CODE_SUCCESS == code) {
code = setQuery(&cxt, pQuery);
}
+ setRefreshMate(&cxt, pQuery);
destroyTranslateContext(&cxt);
return code;
}
diff --git a/source/libs/parser/test/mockCatalog.cpp b/source/libs/parser/test/mockCatalog.cpp
index 154f13ea68..8fb28ce395 100644
--- a/source/libs/parser/test/mockCatalog.cpp
+++ b/source/libs/parser/test/mockCatalog.cpp
@@ -188,8 +188,8 @@ int32_t __catalogGetDBVgVersion(SCatalog* pCtg, const char* dbFName, int32_t* ve
}
int32_t __catalogGetDBVgInfo(SCatalog* pCtg, void* pRpc, const SEpSet* pMgmtEps, const char* dbFName,
- SArray** vgroupList) {
- return 0;
+ SArray** pVgList) {
+ return g_mockCatalogService->catalogGetDBVgInfo(dbFName, pVgList);
}
int32_t __catalogGetDBCfg(SCatalog* pCtg, void* pRpc, const SEpSet* pMgmtEps, const char* dbFName, SDbCfgInfo* pDbCfg) {
diff --git a/source/libs/parser/test/mockCatalogService.cpp b/source/libs/parser/test/mockCatalogService.cpp
index 566c4d8b04..4834d2d377 100644
--- a/source/libs/parser/test/mockCatalogService.cpp
+++ b/source/libs/parser/test/mockCatalogService.cpp
@@ -18,6 +18,7 @@
#include
#include
#include