Merge branch 'develop' into dkj_dev
This commit is contained in:
commit
4fd1c2637d
|
@ -32,7 +32,7 @@ ELSEIF (TD_WINDOWS)
|
|||
#INSTALL(TARGETS taos RUNTIME DESTINATION driver)
|
||||
#INSTALL(TARGETS shell RUNTIME DESTINATION .)
|
||||
IF (TD_MVN_INSTALLED)
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.33-dist.jar DESTINATION connector/jdbc)
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.34-dist.jar DESTINATION connector/jdbc)
|
||||
ENDIF ()
|
||||
ELSEIF (TD_DARWIN)
|
||||
SET(TD_MAKE_INSTALL_SH "${TD_COMMUNITY_DIR}/packaging/tools/make_install.sh")
|
||||
|
|
|
@ -179,17 +179,15 @@ taos> select avg(current), max(voltage), min(phase) from test.d10 interval(10s);
|
|||
| | **CentOS 6/7/8** | **Ubuntu 16/18/20** | **Other Linux** | **统信 UOS** | **银河/中标麒麟** | **凝思 V60/V80** | **华为 EulerOS** |
|
||||
| -------------- | --------------------- | ------------------------ | --------------- | --------------- | ------------------------- | --------------------- | --------------------- |
|
||||
| X64 | ● | ● | | ○ | ● | ● | ● |
|
||||
| 树莓派 ARM32 | | ● | ● | | | | |
|
||||
| 龙芯 MIPS64 | | | ● | | | | |
|
||||
| 鲲鹏 ARM64 | | ○ | ○ | | ● | | |
|
||||
| 申威 Alpha64 | | | ○ | ● | | | |
|
||||
| 鲲鹏 ARM64 | | ○ | ○ | | ● | | |
|
||||
| 申威 Alpha64 | | | ○ | ● | | | |
|
||||
| 飞腾 ARM64 | | ○ 优麒麟 | | | | | |
|
||||
| 海光 X64 | ● | ● | ● | ○ | ● | ● | |
|
||||
| 瑞芯微 ARM64/32 | | | ○ | | | | |
|
||||
| 全志 ARM64/32 | | | ○ | | | | |
|
||||
| 炬力 ARM64/32 | | | ○ | | | | |
|
||||
| TI ARM32 | | | ○ | | | | |
|
||||
| 华为云 ARM64 | | | | | | | ● |
|
||||
| 瑞芯微 ARM64 | | | ○ | | | | |
|
||||
| 全志 ARM64 | | | ○ | | | | |
|
||||
| 炬力 ARM64 | | | ○ | | | | |
|
||||
| 华为云 ARM64 | | | | | | | ● |
|
||||
|
||||
注: ● 表示经过官方测试验证, ○ 表示非官方测试验证。
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ TDengine采取的是Master-Slave模式进行同步,与流行的RAFT一致性
|
|||
2. 应用将打上版本号的写请求封装一个WAL Head, 写入WAL(Write Ahead Log)
|
||||
3. 应用调用API syncForwardToPeer,如果vnode B是slave状态,sync模块将包含WAL Head的数据包通过Forward消息发送给vnode B,否则就不转发。
|
||||
4. vnode B收到Forward消息后,调用回调函数writeToCache, 交给应用处理
|
||||
5. vnode B应用在写入成功后,都需要调用syncAckForward通知sync模块已经写入成功。
|
||||
5. vnode B应用在写入成功后,都需要调用syncConfirmForward通知sync模块已经写入成功。
|
||||
6. 如果quorum大于1,vnode B需要等待应用的回复确认,收到确认后,vnode B发送Forward Response消息给node A。
|
||||
7. 如果quorum大于1,vnode A需要等待vnode B或其他副本对Forward消息的确认。
|
||||
8. 如果quorum大于1,vnode A收到quorum-1条确认消息后,调用回调函数confirmForward,通知应用写入成功。
|
||||
|
@ -140,7 +140,7 @@ TDengine采取的是Master-Slave模式进行同步,与流行的RAFT一致性
|
|||
|
||||
整个数据恢复流程分为两大步骤,第一步,先恢复archived data(file), 然后恢复wal。具体流程如下:
|
||||
|
||||

|
||||

|
||||
|
||||
1. 通过已经建立的TCP连接,发送sync req给master节点
|
||||
2. master收到sync req后,以client的身份,向vnode B主动建立一新的专用于同步的TCP连接(syncFd)
|
||||
|
|
|
@ -323,8 +323,6 @@ Vnode会保持一个数据版本号(Version),对内存数据进行持久化存
|
|||
|
||||
采用同步复制,系统的性能会有所下降,而且latency会增加。因为元数据要强一致,mnode之间的数据同步缺省就是采用的同步复制。
|
||||
|
||||
注:vnode之间的同步复制仅仅企业版支持
|
||||
|
||||
## <a class="anchor" id="persistence"></a>缓存与持久化
|
||||
|
||||
### 缓存
|
||||
|
|
|
@ -48,7 +48,7 @@ TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传
|
|||
| 3 | BIGINT | 8 | 长整型,范围 [-2^63+1, 2^63-1], -2^63 用于 NULL |
|
||||
| 4 | FLOAT | 4 | 浮点型,有效位数 6-7,范围 [-3.4E38, 3.4E38] |
|
||||
| 5 | DOUBLE | 8 | 双精度浮点型,有效位数 15-16,范围 [-1.7E308, 1.7E308] |
|
||||
| 6 | BINARY | 自定义 | 记录单字节字符串,建议只用于处理 ASCII 可见字符,中文等多字节字符需使用 nchar。理论上,最长可以有 16374 字节,但由于每行数据最多 16K 字节,实际上限一般小于理论值。binary 仅支持字符串输入,字符串两端需使用单引号引用。使用时须指定大小,如 binary(20) 定义了最长为 20 个单字节字符的字符串,每个字符占 1 byte 的存储空间,此时如果用户字符串超出 20 字节将会报错。对于字符串内的单引号,可以用转义字符反斜线加单引号来表示,即 `\’`。 |
|
||||
| 6 | BINARY | 自定义 | 记录单字节字符串,建议只用于处理 ASCII 可见字符,中文等多字节字符需使用 nchar。理论上,最长可以有 16374 字节,但由于每行数据最多 16K 字节,实际上限一般小于理论值。binary 仅支持字符串输入,字符串两端需使用单引号引用。使用时须指定大小,如 binary(20) 定义了最长为 20 个单字节字符的字符串,每个字符占 1 byte 的存储空间,总共固定占用 20 bytes 的空间,此时如果用户字符串超出 20 字节将会报错。对于字符串内的单引号,可以用转义字符反斜线加单引号来表示,即 `\’`。 |
|
||||
| 7 | SMALLINT | 2 | 短整型, 范围 [-32767, 32767], -32768 用于 NULL |
|
||||
| 8 | TINYINT | 1 | 单字节整型,范围 [-127, 127], -128 用于 NULL |
|
||||
| 9 | BOOL | 1 | 布尔型,{true, false} |
|
||||
|
@ -208,7 +208,7 @@ TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传
|
|||
|
||||
说明:可在like中使用通配符进行名称的匹配,这一通配符字符串最长不能超过24字节。
|
||||
|
||||
通配符匹配:1)'%'(百分号)匹配0到任意个字符;2)'\_'下划线匹配单个任意字符。(如果希望匹配表名中带有的下划线,那么这里可以用反斜线进行转义,也就是说 '\\\_' 会被用于匹配表名中原始带有的下划线符号)
|
||||
通配符匹配:1)'%'(百分号)匹配0到任意个字符;2)'\_'下划线匹配单个任意字符。
|
||||
|
||||
- **显示一个数据表的创建语句**
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ One of the modules of TDengine is the time-series database. However, in addition
|
|||
- **Full-stack time-series data processing engine**: Integrate database, message queue, cache, stream computing, and other functions, and the applications do not need to integrate with software such as Kafka/Redis/HBase/Spark/HDFS, thus greatly reducing the complexity cost of application development and maintenance.
|
||||
- **Powerful analysis functions**: Data from ten years ago or one second ago, can all be queried based on a specified time range. Data can be aggregated on a timeline or multiple devices. Ad-hoc queries can be made at any time through Shell, Python, R, and MATLAB.
|
||||
- **Seamless connection with third-party tools**: Integration with Telegraf, Grafana, EMQ, HiveMQ, Prometheus, MATLAB, R, etc. without even one single line of code. OPC, Hadoop, Spark, etc. will be supported in the future, and more BI tools will be seamlessly connected to.
|
||||
- **Zero operation cost & zero learning cost**: Installing clusters is simple and quick, with real-time backup built-in, and no need to split libraries or tables. Similar to standard SQL, TDengine can support RESTful, Python/Java/C/C + +/C#/Go/Node.js, and similar to MySQL with zero learning cost.
|
||||
- **Zero operation cost & zero learning cost**: Installing clusters is simple and quick, with real-time backup built-in, and no need to split libraries or tables. Similar to standard SQL, TDengine can support RESTful, Python/Java/C/C++/C#/Go/Node.js, and similar to MySQL with zero learning cost.
|
||||
|
||||
With TDengine, the total cost of ownership of typical IoT, Internet of Vehicles, and Industrial Internet Big Data platforms can be greatly reduced. However, it should be pointed out that due to making full use of the characteristics of IoT time-series data, TDengine cannot be used to process general data from web crawlers, microblogs, WeChat, e-commerce, ERP, CRM, and other sources.
|
||||
|
||||
|
|
|
@ -188,16 +188,14 @@ List of platforms supported by TDengine server
|
|||
| | **CentOS 6/7/8** | **Ubuntu 16/18/20** | **Other Linux** | UnionTech UOS | NeoKylin | LINX V60/V80 |
|
||||
| ------------------ | ---------------- | ------------------- | --------------- | ------------- | -------- | ------------ |
|
||||
| X64 | ● | ● | | ○ | ● | ● |
|
||||
| Raspberry ARM32 | | ● | ● | | | |
|
||||
| Loongson MIPS64 | | | ● | | | |
|
||||
| Kunpeng ARM64 | | ○ | ○ | | ● | |
|
||||
| SWCPU Alpha64 | | | ○ | ● | | |
|
||||
| FT ARM64 | | ○Ubuntu Kylin | | | | |
|
||||
| Hygon X64 | ● | ● | ● | ○ | ● | ● |
|
||||
| Rockchip ARM64/32 | | | ○ | | | |
|
||||
| Allwinner ARM64/32 | | | ○ | | | |
|
||||
| Actions ARM64/32 | | | ○ | | | |
|
||||
| TI ARM32 | | | ○ | | | |
|
||||
| Rockchip ARM64 | | | ○ | | | |
|
||||
| Allwinner ARM64 | | | ○ | | | |
|
||||
| Actions ARM64 | | | ○ | | | |
|
||||
|
||||
Note: ● has been verified by official tests; ○ has been verified by unofficial tests.
|
||||
|
||||
|
|
|
@ -172,7 +172,7 @@ A complete TDengine system runs on one or more physical nodes. Logically, it inc
|
|||
|
||||
**Virtual node group (VGroup)**: Vnodes on different data nodes can form a virtual node group to ensure the high reliability of the system. The virtual node group is managed in a master/slave structure. Write operations can only be performed on the master vnode, and the system synchronizes data to the slave vnode via replication, thus ensuring that one single replica of data is copied on multiple physical nodes. The number of virtual nodes in a vgroup equals the number of data replicas. If the number of replicas of a DB is N, the system must have at least N data nodes. The number of replicas can be specified by the parameter replica when creating DB, and the default is 1. Using the multi-replica feature of TDengine, the same high data reliability can be done without the need for expensive storage devices such as disk arrays. Virtual node group is created and managed by management node, and the management node assigns a system unique ID, aka VGroup ID. If two virtual nodes has the same vnode group ID, means that they belong to the same group and the data is backed up to each other. The number of virtual nodes in a virtual node group can be dynamically changed, allowing only one, that is, no data replication. VGroup ID is never changed. Even if a virtual node group is deleted, its ID will not be reused.
|
||||
|
||||
**TAOSC**: TAOSC is the driver provided by TDengine to applications, which is responsible for dealing with the interface interaction between application and cluster, and provides the native interface of C/C + + language, which is embedded in JDBC, C #, Python, Go, Node.js language connection libraries. Applications interact with the whole cluster through taosc instead of directly connecting to data nodes in the cluster. This module is responsible for obtaining and caching metadata; forwarding requests for insertion, query, etc. to the correct data node; when returning the results to the application, taosc also need to be responsible for the final level of aggregation, sorting, filtering and other operations. For JDBC, C/C + +/C #/Python/Go/Node.js interfaces, this module runs on the physical node where the application is located. At the same time, in order to support the fully distributed RESTful interface, taosc has a running instance on each dnode of TDengine cluster.
|
||||
**TAOSC**: TAOSC is the driver provided by TDengine to applications, which is responsible for dealing with the interface interaction between application and cluster, and provides the native interface of C/C++ language, which is embedded in JDBC, C #, Python, Go, Node.js language connection libraries. Applications interact with the whole cluster through taosc instead of directly connecting to data nodes in the cluster. This module is responsible for obtaining and caching metadata; forwarding requests for insertion, query, etc. to the correct data node; when returning the results to the application, taosc also need to be responsible for the final level of aggregation, sorting, filtering and other operations. For JDBC, C/C++/C #/Python/Go/Node.js interfaces, this module runs on the physical node where the application is located. At the same time, in order to support the fully distributed RESTful interface, taosc has a running instance on each dnode of TDengine cluster.
|
||||
|
||||
### Node Communication
|
||||
|
||||
|
@ -322,8 +322,6 @@ For scenarios with higher data consistency requirements, asynchronous data repli
|
|||
|
||||
With synchronous replication, performance of system will decrease and latency will increase. Because metadata needs strong consistent, the default for data synchronization between mnodes is synchronous replication.
|
||||
|
||||
Note: synchronous replication between vnodes is only supported in Enterprise Edition
|
||||
|
||||
## <a class="anchor" id="persistence"></a> Caching and Persistence
|
||||
|
||||
### Caching
|
||||
|
|
|
@ -4,7 +4,7 @@ TDengine supports multiple interfaces to write data, including SQL, Prometheus,
|
|||
|
||||
## <a class="anchor" id="sql"></a> SQL Writing
|
||||
|
||||
Applications insert data by executing SQL insert statements through C/C + +, JDBC, GO, or Python Connector, and users can manually enter SQL insert statements to insert data through TAOS Shell. For example, the following insert writes a record to table d1001:
|
||||
Applications insert data by executing SQL insert statements through C/C++, JDBC, GO, or Python Connector, and users can manually enter SQL insert statements to insert data through TAOS Shell. For example, the following insert writes a record to table d1001:
|
||||
|
||||
```mysql
|
||||
INSERT INTO d1001 VALUES (1538548685000, 10.3, 219, 0.31);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
## <a class="anchor" id="queries"></a> Main Query Features
|
||||
|
||||
TDengine uses SQL as the query language. Applications can send SQL statements through C/C + +, Java, Go, Python connectors, and users can manually execute SQL Ad-Hoc Query through the Command Line Interface (CLI) tool TAOS Shell provided by TDengine. TDengine supports the following query functions:
|
||||
TDengine uses SQL as the query language. Applications can send SQL statements through C/C++, Java, Go, Python connectors, and users can manually execute SQL Ad-Hoc Query through the Command Line Interface (CLI) tool TAOS Shell provided by TDengine. TDengine supports the following query functions:
|
||||
|
||||
- Single-column and multi-column data query
|
||||
- Multiple filters for tags and numeric values: >, <, =, < >, like, etc
|
||||
|
|
|
@ -22,7 +22,7 @@ Note: ● stands for that has been verified by official tests; ○ stands for th
|
|||
Note:
|
||||
|
||||
- To access the TDengine database through connectors (except RESTful) in the system without TDengine server software, it is necessary to install the corresponding version of the client installation package to make the application driver (the file name is [libtaos.so](http://libtaos.so/) in Linux system and taos.dll in Windows system) installed in the system, otherwise, the error that the corresponding library file cannot be found will occur.
|
||||
- All APIs that execute SQL statements, such as `tao_query`, `taos_query_a`, `taos_subscribe` in C/C + + Connector, and APIs corresponding to them in other languages, can only execute one SQL statement at a time. If the actual parameters contain multiple statements, their behavior is undefined.
|
||||
- All APIs that execute SQL statements, such as `tao_query`, `taos_query_a`, `taos_subscribe` in C/C++ Connector, and APIs corresponding to them in other languages, can only execute one SQL statement at a time. If the actual parameters contain multiple statements, their behavior is undefined.
|
||||
- Users upgrading to TDengine 2.0. 8.0 must update the JDBC connection. TDengine must upgrade taos-jdbcdriver to 2.0.12 and above.
|
||||
- No matter which programming language connector is selected, TDengine version 2.0 and above recommends that each thread of database application establish an independent connection or establish a connection pool based on threads to avoid mutual interference between threads of "USE statement" state variables in the connection (but query and write operations of the connection are thread-safe).
|
||||
|
||||
|
@ -152,7 +152,7 @@ Under cmd, enter the c:\ tdengine directory and directly execute taos.exe, and y
|
|||
| **OS Type** | Linux | Win64 | Win32 | Linux | Linux |
|
||||
| **Supported or Not** | Yes | **Yes** | **Yes** | **Yes** | **In development** |
|
||||
|
||||
The C/C + + API is similar to MySQL's C API. When application use it, it needs to include the TDengine header file taos.h (after installed, it is located in/usr/local/taos/include):
|
||||
The C/C++ API is similar to MySQL's C API. When application use it, it needs to include the TDengine header file taos.h (after installed, it is located in/usr/local/taos/include):
|
||||
|
||||
```C
|
||||
#include <taos.h>
|
||||
|
@ -923,7 +923,7 @@ Manually install the following tools:
|
|||
|
||||
If the steps above cannot be performed successfully, you can refer to Microsoft's Node.js User Manual [Microsoft's Node.js Guidelines for Windows](https://github.com/Microsoft/nodejs-guidelines/blob/master/windows-environment.md#compiling-native-addon-modules).
|
||||
|
||||
If you use ARM64 Node.js on Windows 10 ARM, you also need to add "Visual C + + compilers and libraries for ARM64" and "Visual C + + ATL for ARM64".
|
||||
If you use ARM64 Node.js on Windows 10 ARM, you also need to add "Visual C++ compilers and libraries for ARM64" and "Visual C++ ATL for ARM64".
|
||||
|
||||
#### Sample
|
||||
|
||||
|
|
|
@ -240,7 +240,7 @@ Client configuration parameters:
|
|||
```sql
|
||||
SELECT count(*) FROM table_name WHERE TS<1554984068000;
|
||||
```
|
||||
In order to avoid the uncertainty caused by using string time format, Unix timestamp can also be used directly. In addition, timestamp strings with time zones can also be used in SQL statements, such as: timestamp strings in RFC3339 format, 2013-04-12T15: 52: 01.123 +08:00, or ISO-8601 format timestamp strings 2013-04-12T15: 52: 01.123 +0800. The conversion of the above two strings into Unix timestamps is not affected by the time zone in which the system is located.
|
||||
In order to avoid the uncertainty caused by using string time format, Unix timestamp can also be used directly. In addition, timestamp strings with time zones can also be used in SQL statements, such as: timestamp strings in RFC3339 format, 2013-04-12T15:52:01.123+08:00, or ISO-8601 format timestamp strings 2013-04-12T15:52:01.123+0800. The conversion of the above two strings into Unix timestamps is not affected by the time zone in which the system is located.
|
||||
|
||||
When starting taos, you can also specify an end point for an instance of taosd from the command line, otherwise read from taos.cfg.
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
static SBnThread tsBnThread;
|
||||
|
||||
static void *bnThreadFunc(void *arg) {
|
||||
setThreadName("bnThreadd");
|
||||
setThreadName("balance");
|
||||
|
||||
while (1) {
|
||||
pthread_mutex_lock(&tsBnThread.mutex);
|
||||
|
|
|
@ -344,6 +344,7 @@ int32_t tscCreateTableMetaFromSTableMeta(STableMeta* pChild, const char* name, v
|
|||
STableMeta* tscTableMetaDup(STableMeta* pTableMeta);
|
||||
SVgroupsInfo* tscVgroupsInfoDup(SVgroupsInfo* pVgroupsInfo);
|
||||
|
||||
int32_t tscGetColFilterSerializeLen(SQueryInfo* pQueryInfo);
|
||||
int32_t tscCreateQueryFromQueryInfo(SQueryInfo* pQueryInfo, SQueryAttr* pQueryAttr, void* addr);
|
||||
void* createQInfoFromQueryNode(SQueryInfo* pQueryInfo, STableGroupInfo* pTableGroupInfo, SOperatorInfo* pOperator, char* sql, void* addr, int32_t stage, uint64_t qId);
|
||||
|
||||
|
@ -354,6 +355,8 @@ char* strdup_throw(const char* str);
|
|||
bool vgroupInfoIdentical(SNewVgroupInfo *pExisted, SVgroupMsg* src);
|
||||
SNewVgroupInfo createNewVgroupInfo(SVgroupMsg *pVgroupMsg);
|
||||
|
||||
void tscRemoveTableMetaBuf(STableMetaInfo* pTableMetaInfo, uint64_t id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -151,7 +151,8 @@ typedef struct STableDataBlocks {
|
|||
|
||||
typedef struct {
|
||||
STableMeta *pTableMeta;
|
||||
SVgroupsInfo *pVgroupInfo;
|
||||
SArray *vgroupIdList;
|
||||
// SVgroupsInfo *pVgroupsInfo;
|
||||
} STableMetaVgroupInfo;
|
||||
|
||||
typedef struct SInsertStatementParam {
|
||||
|
@ -375,6 +376,8 @@ void tscResetSqlCmd(SSqlCmd *pCmd, bool removeMeta);
|
|||
*/
|
||||
void tscFreeSqlResult(SSqlObj *pSql);
|
||||
|
||||
void* tscCleanupTableMetaMap(SHashObj* pTableMetaMap);
|
||||
|
||||
/**
|
||||
* free sql object, release allocated resource
|
||||
* @param pObj
|
||||
|
@ -415,7 +418,8 @@ int32_t tscValidateSqlInfo(SSqlObj *pSql, struct SSqlInfo *pInfo);
|
|||
int32_t tsSetBlockInfo(SSubmitBlk *pBlocks, const STableMeta *pTableMeta, int32_t numOfRows);
|
||||
extern int32_t sentinel;
|
||||
extern SHashObj *tscVgroupMap;
|
||||
extern SHashObj *tscTableMetaInfo;
|
||||
extern SHashObj *tscTableMetaMap;
|
||||
extern SCacheObj *tscVgroupListBuf;
|
||||
|
||||
extern int tscObjRef;
|
||||
extern void *tscTmr;
|
||||
|
|
|
@ -325,61 +325,6 @@ void tscAsyncResultOnError(SSqlObj* pSql) {
|
|||
|
||||
int tscSendMsgToServer(SSqlObj *pSql);
|
||||
|
||||
static int32_t updateMetaBeforeRetryQuery(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo, SQueryInfo* pQueryInfo) {
|
||||
// handle the invalid table error code for super table.
|
||||
// update the pExpr info, colList info, number of table columns
|
||||
// TODO Re-parse this sql and issue the corresponding subquery as an alternative for this case.
|
||||
if (pSql->retryReason == TSDB_CODE_TDB_INVALID_TABLE_ID) {
|
||||
int32_t numOfExprs = (int32_t) tscNumOfExprs(pQueryInfo);
|
||||
int32_t numOfCols = tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
|
||||
int32_t numOfTags = tscGetNumOfTags(pTableMetaInfo->pTableMeta);
|
||||
|
||||
SSchema *pSchema = tscGetTableSchema(pTableMetaInfo->pTableMeta);
|
||||
SSchema *pTagSchema = tscGetTableTagSchema(pTableMetaInfo->pTableMeta);
|
||||
|
||||
for (int32_t i = 0; i < numOfExprs; ++i) {
|
||||
SSqlExpr *pExpr = &(tscExprGet(pQueryInfo, i)->base);
|
||||
|
||||
// update the table uid
|
||||
pExpr->uid = pTableMetaInfo->pTableMeta->id.uid;
|
||||
|
||||
if (pExpr->colInfo.colIndex >= 0) {
|
||||
int32_t index = pExpr->colInfo.colIndex;
|
||||
|
||||
if ((TSDB_COL_IS_NORMAL_COL(pExpr->colInfo.flag) && index >= numOfCols) ||
|
||||
(TSDB_COL_IS_TAG(pExpr->colInfo.flag) && (index < 0 || index >= numOfTags))) {
|
||||
return pSql->retryReason;
|
||||
}
|
||||
|
||||
if (TSDB_COL_IS_TAG(pExpr->colInfo.flag)) {
|
||||
if ((pTagSchema[pExpr->colInfo.colIndex].colId != pExpr->colInfo.colId) &&
|
||||
strcasecmp(pExpr->colInfo.name, pTagSchema[pExpr->colInfo.colIndex].name) != 0) {
|
||||
return pSql->retryReason;
|
||||
}
|
||||
} else if (TSDB_COL_IS_NORMAL_COL(pExpr->colInfo.flag)) {
|
||||
if ((pSchema[pExpr->colInfo.colIndex].colId != pExpr->colInfo.colId) &&
|
||||
strcasecmp(pExpr->colInfo.name, pSchema[pExpr->colInfo.colIndex].name) != 0) {
|
||||
return pSql->retryReason;
|
||||
}
|
||||
} else { // do nothing for udc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// validate the table columns information
|
||||
for (int32_t i = 0; i < taosArrayGetSize(pQueryInfo->colList); ++i) {
|
||||
SColumn *pCol = taosArrayGetP(pQueryInfo->colList, i);
|
||||
if (pCol->columnIndex >= numOfCols) {
|
||||
return pSql->retryReason;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) {
|
||||
SSqlObj* pSql = (SSqlObj*)taosAcquireRef(tscObjRef, (int64_t)param);
|
||||
if (pSql == NULL) return;
|
||||
|
@ -391,7 +336,7 @@ void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) {
|
|||
pRes->code = code;
|
||||
|
||||
SSqlObj *sub = (SSqlObj*) res;
|
||||
const char* msg = (sub->cmd.command == TSDB_SQL_STABLEVGROUP)? "vgroup-list":"table-meta";
|
||||
const char* msg = (sub->cmd.command == TSDB_SQL_STABLEVGROUP)? "vgroup-list":"multi-tableMeta";
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
tscError("0x%"PRIx64" get %s failed, code:%s", pSql->self, msg, tstrerror(code));
|
||||
goto _error;
|
||||
|
@ -401,85 +346,56 @@ void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) {
|
|||
if (pSql->pStream == NULL) {
|
||||
SQueryInfo *pQueryInfo = tscGetQueryInfo(pCmd);
|
||||
|
||||
// check if it is a sub-query of super table query first, if true, enter another routine
|
||||
if (TSDB_QUERY_HAS_TYPE(pQueryInfo->type, (TSDB_QUERY_TYPE_STABLE_SUBQUERY | TSDB_QUERY_TYPE_SUBQUERY |
|
||||
TSDB_QUERY_TYPE_TAG_FILTER_QUERY))) {
|
||||
tscDebug("0x%" PRIx64 " update cached table-meta, continue to process sql and send the corresponding query", pSql->self);
|
||||
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
|
||||
code = tscGetTableMeta(pSql, pTableMetaInfo);
|
||||
assert(code == TSDB_CODE_TSC_ACTION_IN_PROGRESS || code == TSDB_CODE_SUCCESS);
|
||||
if (TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_INSERT)) {
|
||||
tscDebug("0x%" PRIx64 " continue parse sql after get table-meta", pSql->self);
|
||||
|
||||
code = tsParseSql(pSql, false);
|
||||
if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
|
||||
taosReleaseRef(tscObjRef, pSql->self);
|
||||
return;
|
||||
}
|
||||
|
||||
assert((tscGetNumOfTags(pTableMetaInfo->pTableMeta) != 0));
|
||||
code = updateMetaBeforeRetryQuery(pSql, pTableMetaInfo, pQueryInfo);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
} else if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _error;
|
||||
}
|
||||
|
||||
// tscBuildAndSendRequest can add error into async res
|
||||
tscBuildAndSendRequest(pSql, NULL);
|
||||
taosReleaseRef(tscObjRef, pSql->self);
|
||||
return;
|
||||
} else { // continue to process normal async query
|
||||
if (TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_INSERT)) {
|
||||
tscDebug("0x%" PRIx64 " continue parse sql after get table-meta", pSql->self);
|
||||
|
||||
code = tsParseSql(pSql, false);
|
||||
if (TSDB_QUERY_HAS_TYPE(pCmd->insertParam.insertType, TSDB_QUERY_TYPE_STMT_INSERT)) { // stmt insert
|
||||
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
code = tscGetTableMeta(pSql, pTableMetaInfo);
|
||||
if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
|
||||
taosReleaseRef(tscObjRef, pSql->self);
|
||||
return;
|
||||
} else if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _error;
|
||||
}
|
||||
|
||||
if (TSDB_QUERY_HAS_TYPE(pCmd->insertParam.insertType, TSDB_QUERY_TYPE_STMT_INSERT)) {
|
||||
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
code = tscGetTableMeta(pSql, pTableMetaInfo);
|
||||
if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
|
||||
taosReleaseRef(tscObjRef, pSql->self);
|
||||
return;
|
||||
} else {
|
||||
assert(code == TSDB_CODE_SUCCESS);
|
||||
}
|
||||
|
||||
(*pSql->fp)(pSql->param, pSql, code);
|
||||
} else {
|
||||
if (TSDB_QUERY_HAS_TYPE(pCmd->insertParam.insertType, TSDB_QUERY_TYPE_FILE_INSERT)) {
|
||||
tscImportDataFromFile(pSql);
|
||||
} else {
|
||||
tscHandleMultivnodeInsert(pSql);
|
||||
}
|
||||
assert(code == TSDB_CODE_SUCCESS);
|
||||
}
|
||||
|
||||
(*pSql->fp)(pSql->param, pSql, code);
|
||||
} else if (TSDB_QUERY_HAS_TYPE(pCmd->insertParam.insertType, TSDB_QUERY_TYPE_FILE_INSERT)) { // file insert
|
||||
tscImportDataFromFile(pSql);
|
||||
} else { // sql string insert
|
||||
tscHandleMultivnodeInsert(pSql);
|
||||
}
|
||||
} else {
|
||||
if (pSql->retryReason != TSDB_CODE_SUCCESS) {
|
||||
tscDebug("0x%" PRIx64 " update cached table-meta, re-validate sql statement and send query again", pSql->self);
|
||||
tscResetSqlCmd(pCmd, false);
|
||||
pSql->retryReason = TSDB_CODE_SUCCESS;
|
||||
} else {
|
||||
if (pSql->retryReason != TSDB_CODE_SUCCESS) {
|
||||
tscDebug("0x%" PRIx64 " update cached table-meta, re-validate sql statement and send query again",
|
||||
pSql->self);
|
||||
tscResetSqlCmd(pCmd, false);
|
||||
pSql->retryReason = TSDB_CODE_SUCCESS;
|
||||
} else {
|
||||
tscDebug("0x%" PRIx64 " cached table-meta, continue validate sql statement and send query", pSql->self);
|
||||
}
|
||||
|
||||
code = tsParseSql(pSql, true);
|
||||
if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
|
||||
taosReleaseRef(tscObjRef, pSql->self);
|
||||
return;
|
||||
} else if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _error;
|
||||
}
|
||||
|
||||
SQueryInfo *pQueryInfo1 = tscGetQueryInfo(pCmd);
|
||||
executeQuery(pSql, pQueryInfo1);
|
||||
tscDebug("0x%" PRIx64 " cached table-meta, continue validate sql statement and send query", pSql->self);
|
||||
}
|
||||
|
||||
taosReleaseRef(tscObjRef, pSql->self);
|
||||
return;
|
||||
code = tsParseSql(pSql, true);
|
||||
if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
|
||||
taosReleaseRef(tscObjRef, pSql->self);
|
||||
return;
|
||||
} else if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _error;
|
||||
}
|
||||
|
||||
SQueryInfo *pQueryInfo1 = tscGetQueryInfo(pCmd);
|
||||
executeQuery(pSql, pQueryInfo1);
|
||||
}
|
||||
|
||||
taosReleaseRef(tscObjRef, pSql->self);
|
||||
return;
|
||||
} else { // stream computing
|
||||
tscDebug("0x%"PRIx64" stream:%p meta is updated, start new query, command:%d", pSql->self, pSql->pStream, pCmd->command);
|
||||
|
||||
|
|
|
@ -920,7 +920,8 @@ int tscProcessLocalCmd(SSqlObj *pSql) {
|
|||
} else if (pCmd->command == TSDB_SQL_SHOW_CREATE_DATABASE) {
|
||||
pRes->code = tscProcessShowCreateDatabase(pSql);
|
||||
} else if (pCmd->command == TSDB_SQL_RESET_CACHE) {
|
||||
taosHashClear(tscTableMetaInfo);
|
||||
taosHashClear(tscTableMetaMap);
|
||||
taosCacheEmpty(tscVgroupListBuf);
|
||||
pRes->code = TSDB_CODE_SUCCESS;
|
||||
} else if (pCmd->command == TSDB_SQL_SERV_VERSION) {
|
||||
pRes->code = tscProcessServerVer(pSql);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -80,8 +80,8 @@ static void getColumnName(tSqlExprItem* pItem, char* resultFieldName, char* rawN
|
|||
|
||||
static int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t colIndex, tSqlExprItem* pItem,
|
||||
bool finalResult, SUdfInfo* pUdfInfo);
|
||||
static int32_t insertResultField(SQueryInfo* pQueryInfo, int32_t outputIndex, SColumnList* pIdList, int16_t bytes,
|
||||
int8_t type, char* fieldName, SExprInfo* pSqlExpr);
|
||||
static int32_t insertResultField(SQueryInfo* pQueryInfo, int32_t outputIndex, SColumnList* pColList, int16_t bytes,
|
||||
int8_t type, char* fieldName, SExprInfo* pSqlExpr);
|
||||
|
||||
static uint8_t convertRelationalOperator(SStrToken *pToken);
|
||||
|
||||
|
@ -1947,12 +1947,13 @@ bool isValidDistinctSql(SQueryInfo* pQueryInfo) {
|
|||
if (pQueryInfo == NULL) {
|
||||
return false;
|
||||
}
|
||||
if ((pQueryInfo->type & TSDB_QUERY_TYPE_STABLE_QUERY) != TSDB_QUERY_TYPE_STABLE_QUERY) {
|
||||
if ((pQueryInfo->type & TSDB_QUERY_TYPE_STABLE_QUERY) != TSDB_QUERY_TYPE_STABLE_QUERY
|
||||
&& (pQueryInfo->type & TSDB_QUERY_TYPE_TABLE_QUERY) != TSDB_QUERY_TYPE_TABLE_QUERY) {
|
||||
return false;
|
||||
}
|
||||
if (tscQueryTags(pQueryInfo) && tscNumOfExprs(pQueryInfo) == 1){
|
||||
if (tscNumOfExprs(pQueryInfo) == 1){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2046,7 +2047,7 @@ int32_t validateSelectNodeList(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SArray* pS
|
|||
const char* msg1 = "too many items in selection clause";
|
||||
const char* msg2 = "functions or others can not be mixed up";
|
||||
const char* msg3 = "not support query expression";
|
||||
const char* msg4 = "only support distinct one tag";
|
||||
const char* msg4 = "only support distinct one column or tag";
|
||||
const char* msg5 = "invalid function name";
|
||||
|
||||
// too many result columns not support order by in query
|
||||
|
@ -2106,13 +2107,13 @@ int32_t validateSelectNodeList(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SArray* pS
|
|||
}
|
||||
|
||||
if (hasDistinct == true) {
|
||||
if (!isValidDistinctSql(pQueryInfo)) {
|
||||
if (!isValidDistinctSql(pQueryInfo) ) {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg4);
|
||||
}
|
||||
|
||||
pQueryInfo->distinctTag = true;
|
||||
pQueryInfo->distinct = true;
|
||||
}
|
||||
|
||||
|
||||
// there is only one user-defined column in the final result field, add the timestamp column.
|
||||
size_t numOfSrcCols = taosArrayGetSize(pQueryInfo->colList);
|
||||
if ((numOfSrcCols <= 0 || !hasNoneUserDefineExpr(pQueryInfo)) && !tscQueryTags(pQueryInfo) && !tscQueryBlockInfo(pQueryInfo)) {
|
||||
|
@ -3976,8 +3977,10 @@ static int32_t getTablenameCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr*
|
|||
|
||||
static int32_t getColumnQueryCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr, int32_t relOptr) {
|
||||
if (pExpr == NULL) {
|
||||
pQueryInfo->onlyHasTagCond &= true;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
pQueryInfo->onlyHasTagCond &= false;
|
||||
|
||||
if (!tSqlExprIsParentOfLeaf(pExpr)) { // internal node
|
||||
int32_t ret = getColumnQueryCondInfo(pCmd, pQueryInfo, pExpr->pLeft, pExpr->tokenId);
|
||||
|
@ -4104,6 +4107,7 @@ static int32_t checkAndSetJoinCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tS
|
|||
|
||||
static int32_t getJoinCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr) {
|
||||
if (pExpr == NULL) {
|
||||
pQueryInfo->onlyHasTagCond &= true;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -4783,8 +4787,11 @@ static int32_t getTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlE
|
|||
int32_t code = 0;
|
||||
|
||||
if (pExpr == NULL) {
|
||||
pQueryInfo->onlyHasTagCond &= true;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
pQueryInfo->onlyHasTagCond &= false;
|
||||
|
||||
|
||||
if (!tSqlExprIsParentOfLeaf(pExpr)) {
|
||||
if (pExpr->tokenId == TK_OR) {
|
||||
|
@ -4833,11 +4840,13 @@ static int32_t validateJoinExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondExpr
|
|||
|
||||
if (!QUERY_IS_JOIN_QUERY(pQueryInfo->type)) {
|
||||
if (pQueryInfo->numOfTables == 1) {
|
||||
pQueryInfo->onlyHasTagCond &= true;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} else {
|
||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
|
||||
}
|
||||
}
|
||||
pQueryInfo->onlyHasTagCond &= false;
|
||||
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { // for stable join, tag columns
|
||||
|
@ -5150,7 +5159,7 @@ int32_t validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSq
|
|||
if (pExpr == NULL) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
const char* msg1 = "invalid expression";
|
||||
const char* msg2 = "invalid filter expression";
|
||||
|
||||
|
@ -5183,6 +5192,7 @@ int32_t validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSq
|
|||
if ((ret = getTimeRangeFromExpr(&pSql->cmd, pQueryInfo, condExpr.pTimewindow)) != TSDB_CODE_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// 3. get the tag query condition
|
||||
if ((ret = getTagQueryCondExpr(&pSql->cmd, pQueryInfo, &condExpr, pExpr)) != TSDB_CODE_SUCCESS) {
|
||||
|
@ -5492,7 +5502,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
|
|||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
|
||||
|
||||
if (pQueryInfo->distinctTag == true) {
|
||||
if (pQueryInfo->distinct == true) {
|
||||
pQueryInfo->order.order = TSDB_ORDER_ASC;
|
||||
pQueryInfo->order.orderColId = 0;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -7237,7 +7247,7 @@ void tscPrintSelNodeList(SSqlObj* pSql, int32_t subClauseIndex) {
|
|||
}
|
||||
|
||||
tmpLen =
|
||||
sprintf(tmpBuf, "%s(uid:%" PRId64 ", %d)", name, pExpr->base.uid, pExpr->base.colInfo.colId);
|
||||
sprintf(tmpBuf, "%s(uid:%" PRIu64 ", %d)", name, pExpr->base.uid, pExpr->base.colInfo.colId);
|
||||
|
||||
if (tmpLen + offset >= totalBufSize - 1) break;
|
||||
|
||||
|
@ -8113,6 +8123,7 @@ int32_t loadAllTableMeta(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
pTableMeta = calloc(1, maxSize);
|
||||
|
||||
plist = taosArrayInit(4, POINTER_BYTES);
|
||||
|
@ -8128,9 +8139,13 @@ int32_t loadAllTableMeta(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
|
||||
size_t len = strlen(name);
|
||||
memset(pTableMeta, 0, maxSize);
|
||||
taosHashGetClone(tscTableMetaInfo, name, len, NULL, pTableMeta, -1);
|
||||
taosHashGetClone(tscTableMetaMap, name, len, NULL, pTableMeta);
|
||||
|
||||
if (pTableMeta->id.uid > 0) {
|
||||
tscDebug("0x%"PRIx64" retrieve table meta %s from local buf", pSql->self, name);
|
||||
|
||||
// avoid mem leak, may should update pTableMeta
|
||||
void* pVgroupIdList = NULL;
|
||||
if (pTableMeta->tableType == TSDB_CHILD_TABLE) {
|
||||
code = tscCreateTableMetaFromSTableMeta(pTableMeta, name, pSql->pBuf);
|
||||
|
||||
|
@ -8142,23 +8157,34 @@ int32_t loadAllTableMeta(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
}
|
||||
} else if (pTableMeta->tableType == TSDB_SUPER_TABLE) {
|
||||
// the vgroup list of super table is not kept in local buffer, so here need retrieve it from the mnode each time
|
||||
char* t = strdup(name);
|
||||
taosArrayPush(pVgroupList, &t);
|
||||
tscDebug("0x%"PRIx64" try to acquire cached super table %s vgroup id list", pSql->self, name);
|
||||
void* pv = taosCacheAcquireByKey(tscVgroupListBuf, name, len);
|
||||
if (pv == NULL) {
|
||||
char* t = strdup(name);
|
||||
taosArrayPush(pVgroupList, &t);
|
||||
tscDebug("0x%"PRIx64" failed to retrieve stable %s vgroup id list in cache, try fetch from mnode", pSql->self, name);
|
||||
} else {
|
||||
tFilePage* pdata = (tFilePage*) pv;
|
||||
pVgroupIdList = taosArrayInit((size_t) pdata->num, sizeof(int32_t));
|
||||
if (pVgroupIdList == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
taosArrayAddBatch(pVgroupIdList, pdata->data, (int32_t) pdata->num);
|
||||
taosCacheRelease(tscVgroupListBuf, &pv, false);
|
||||
}
|
||||
}
|
||||
|
||||
//STableMeta* pMeta = tscTableMetaDup(pTableMeta);
|
||||
//STableMetaVgroupInfo p = { .pTableMeta = pMeta };
|
||||
|
||||
//const char* px = tNameGetTableName(pname);
|
||||
//taosHashPut(pCmd->pTableMetaMap, px, strlen(px), &p, sizeof(STableMetaVgroupInfo));
|
||||
// avoid mem leak, may should update pTableMeta
|
||||
const char* px = tNameGetTableName(pname);
|
||||
if (taosHashGet(pCmd->pTableMetaMap, px, strlen(px)) == NULL) {
|
||||
if (taosHashGet(pCmd->pTableMetaMap, name, len) == NULL) {
|
||||
STableMeta* pMeta = tscTableMetaDup(pTableMeta);
|
||||
STableMetaVgroupInfo p = { .pTableMeta = pMeta, .pVgroupInfo = NULL};
|
||||
taosHashPut(pCmd->pTableMetaMap, px, strlen(px), &p, sizeof(STableMetaVgroupInfo));
|
||||
STableMetaVgroupInfo tvi = { .pTableMeta = pMeta, .vgroupIdList = pVgroupIdList};
|
||||
taosHashPut(pCmd->pTableMetaMap, name, len, &tvi, sizeof(STableMetaVgroupInfo));
|
||||
}
|
||||
} else { // add to the retrieve table meta array list.
|
||||
} else {
|
||||
// Add to the retrieve table meta array list.
|
||||
// If the tableMeta is missing, the cached vgroup list for the corresponding super table will be ignored.
|
||||
tscDebug("0x%"PRIx64" failed to retrieve table meta %s from local buf", pSql->self, name);
|
||||
|
||||
char* t = strdup(name);
|
||||
taosArrayPush(plist, &t);
|
||||
}
|
||||
|
@ -8272,22 +8298,44 @@ static int32_t doLoadAllTableMeta(SSqlObj* pSql, SQueryInfo* pQueryInfo, SSqlNod
|
|||
strncpy(pTableMetaInfo->aliasName, tNameGetTableName(&pTableMetaInfo->name), tListLen(pTableMetaInfo->aliasName));
|
||||
}
|
||||
|
||||
const char* name = tNameGetTableName(&pTableMetaInfo->name);
|
||||
STableMetaVgroupInfo* p = taosHashGet(pCmd->pTableMetaMap, name, strlen(name));
|
||||
char fname[TSDB_TABLE_FNAME_LEN] = {0};
|
||||
tNameExtractFullName(&pTableMetaInfo->name, fname);
|
||||
STableMetaVgroupInfo* p = taosHashGet(pCmd->pTableMetaMap, fname, strnlen(fname, TSDB_TABLE_FNAME_LEN));
|
||||
|
||||
pTableMetaInfo->pTableMeta = tscTableMetaDup(p->pTableMeta);
|
||||
assert(pTableMetaInfo->pTableMeta != NULL);
|
||||
|
||||
if (p->pVgroupInfo != NULL) {
|
||||
pTableMetaInfo->vgroupList = tscVgroupsInfoDup(p->pVgroupInfo);
|
||||
}
|
||||
if (p->vgroupIdList != NULL) {
|
||||
size_t s = taosArrayGetSize(p->vgroupIdList);
|
||||
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
size_t vgroupsz = sizeof(SVgroupInfo) * s + sizeof(SVgroupsInfo);
|
||||
pTableMetaInfo->vgroupList = calloc(1, vgroupsz);
|
||||
if (pTableMetaInfo->vgroupList == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
pTableMetaInfo->vgroupList->numOfVgroups = (int32_t) s;
|
||||
for(int32_t j = 0; j < s; ++j) {
|
||||
int32_t* id = taosArrayGet(p->vgroupIdList, j);
|
||||
|
||||
// check if current buffer contains the vgroup info. If not, add it
|
||||
SNewVgroupInfo existVgroupInfo = {.inUse = -1,};
|
||||
taosHashGetClone(tscVgroupMap, id, sizeof(*id), NULL, &existVgroupInfo);
|
||||
|
||||
assert(existVgroupInfo.inUse >= 0);
|
||||
SVgroupInfo *pVgroup = &pTableMetaInfo->vgroupList->vgroups[j];
|
||||
|
||||
pVgroup->numOfEps = existVgroupInfo.numOfEps;
|
||||
pVgroup->vgId = existVgroupInfo.vgId;
|
||||
for (int32_t k = 0; k < existVgroupInfo.numOfEps; ++k) {
|
||||
pVgroup->epAddr[k].port = existVgroupInfo.ep[k].port;
|
||||
pVgroup->epAddr[k].fqdn = strndup(existVgroupInfo.ep[k].fqdn, TSDB_FQDN_LEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
return code;
|
||||
}
|
||||
|
||||
static STableMeta* extractTempTableMetaFromSubquery(SQueryInfo* pUpstream) {
|
||||
|
@ -8565,7 +8613,7 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
|
|||
if (validateGroupbyNode(pQueryInfo, pSqlNode->pGroupby, pCmd) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
pQueryInfo->onlyHasTagCond = true;
|
||||
// set where info
|
||||
if (pSqlNode->pWhere != NULL) {
|
||||
if (validateWhereNode(pQueryInfo, &pSqlNode->pWhere, pSql) != TSDB_CODE_SUCCESS) {
|
||||
|
@ -8588,6 +8636,10 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
|
|||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
if (isSTable && tscQueryTags(pQueryInfo) && pQueryInfo->distinct && !pQueryInfo->onlyHasTagCond) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
// parse the window_state
|
||||
if (validateStateWindowNode(pCmd, pQueryInfo, pSqlNode, isSTable) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
|
|
|
@ -157,7 +157,7 @@ static void tscUpdateVgroupInfo(SSqlObj *pSql, SRpcEpSet *pEpSet) {
|
|||
assert(vgId > 0);
|
||||
|
||||
SNewVgroupInfo vgroupInfo = {.vgId = -1};
|
||||
taosHashGetClone(tscVgroupMap, &vgId, sizeof(vgId), NULL, &vgroupInfo, sizeof(SNewVgroupInfo));
|
||||
taosHashGetClone(tscVgroupMap, &vgId, sizeof(vgId), NULL, &vgroupInfo);
|
||||
assert(vgroupInfo.numOfEps > 0 && vgroupInfo.vgId > 0);
|
||||
|
||||
tscDebug("before: Endpoint in use:%d, numOfEps:%d", vgroupInfo.inUse, vgroupInfo.numOfEps);
|
||||
|
@ -344,6 +344,7 @@ void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcEpSet *pEpSet) {
|
|||
rpcFreeCont(rpcMsg->pCont);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(pSql->self == handle);
|
||||
|
||||
STscObj *pObj = pSql->pTscObj;
|
||||
|
@ -389,33 +390,40 @@ void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcEpSet *pEpSet) {
|
|||
pSql->cmd.insertParam.schemaAttached = 1;
|
||||
}
|
||||
|
||||
// single table query error need to be handled here.
|
||||
if ((cmd == TSDB_SQL_SELECT || cmd == TSDB_SQL_UPDATE_TAGS_VAL) &&
|
||||
(rpcMsg->code == TSDB_CODE_TDB_INVALID_TABLE_ID ||
|
||||
rpcMsg->code == TSDB_CODE_VND_INVALID_VGROUP_ID ||
|
||||
rpcMsg->code == TSDB_CODE_RPC_NETWORK_UNAVAIL ||
|
||||
(((rpcMsg->code == TSDB_CODE_TDB_INVALID_TABLE_ID || // change the retry procedure
|
||||
rpcMsg->code == TSDB_CODE_VND_INVALID_VGROUP_ID)) ||
|
||||
rpcMsg->code == TSDB_CODE_RPC_NETWORK_UNAVAIL || // change the retry procedure
|
||||
rpcMsg->code == TSDB_CODE_APP_NOT_READY)) {
|
||||
|
||||
pSql->retry++;
|
||||
tscWarn("0x%"PRIx64" it shall renew table meta, code:%s, retry:%d", pSql->self, tstrerror(rpcMsg->code), pSql->retry);
|
||||
|
||||
pSql->res.code = rpcMsg->code; // keep the previous error code
|
||||
if (pSql->retry > pSql->maxRetry) {
|
||||
tscError("0x%"PRIx64" max retry %d reached, give up", pSql->self, pSql->maxRetry);
|
||||
} else {
|
||||
// wait for a little bit moment and then retry
|
||||
// todo do not sleep in rpc callback thread, add this process into queueu to process
|
||||
if (rpcMsg->code == TSDB_CODE_APP_NOT_READY || rpcMsg->code == TSDB_CODE_VND_INVALID_VGROUP_ID) {
|
||||
int32_t duration = getWaitingTimeInterval(pSql->retry);
|
||||
taosMsleep(duration);
|
||||
}
|
||||
if (TSDB_QUERY_HAS_TYPE(pQueryInfo->type, (TSDB_QUERY_TYPE_STABLE_SUBQUERY | TSDB_QUERY_TYPE_SUBQUERY |
|
||||
TSDB_QUERY_TYPE_TAG_FILTER_QUERY)) &&
|
||||
!TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_PROJECTION_QUERY)) {
|
||||
// do nothing in case of super table subquery
|
||||
} else {
|
||||
pSql->retry += 1;
|
||||
tscWarn("0x%" PRIx64 " it shall renew table meta, code:%s, retry:%d", pSql->self, tstrerror(rpcMsg->code), pSql->retry);
|
||||
|
||||
pSql->retryReason = rpcMsg->code;
|
||||
rpcMsg->code = tscRenewTableMeta(pSql, 0);
|
||||
// if there is an error occurring, proceed to the following error handling procedure.
|
||||
if (rpcMsg->code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
|
||||
taosReleaseRef(tscObjRef, handle);
|
||||
rpcFreeCont(rpcMsg->pCont);
|
||||
return;
|
||||
pSql->res.code = rpcMsg->code; // keep the previous error code
|
||||
if (pSql->retry > pSql->maxRetry) {
|
||||
tscError("0x%" PRIx64 " max retry %d reached, give up", pSql->self, pSql->maxRetry);
|
||||
} else {
|
||||
// wait for a little bit moment and then retry
|
||||
// todo do not sleep in rpc callback thread, add this process into queue to process
|
||||
if (rpcMsg->code == TSDB_CODE_APP_NOT_READY || rpcMsg->code == TSDB_CODE_VND_INVALID_VGROUP_ID) {
|
||||
int32_t duration = getWaitingTimeInterval(pSql->retry);
|
||||
taosMsleep(duration);
|
||||
}
|
||||
|
||||
pSql->retryReason = rpcMsg->code;
|
||||
rpcMsg->code = tscRenewTableMeta(pSql, 0);
|
||||
// if there is an error occurring, proceed to the following error handling procedure.
|
||||
if (rpcMsg->code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
|
||||
taosReleaseRef(tscObjRef, handle);
|
||||
rpcFreeCont(rpcMsg->pCont);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -614,7 +622,7 @@ int tscBuildSubmitMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
|||
pSql->cmd.msgType = TSDB_MSG_TYPE_SUBMIT;
|
||||
|
||||
SNewVgroupInfo vgroupInfo = {0};
|
||||
taosHashGetClone(tscVgroupMap, &pTableMeta->vgId, sizeof(pTableMeta->vgId), NULL, &vgroupInfo, sizeof(SNewVgroupInfo));
|
||||
taosHashGetClone(tscVgroupMap, &pTableMeta->vgId, sizeof(pTableMeta->vgId), NULL, &vgroupInfo);
|
||||
tscDumpEpSetFromVgroupInfo(&pSql->epSet, &vgroupInfo);
|
||||
|
||||
tscDebug("0x%"PRIx64" submit msg built, numberOfEP:%d", pSql->self, pSql->epSet.numOfEps);
|
||||
|
@ -632,7 +640,7 @@ static int32_t tscEstimateQueryMsgSize(SSqlObj *pSql) {
|
|||
SQueryInfo *pQueryInfo = tscGetQueryInfo(pCmd);
|
||||
|
||||
int32_t srcColListSize = (int32_t)(taosArrayGetSize(pQueryInfo->colList) * sizeof(SColumnInfo));
|
||||
|
||||
int32_t srcColFilterSize = tscGetColFilterSerializeLen(pQueryInfo);
|
||||
size_t numOfExprs = tscNumOfExprs(pQueryInfo);
|
||||
int32_t exprSize = (int32_t)(sizeof(SSqlExpr) * numOfExprs * 2);
|
||||
|
||||
|
@ -653,7 +661,7 @@ static int32_t tscEstimateQueryMsgSize(SSqlObj *pSql) {
|
|||
tableSerialize = totalTables * sizeof(STableIdInfo);
|
||||
}
|
||||
|
||||
return MIN_QUERY_MSG_PKT_SIZE + minMsgSize() + sizeof(SQueryTableMsg) + srcColListSize + exprSize + tsBufSize +
|
||||
return MIN_QUERY_MSG_PKT_SIZE + minMsgSize() + sizeof(SQueryTableMsg) + srcColListSize + srcColFilterSize + exprSize + tsBufSize +
|
||||
tableSerialize + sqlLen + 4096 + pQueryInfo->bufLen;
|
||||
}
|
||||
|
||||
|
@ -687,7 +695,7 @@ static char *doSerializeTableInfo(SQueryTableMsg *pQueryMsg, SSqlObj *pSql, STab
|
|||
vgId = pTableMeta->vgId;
|
||||
|
||||
SNewVgroupInfo vgroupInfo = {0};
|
||||
taosHashGetClone(tscVgroupMap, &pTableMeta->vgId, sizeof(pTableMeta->vgId), NULL, &vgroupInfo, sizeof(SNewVgroupInfo));
|
||||
taosHashGetClone(tscVgroupMap, &pTableMeta->vgId, sizeof(pTableMeta->vgId), NULL, &vgroupInfo);
|
||||
tscDumpEpSetFromVgroupInfo(&pSql->epSet, &vgroupInfo);
|
||||
}
|
||||
|
||||
|
@ -1582,7 +1590,7 @@ int tscBuildUpdateTagMsg(SSqlObj* pSql, SSqlInfo *pInfo) {
|
|||
STableMeta *pTableMeta = tscGetMetaInfo(pQueryInfo, 0)->pTableMeta;
|
||||
|
||||
SNewVgroupInfo vgroupInfo = {.vgId = -1};
|
||||
taosHashGetClone(tscVgroupMap, &pTableMeta->vgId, sizeof(pTableMeta->vgId), NULL, &vgroupInfo, sizeof(SNewVgroupInfo));
|
||||
taosHashGetClone(tscVgroupMap, &pTableMeta->vgId, sizeof(pTableMeta->vgId), NULL, &vgroupInfo);
|
||||
assert(vgroupInfo.vgId > 0);
|
||||
|
||||
tscDumpEpSetFromVgroupInfo(&pSql->epSet, &vgroupInfo);
|
||||
|
@ -1809,34 +1817,6 @@ int tscBuildConnectMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int tscBuildTableMetaMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
||||
#if 0
|
||||
SSqlCmd *pCmd = &pSql->cmd;
|
||||
SQueryInfo *pQueryInfo = tscGetQueryInfo(&pSql->cmd);
|
||||
|
||||
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
STableInfoMsg *pInfoMsg = (STableInfoMsg *)pCmd->payload;
|
||||
|
||||
int32_t code = tNameExtractFullName(&pTableMetaInfo->name, pInfoMsg->tableFname);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
pInfoMsg->createFlag = htons(pSql->cmd.autoCreated ? 1 : 0);
|
||||
|
||||
char *pMsg = (char *)pInfoMsg + sizeof(STableInfoMsg);
|
||||
|
||||
if (pCmd->autoCreated && pCmd->tagData.dataLen != 0) {
|
||||
pMsg = serializeTagData(&pCmd->tagData, pMsg);
|
||||
}
|
||||
|
||||
pCmd->payloadLen = (int32_t)(pMsg - (char*)pInfoMsg);
|
||||
pCmd->msgType = TSDB_MSG_TYPE_CM_TABLE_META;
|
||||
#endif
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* multi table meta req pkg format:
|
||||
* |SMultiTableInfoMsg | tableId0 | tableId1 | tableId2 | ......
|
||||
|
@ -1996,20 +1976,17 @@ static int32_t tableMetaMsgConvert(STableMetaMsg* pMetaMsg) {
|
|||
}
|
||||
|
||||
// update the vgroupInfo if needed
|
||||
static void doUpdateVgroupInfo(STableMeta *pTableMeta, SVgroupMsg *pVgroupMsg) {
|
||||
if (pTableMeta->vgId > 0) {
|
||||
int32_t vgId = pTableMeta->vgId;
|
||||
assert(pTableMeta->tableType != TSDB_SUPER_TABLE);
|
||||
static void doUpdateVgroupInfo(int32_t vgId, SVgroupMsg *pVgroupMsg) {
|
||||
assert(vgId > 0);
|
||||
|
||||
SNewVgroupInfo vgroupInfo = {.inUse = -1};
|
||||
taosHashGetClone(tscVgroupMap, &vgId, sizeof(vgId), NULL, &vgroupInfo, sizeof(SNewVgroupInfo));
|
||||
SNewVgroupInfo vgroupInfo = {.inUse = -1};
|
||||
taosHashGetClone(tscVgroupMap, &vgId, sizeof(vgId), NULL, &vgroupInfo);
|
||||
|
||||
// vgroup info exists, compare with it
|
||||
if (((vgroupInfo.inUse >= 0) && !vgroupInfoIdentical(&vgroupInfo, pVgroupMsg)) || (vgroupInfo.inUse < 0)) {
|
||||
vgroupInfo = createNewVgroupInfo(pVgroupMsg);
|
||||
taosHashPut(tscVgroupMap, &vgId, sizeof(vgId), &vgroupInfo, sizeof(vgroupInfo));
|
||||
tscDebug("add new VgroupInfo, vgId:%d, total cached:%d", vgId, (int32_t) taosHashGetSize(tscVgroupMap));
|
||||
}
|
||||
// vgroup info exists, compare with it
|
||||
if (((vgroupInfo.inUse >= 0) && !vgroupInfoIdentical(&vgroupInfo, pVgroupMsg)) || (vgroupInfo.inUse < 0)) {
|
||||
vgroupInfo = createNewVgroupInfo(pVgroupMsg);
|
||||
taosHashPut(tscVgroupMap, &vgId, sizeof(vgId), &vgroupInfo, sizeof(vgroupInfo));
|
||||
tscDebug("add/update new VgroupInfo, vgId:%d, total cached:%d", vgId, (int32_t) taosHashGetSize(tscVgroupMap));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2022,18 +1999,18 @@ static void doAddTableMetaToLocalBuf(STableMeta* pTableMeta, STableMetaMsg* pMet
|
|||
if (updateSTable) {
|
||||
STableMeta* pSupTableMeta = createSuperTableMeta(pMetaMsg);
|
||||
uint32_t size = tscGetTableMetaSize(pSupTableMeta);
|
||||
int32_t code = taosHashPut(tscTableMetaInfo, pTableMeta->sTableName, len, pSupTableMeta, size);
|
||||
int32_t code = taosHashPut(tscTableMetaMap, pTableMeta->sTableName, len, pSupTableMeta, size);
|
||||
assert(code == TSDB_CODE_SUCCESS);
|
||||
|
||||
tfree(pSupTableMeta);
|
||||
}
|
||||
|
||||
CChildTableMeta* cMeta = tscCreateChildMeta(pTableMeta);
|
||||
taosHashPut(tscTableMetaInfo, pMetaMsg->tableFname, strlen(pMetaMsg->tableFname), cMeta, sizeof(CChildTableMeta));
|
||||
taosHashPut(tscTableMetaMap, pMetaMsg->tableFname, strlen(pMetaMsg->tableFname), cMeta, sizeof(CChildTableMeta));
|
||||
tfree(cMeta);
|
||||
} else {
|
||||
uint32_t s = tscGetTableMetaSize(pTableMeta);
|
||||
taosHashPut(tscTableMetaInfo, pMetaMsg->tableFname, strlen(pMetaMsg->tableFname), pTableMeta, s);
|
||||
taosHashPut(tscTableMetaMap, pMetaMsg->tableFname, strlen(pMetaMsg->tableFname), pTableMeta, s);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2058,7 +2035,9 @@ int tscProcessTableMetaRsp(SSqlObj *pSql) {
|
|||
assert(strncmp(pMetaMsg->tableFname, name, tListLen(pMetaMsg->tableFname)) == 0);
|
||||
|
||||
doAddTableMetaToLocalBuf(pTableMeta, pMetaMsg, true);
|
||||
doUpdateVgroupInfo(pTableMeta, &pMetaMsg->vgroup);
|
||||
if (pTableMeta->tableType != TSDB_SUPER_TABLE) {
|
||||
doUpdateVgroupInfo(pTableMeta->vgId, &pMetaMsg->vgroup);
|
||||
}
|
||||
|
||||
tscDebug("0x%"PRIx64" recv table meta, uid:%" PRIu64 ", tid:%d, name:%s, numOfCols:%d, numOfTags:%d", pSql->self,
|
||||
pTableMeta->id.uid, pTableMeta->id.tid, tNameGetTableName(&pTableMetaInfo->name), pTableMeta->tableInfo.numOfColumns,
|
||||
|
@ -2068,6 +2047,37 @@ int tscProcessTableMetaRsp(SSqlObj *pSql) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static SArray* createVgroupIdListFromMsg(char* pMsg, SHashObj* pSet, char* name, int32_t* size, uint64_t id) {
|
||||
SVgroupsMsg *pVgroupMsg = (SVgroupsMsg *)pMsg;
|
||||
|
||||
pVgroupMsg->numOfVgroups = htonl(pVgroupMsg->numOfVgroups);
|
||||
*size = (int32_t)(sizeof(SVgroupMsg) * pVgroupMsg->numOfVgroups + sizeof(SVgroupsMsg));
|
||||
|
||||
SArray* vgroupIdList = taosArrayInit(pVgroupMsg->numOfVgroups, sizeof(int32_t));
|
||||
|
||||
if (pVgroupMsg->numOfVgroups <= 0) {
|
||||
tscDebug("0x%" PRIx64 " empty vgroup id list, no corresponding tables for stable:%s", id, name);
|
||||
} else {
|
||||
// just init, no need to lock
|
||||
for (int32_t j = 0; j < pVgroupMsg->numOfVgroups; ++j) {
|
||||
SVgroupMsg *vmsg = &pVgroupMsg->vgroups[j];
|
||||
vmsg->vgId = htonl(vmsg->vgId);
|
||||
for (int32_t k = 0; k < vmsg->numOfEps; ++k) {
|
||||
vmsg->epAddr[k].port = htons(vmsg->epAddr[k].port);
|
||||
}
|
||||
|
||||
taosArrayPush(vgroupIdList, &vmsg->vgId);
|
||||
|
||||
if (taosHashGet(pSet, &vmsg->vgId, sizeof(vmsg->vgId)) == NULL) {
|
||||
taosHashPut(pSet, &vmsg->vgId, sizeof(vmsg->vgId), "", 0);
|
||||
doUpdateVgroupInfo(vmsg->vgId, vmsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return vgroupIdList;
|
||||
}
|
||||
|
||||
static SVgroupsInfo* createVgroupInfoFromMsg(char* pMsg, int32_t* size, uint64_t id) {
|
||||
SVgroupsMsg *pVgroupMsg = (SVgroupsMsg *)pMsg;
|
||||
pVgroupMsg->numOfVgroups = htonl(pVgroupMsg->numOfVgroups);
|
||||
|
@ -2092,24 +2102,14 @@ static SVgroupsInfo* createVgroupInfoFromMsg(char* pMsg, int32_t* size, uint64_t
|
|||
vmsg->epAddr[k].port = htons(vmsg->epAddr[k].port);
|
||||
}
|
||||
|
||||
SNewVgroupInfo newVi = createNewVgroupInfo(vmsg);
|
||||
pVgroup->numOfEps = newVi.numOfEps;
|
||||
pVgroup->vgId = newVi.vgId;
|
||||
pVgroup->numOfEps = vmsg->numOfEps;
|
||||
pVgroup->vgId = vmsg->vgId;
|
||||
for (int32_t k = 0; k < vmsg->numOfEps; ++k) {
|
||||
pVgroup->epAddr[k].port = newVi.ep[k].port;
|
||||
pVgroup->epAddr[k].fqdn = strndup(newVi.ep[k].fqdn, TSDB_FQDN_LEN);
|
||||
pVgroup->epAddr[k].port = vmsg->epAddr[k].port;
|
||||
pVgroup->epAddr[k].fqdn = strndup(vmsg->epAddr[k].fqdn, TSDB_FQDN_LEN);
|
||||
}
|
||||
|
||||
// check if current buffer contains the vgroup info.
|
||||
// If not, add it
|
||||
SNewVgroupInfo existVgroupInfo = {.inUse = -1};
|
||||
taosHashGetClone(tscVgroupMap, &newVi.vgId, sizeof(newVi.vgId), NULL, &existVgroupInfo, sizeof(SNewVgroupInfo));
|
||||
|
||||
if (((existVgroupInfo.inUse >= 0) && !vgroupInfoIdentical(&existVgroupInfo, vmsg)) ||
|
||||
(existVgroupInfo.inUse < 0)) { // vgroup info exists, compare with it
|
||||
taosHashPut(tscVgroupMap, &newVi.vgId, sizeof(newVi.vgId), &newVi, sizeof(newVi));
|
||||
tscDebug("0x%" PRIx64 " add new VgroupInfo, vgId:%d, total cached:%d", id, newVi.vgId, (int32_t)taosHashGetSize(tscVgroupMap));
|
||||
}
|
||||
doUpdateVgroupInfo(pVgroup->vgId, vmsg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2187,6 +2187,8 @@ int tscProcessMultiTableMetaRsp(SSqlObj *pSql) {
|
|||
|
||||
char* buf = NULL;
|
||||
char* pMsg = pMultiMeta->meta;
|
||||
|
||||
// decompresss the message payload
|
||||
if (pMultiMeta->compressed) {
|
||||
buf = malloc(pMultiMeta->rawLen - sizeof(SMultiTableMeta));
|
||||
int32_t len = tsDecompressString(pMultiMeta->meta, pMultiMeta->contLen - sizeof(SMultiTableMeta), 1,
|
||||
|
@ -2219,15 +2221,13 @@ int tscProcessMultiTableMetaRsp(SSqlObj *pSql) {
|
|||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
SName sn = {0};
|
||||
tNameFromString(&sn, pMetaMsg->tableFname, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE);
|
||||
|
||||
if (pMultiMeta->metaClone == 1 || pTableMeta->tableType == TSDB_SUPER_TABLE) {
|
||||
STableMetaVgroupInfo p = {.pTableMeta = pTableMeta,};
|
||||
size_t keyLen = strnlen(pMetaMsg->tableFname, TSDB_TABLE_FNAME_LEN);
|
||||
void* t = taosHashGet(pParentCmd->pTableMetaMap, pMetaMsg->tableFname, keyLen);
|
||||
assert(t == NULL);
|
||||
|
||||
const char* tableName = tNameGetTableName(&sn);
|
||||
size_t keyLen = strlen(tableName);
|
||||
taosHashPut(pParentCmd->pTableMetaMap, tableName, keyLen, &p, sizeof(STableMetaVgroupInfo));
|
||||
taosHashPut(pParentCmd->pTableMetaMap, pMetaMsg->tableFname, keyLen, &p, sizeof(STableMetaVgroupInfo));
|
||||
} else {
|
||||
freeMeta = true;
|
||||
}
|
||||
|
@ -2245,7 +2245,7 @@ int tscProcessMultiTableMetaRsp(SSqlObj *pSql) {
|
|||
// for each vgroup, only update the information once.
|
||||
int64_t vgId = pMetaMsg->vgroup.vgId;
|
||||
if (pTableMeta->tableType != TSDB_SUPER_TABLE && taosHashGet(pSet, &vgId, sizeof(vgId)) == NULL) {
|
||||
doUpdateVgroupInfo(pTableMeta, &pMetaMsg->vgroup);
|
||||
doUpdateVgroupInfo((int32_t) vgId, &pMetaMsg->vgroup);
|
||||
taosHashPut(pSet, &vgId, sizeof(vgId), "", 0);
|
||||
}
|
||||
|
||||
|
@ -2256,18 +2256,33 @@ int tscProcessMultiTableMetaRsp(SSqlObj *pSql) {
|
|||
}
|
||||
|
||||
for(int32_t i = 0; i < pMultiMeta->numOfVgroup; ++i) {
|
||||
char* name = pMsg;
|
||||
pMsg += TSDB_TABLE_NAME_LEN;
|
||||
char fname[TSDB_TABLE_FNAME_LEN] = {0};
|
||||
tstrncpy(fname, pMsg, TSDB_TABLE_FNAME_LEN);
|
||||
size_t len = strnlen(fname, TSDB_TABLE_FNAME_LEN);
|
||||
|
||||
STableMetaVgroupInfo* p = taosHashGet(pParentCmd->pTableMetaMap, name, strnlen(name, TSDB_TABLE_NAME_LEN));
|
||||
pMsg += TSDB_TABLE_FNAME_LEN;
|
||||
|
||||
STableMetaVgroupInfo* p = taosHashGet(pParentCmd->pTableMetaMap, fname, len);
|
||||
assert(p != NULL);
|
||||
|
||||
int32_t size = 0;
|
||||
if (p->pVgroupInfo!= NULL) {
|
||||
tscVgroupInfoClear(p->pVgroupInfo);
|
||||
//tfree(p->pTableMeta);
|
||||
if (p->vgroupIdList!= NULL) {
|
||||
taosArrayDestroy(p->vgroupIdList);
|
||||
}
|
||||
p->pVgroupInfo = createVgroupInfoFromMsg(pMsg, &size, pSql->self);
|
||||
|
||||
p->vgroupIdList = createVgroupIdListFromMsg(pMsg, pSet, fname, &size, pSql->self);
|
||||
|
||||
int32_t numOfVgId = (int32_t) taosArrayGetSize(p->vgroupIdList);
|
||||
int32_t s = sizeof(tFilePage) + numOfVgId * sizeof(int32_t);
|
||||
|
||||
tFilePage* idList = calloc(1, s);
|
||||
idList->num = numOfVgId;
|
||||
memcpy(idList->data, TARRAY_GET_START(p->vgroupIdList), numOfVgId * sizeof(int32_t));
|
||||
|
||||
void* idListInst = taosCachePut(tscVgroupListBuf, fname, len, idList, s, 5000);
|
||||
taosCacheRelease(tscVgroupListBuf, (void*) &idListInst, false);
|
||||
|
||||
tfree(idList);
|
||||
pMsg += size;
|
||||
}
|
||||
|
||||
|
@ -2332,14 +2347,18 @@ int tscProcessSTableVgroupRsp(SSqlObj *pSql) {
|
|||
SSqlCmd* pCmd = &parent->cmd;
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfo(pCmd);
|
||||
|
||||
char fName[TSDB_TABLE_FNAME_LEN] = {0};
|
||||
for(int32_t i = 0; i < pStableVgroup->numOfTables; ++i) {
|
||||
char* name = pMsg;
|
||||
pMsg += TSDB_TABLE_NAME_LEN;
|
||||
pMsg += TSDB_TABLE_FNAME_LEN;
|
||||
|
||||
STableMetaInfo *pInfo = NULL;
|
||||
for(int32_t j = 0; j < pQueryInfo->numOfTables; ++j) {
|
||||
STableMetaInfo *pInfo1 = tscGetTableMetaInfoFromCmd(pCmd, j);
|
||||
if (strcmp(name, tNameGetTableName(&pInfo1->name)) != 0) {
|
||||
memset(fName, 0, tListLen(fName));
|
||||
|
||||
tNameExtractFullName(&pInfo1->name, fName);
|
||||
if (strcmp(name, fName) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2499,24 +2518,20 @@ int tscProcessUseDbRsp(SSqlObj *pSql) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
//todo only invalid the buffered data that belongs to dropped databases
|
||||
int tscProcessDropDbRsp(SSqlObj *pSql) {
|
||||
//TODO LOCK DB WHEN MODIFY IT
|
||||
//pSql->pTscObj->db[0] = 0;
|
||||
|
||||
taosHashClear(tscTableMetaInfo);
|
||||
taosHashClear(tscTableMetaMap);
|
||||
taosHashClear(tscVgroupMap);
|
||||
taosCacheEmpty(tscVgroupListBuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tscProcessDropTableRsp(SSqlObj *pSql) {
|
||||
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(&pSql->cmd, 0);
|
||||
|
||||
//The cached tableMeta is expired in this case, so clean it in hash table
|
||||
char name[TSDB_TABLE_FNAME_LEN] = {0};
|
||||
tNameExtractFullName(&pTableMetaInfo->name, name);
|
||||
|
||||
taosHashRemove(tscTableMetaInfo, name, strnlen(name, TSDB_TABLE_FNAME_LEN));
|
||||
tscDebug("0x%"PRIx64" remove table meta after drop table:%s, numOfRemain:%d", pSql->self, name, (int32_t) taosHashGetSize(tscTableMetaInfo));
|
||||
|
||||
tscRemoveTableMetaBuf(pTableMetaInfo, pSql->self);
|
||||
tfree(pTableMetaInfo->pTableMeta);
|
||||
return 0;
|
||||
}
|
||||
|
@ -2530,11 +2545,11 @@ int tscProcessAlterTableMsgRsp(SSqlObj *pSql) {
|
|||
tscDebug("0x%"PRIx64" remove tableMeta in hashMap after alter-table: %s", pSql->self, name);
|
||||
|
||||
bool isSuperTable = UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo);
|
||||
taosHashRemove(tscTableMetaInfo, name, strnlen(name, TSDB_TABLE_FNAME_LEN));
|
||||
taosHashRemove(tscTableMetaMap, name, strnlen(name, TSDB_TABLE_FNAME_LEN));
|
||||
tfree(pTableMetaInfo->pTableMeta);
|
||||
|
||||
if (isSuperTable) { // if it is a super table, iterate the hashTable and remove all the childTableMeta
|
||||
taosHashClear(tscTableMetaInfo);
|
||||
taosHashClear(tscTableMetaMap);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -2801,7 +2816,7 @@ int32_t tscGetTableMetaImpl(SSqlObj* pSql, STableMetaInfo *pTableMetaInfo, bool
|
|||
tNameExtractFullName(&pTableMetaInfo->name, name);
|
||||
|
||||
size_t len = strlen(name);
|
||||
taosHashGetClone(tscTableMetaInfo, name, len, NULL, pTableMetaInfo->pTableMeta, -1);
|
||||
taosHashGetClone(tscTableMetaMap, name, len, NULL, pTableMetaInfo->pTableMeta);
|
||||
|
||||
// TODO resize the tableMeta
|
||||
assert(size < 80 * TSDB_MAX_COLUMNS);
|
||||
|
@ -2892,6 +2907,10 @@ int32_t tscGetUdfFromNode(SSqlObj *pSql, SQueryInfo* pQueryInfo) {
|
|||
return code;
|
||||
}
|
||||
|
||||
static void freeElem(void* p) {
|
||||
tfree(*(char**)p);
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve table meta from mnode, and then update the local table meta hashmap.
|
||||
* @param pSql sql object
|
||||
|
@ -2899,7 +2918,7 @@ int32_t tscGetUdfFromNode(SSqlObj *pSql, SQueryInfo* pQueryInfo) {
|
|||
* @return status code
|
||||
*/
|
||||
int tscRenewTableMeta(SSqlObj *pSql, int32_t tableIndex) {
|
||||
SSqlCmd *pCmd = &pSql->cmd;
|
||||
SSqlCmd* pCmd = &pSql->cmd;
|
||||
|
||||
SQueryInfo *pQueryInfo = tscGetQueryInfo(pCmd);
|
||||
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, tableIndex);
|
||||
|
@ -2913,15 +2932,26 @@ int tscRenewTableMeta(SSqlObj *pSql, int32_t tableIndex) {
|
|||
|
||||
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
|
||||
if (pTableMeta) {
|
||||
tscDebug("0x%"PRIx64" update table meta:%s, old meta numOfTags:%d, numOfCols:%d, uid:%" PRId64, pSql->self, name,
|
||||
tscDebug("0x%"PRIx64" update table meta:%s, old meta numOfTags:%d, numOfCols:%d, uid:%" PRIu64, pSql->self, name,
|
||||
tscGetNumOfTags(pTableMeta), tscGetNumOfColumns(pTableMeta), pTableMeta->id.uid);
|
||||
}
|
||||
|
||||
// remove stored tableMeta info in hash table
|
||||
size_t len = strlen(name);
|
||||
taosHashRemove(tscTableMetaInfo, name, len);
|
||||
tscRemoveTableMetaBuf(pTableMetaInfo, pSql->self);
|
||||
|
||||
return getTableMetaFromMnode(pSql, pTableMetaInfo, false);
|
||||
pCmd->pTableMetaMap = tscCleanupTableMetaMap(pCmd->pTableMetaMap);
|
||||
pCmd->pTableMetaMap = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
|
||||
|
||||
SArray* pNameList = taosArrayInit(1, POINTER_BYTES);
|
||||
SArray* vgroupList = taosArrayInit(1, POINTER_BYTES);
|
||||
|
||||
char* n = strdup(name);
|
||||
taosArrayPush(pNameList, &n);
|
||||
code = getMultiTableMetaFromMnode(pSql, pNameList, vgroupList, NULL, tscTableMetaCallBack, true);
|
||||
taosArrayDestroyEx(pNameList, freeElem);
|
||||
taosArrayDestroyEx(vgroupList, freeElem);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static bool allVgroupInfoRetrieved(SQueryInfo* pQueryInfo) {
|
||||
|
@ -2971,8 +3001,6 @@ int tscGetSTableVgroupInfo(SSqlObj *pSql, SQueryInfo* pQueryInfo) {
|
|||
tscDebug("0x%"PRIx64" svgroupRid from %" PRId64 " to %" PRId64 , pSql->self, pSql->svgroupRid, pNew->self);
|
||||
|
||||
pSql->svgroupRid = pNew->self;
|
||||
|
||||
|
||||
tscDebug("0x%"PRIx64" new sqlObj:%p to get vgroupInfo, numOfTables:%d", pSql->self, pNew, pNewQueryInfo->numOfTables);
|
||||
|
||||
pNew->fp = tscTableMetaCallBack;
|
||||
|
@ -3015,7 +3043,6 @@ void tscInitMsgsFp() {
|
|||
|
||||
tscBuildMsg[TSDB_SQL_CONNECT] = tscBuildConnectMsg;
|
||||
tscBuildMsg[TSDB_SQL_USE_DB] = tscBuildUseDbMsg;
|
||||
// tscBuildMsg[TSDB_SQL_META] = tscBuildTableMetaMsg;
|
||||
tscBuildMsg[TSDB_SQL_STABLEVGROUP] = tscBuildSTableVgroupMsg;
|
||||
tscBuildMsg[TSDB_SQL_RETRIEVE_FUNC] = tscBuildRetrieveFuncMsg;
|
||||
|
||||
|
|
|
@ -206,7 +206,7 @@ static void tscProcessStreamQueryCallback(void *param, TAOS_RES *tres, int numOf
|
|||
char name[TSDB_TABLE_FNAME_LEN] = {0};
|
||||
tNameExtractFullName(&pTableMetaInfo->name, name);
|
||||
|
||||
taosHashRemove(tscTableMetaInfo, name, strnlen(name, TSDB_TABLE_FNAME_LEN));
|
||||
taosHashRemove(tscTableMetaMap, name, strnlen(name, TSDB_TABLE_FNAME_LEN));
|
||||
|
||||
tfree(pTableMetaInfo->pTableMeta);
|
||||
|
||||
|
|
|
@ -2704,8 +2704,7 @@ void tscHandleSubqueryError(SRetrieveSupport *trsupport, SSqlObj *pSql, int numO
|
|||
tstrerror(pParentSql->res.code));
|
||||
|
||||
// release allocated resource
|
||||
tscDestroyGlobalMergerEnv(trsupport->pExtMemBuffer, trsupport->pOrderDescriptor,
|
||||
pState->numOfSub);
|
||||
tscDestroyGlobalMergerEnv(trsupport->pExtMemBuffer, trsupport->pOrderDescriptor, pState->numOfSub);
|
||||
|
||||
tscFreeRetrieveSup(pSql);
|
||||
|
||||
|
@ -2713,7 +2712,35 @@ void tscHandleSubqueryError(SRetrieveSupport *trsupport, SSqlObj *pSql, int numO
|
|||
SQueryInfo *pQueryInfo = tscGetQueryInfo(&pParentSql->cmd);
|
||||
|
||||
if (!TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_JOIN_SEC_STAGE)) {
|
||||
(*pParentSql->fp)(pParentSql->param, pParentSql, pParentSql->res.code);
|
||||
|
||||
int32_t code = pParentSql->res.code;
|
||||
if ((code == TSDB_CODE_TDB_INVALID_TABLE_ID || code == TSDB_CODE_VND_INVALID_VGROUP_ID) && pParentSql->retry < pParentSql->maxRetry) {
|
||||
// remove the cached tableMeta and vgroup id list, and then parse the sql again
|
||||
STableMetaInfo* pTableMetaInfo = tscGetTableMetaInfoFromCmd(&pParentSql->cmd, 0);
|
||||
tscRemoveTableMetaBuf(pTableMetaInfo, pParentSql->self);
|
||||
|
||||
tscResetSqlCmd(&pParentSql->cmd, true);
|
||||
pParentSql->res.code = TSDB_CODE_SUCCESS;
|
||||
pParentSql->retry++;
|
||||
|
||||
tscDebug("0x%"PRIx64" retry parse sql and send query, prev error: %s, retry:%d", pParentSql->self,
|
||||
tstrerror(code), pParentSql->retry);
|
||||
|
||||
code = tsParseSql(pParentSql, true);
|
||||
if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
pParentSql->res.code = code;
|
||||
tscAsyncResultOnError(pParentSql);
|
||||
return;
|
||||
}
|
||||
|
||||
executeQuery(pParentSql, pQueryInfo);
|
||||
} else {
|
||||
(*pParentSql->fp)(pParentSql->param, pParentSql, pParentSql->res.code);
|
||||
}
|
||||
} else { // regular super table query
|
||||
if (pParentSql->res.code != TSDB_CODE_SUCCESS) {
|
||||
tscAsyncResultOnError(pParentSql);
|
||||
|
@ -2892,7 +2919,7 @@ static void tscRetrieveFromDnodeCallBack(void *param, TAOS_RES *tres, int numOfR
|
|||
tscDebug("0x%"PRIx64" sub:0x%"PRIx64" retrieve numOfRows:%d totalNumOfRows:%" PRIu64 " from ep:%s, orderOfSub:%d",
|
||||
pParentSql->self, pSql->self, pRes->numOfRows, pState->numOfRetrievedRows, pSql->epSet.fqdn[pSql->epSet.inUse], idx);
|
||||
|
||||
if (num > tsMaxNumOfOrderedResults && tscIsProjectionQueryOnSTable(pQueryInfo, 0) && !(tscGetQueryInfo(&pParentSql->cmd)->distinctTag)) {
|
||||
if (num > tsMaxNumOfOrderedResults && /*tscIsProjectionQueryOnSTable(pQueryInfo, 0) &&*/ !(tscGetQueryInfo(&pParentSql->cmd)->distinct)) {
|
||||
tscError("0x%"PRIx64" sub:0x%"PRIx64" num of OrderedRes is too many, max allowed:%" PRId32 " , current:%" PRId64,
|
||||
pParentSql->self, pSql->self, tsMaxNumOfOrderedResults, num);
|
||||
tscAbortFurtherRetryRetrieval(trsupport, tres, TSDB_CODE_TSC_SORTED_RES_TOO_MANY);
|
||||
|
@ -2996,7 +3023,7 @@ void tscRetrieveDataRes(void *param, TAOS_RES *tres, int code) {
|
|||
if (taos_errno(pSql) != TSDB_CODE_SUCCESS) {
|
||||
assert(code == taos_errno(pSql));
|
||||
|
||||
if (trsupport->numOfRetry++ < MAX_NUM_OF_SUBQUERY_RETRY) {
|
||||
if (trsupport->numOfRetry++ < MAX_NUM_OF_SUBQUERY_RETRY && (code != TSDB_CODE_TDB_INVALID_TABLE_ID)) {
|
||||
tscError("0x%"PRIx64" sub:0x%"PRIx64" failed code:%s, retry:%d", pParentSql->self, pSql->self, tstrerror(code), trsupport->numOfRetry);
|
||||
|
||||
int32_t sent = 0;
|
||||
|
@ -3005,7 +3032,7 @@ void tscRetrieveDataRes(void *param, TAOS_RES *tres, int code) {
|
|||
return;
|
||||
}
|
||||
} else {
|
||||
tscError("0x%"PRIx64" sub:0x%"PRIx64" reach the max retry times, set global code:%s", pParentSql->self, pSql->self, tstrerror(code));
|
||||
tscError("0x%"PRIx64" sub:0x%"PRIx64" reach the max retry times or no need to retry, set global code:%s", pParentSql->self, pSql->self, tstrerror(code));
|
||||
atomic_val_compare_exchange_32(&pParentSql->res.code, TSDB_CODE_SUCCESS, code); // set global code and abort
|
||||
}
|
||||
|
||||
|
@ -3125,12 +3152,10 @@ static void multiVnodeInsertFinalize(void* param, TAOS_RES* tres, int numOfRows)
|
|||
for(int32_t i = 0; i < pParentObj->cmd.insertParam.numOfTables; ++i) {
|
||||
char name[TSDB_TABLE_FNAME_LEN] = {0};
|
||||
tNameExtractFullName(pParentObj->cmd.insertParam.pTableNameList[i], name);
|
||||
taosHashRemove(tscTableMetaInfo, name, strnlen(name, TSDB_TABLE_FNAME_LEN));
|
||||
taosHashRemove(tscTableMetaMap, name, strnlen(name, TSDB_TABLE_FNAME_LEN));
|
||||
}
|
||||
|
||||
pParentObj->res.code = TSDB_CODE_SUCCESS;
|
||||
// pParentObj->cmd.parseFinished = false;
|
||||
|
||||
tscResetSqlCmd(&pParentObj->cmd, false);
|
||||
|
||||
// in case of insert, redo parsing the sql string and build new submit data block for two reasons:
|
||||
|
|
|
@ -19,15 +19,12 @@
|
|||
#include "trpc.h"
|
||||
#include "tnote.h"
|
||||
#include "ttimer.h"
|
||||
#include "tutil.h"
|
||||
#include "tsched.h"
|
||||
#include "tscLog.h"
|
||||
#include "tscUtil.h"
|
||||
#include "tsclient.h"
|
||||
#include "tglobal.h"
|
||||
#include "tconfig.h"
|
||||
#include "ttimezone.h"
|
||||
#include "tlocale.h"
|
||||
#include "qScript.h"
|
||||
|
||||
// global, not configurable
|
||||
|
@ -36,8 +33,10 @@
|
|||
|
||||
int32_t sentinel = TSC_VAR_NOT_RELEASE;
|
||||
|
||||
SHashObj *tscVgroupMap; // hash map to keep the global vgroup info
|
||||
SHashObj *tscTableMetaInfo; // table meta info
|
||||
SHashObj *tscVgroupMap; // hash map to keep the vgroup info from mnode
|
||||
SHashObj *tscTableMetaMap; // table meta info buffer
|
||||
SCacheObj *tscVgroupListBuf; // super table vgroup list information, only survives 5 seconds for each super table vgroup list
|
||||
|
||||
int32_t tscObjRef = -1;
|
||||
void *tscTmr;
|
||||
void *tscQhandle;
|
||||
|
@ -45,17 +44,21 @@ int32_t tscRefId = -1;
|
|||
int32_t tscNumOfObj = 0; // number of sqlObj in current process.
|
||||
static void *tscCheckDiskUsageTmr;
|
||||
void *tscRpcCache; // cache to keep rpc obj
|
||||
int32_t tscNumOfThreads = 1; // num of rpc threads
|
||||
char tscLogFileName[12] = "taoslog";
|
||||
int tscLogFileNum = 10;
|
||||
static pthread_mutex_t rpcObjMutex; // mutex to protect open the rpc obj concurrently
|
||||
static pthread_once_t tscinit = PTHREAD_ONCE_INIT;
|
||||
int32_t tscNumOfThreads = 1; // num of rpc threads
|
||||
char tscLogFileName[12] = "taoslog";
|
||||
int tscLogFileNum = 10;
|
||||
|
||||
static pthread_mutex_t rpcObjMutex; // mutex to protect open the rpc obj concurrently
|
||||
static pthread_once_t tscinit = PTHREAD_ONCE_INIT;
|
||||
|
||||
// pthread_once can not return result code, so result code is set to a global variable.
|
||||
static volatile int tscInitRes = 0;
|
||||
|
||||
void tscCheckDiskUsage(void *UNUSED_PARAM(para), void *UNUSED_PARAM(param)) {
|
||||
taosGetDisk();
|
||||
taosTmrReset(tscCheckDiskUsage, 20 * 1000, NULL, tscTmr, &tscCheckDiskUsageTmr);
|
||||
}
|
||||
|
||||
void tscFreeRpcObj(void *param) {
|
||||
assert(param);
|
||||
SRpcObj *pRpcObj = (SRpcObj *)(param);
|
||||
|
@ -67,10 +70,9 @@ void tscReleaseRpc(void *param) {
|
|||
if (param == NULL) {
|
||||
return;
|
||||
}
|
||||
pthread_mutex_lock(&rpcObjMutex);
|
||||
taosCacheRelease(tscRpcCache, (void *)¶m, false);
|
||||
pthread_mutex_unlock(&rpcObjMutex);
|
||||
}
|
||||
|
||||
taosCacheRelease(tscRpcCache, (void *)¶m, false);
|
||||
}
|
||||
|
||||
int32_t tscAcquireRpc(const char *key, const char *user, const char *secretEncrypt, void **ppRpcObj) {
|
||||
pthread_mutex_lock(&rpcObjMutex);
|
||||
|
@ -80,7 +82,7 @@ int32_t tscAcquireRpc(const char *key, const char *user, const char *secretEncry
|
|||
*ppRpcObj = pRpcObj;
|
||||
pthread_mutex_unlock(&rpcObjMutex);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
SRpcInit rpcInit;
|
||||
memset(&rpcInit, 0, sizeof(rpcInit));
|
||||
|
@ -104,7 +106,8 @@ int32_t tscAcquireRpc(const char *key, const char *user, const char *secretEncry
|
|||
pthread_mutex_unlock(&rpcObjMutex);
|
||||
tscError("failed to init connection to TDengine");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
pRpcObj = taosCachePut(tscRpcCache, rpcObj.key, strlen(rpcObj.key), &rpcObj, sizeof(rpcObj), 1000*5);
|
||||
if (pRpcObj == NULL) {
|
||||
rpcClose(rpcObj.pDnodeConn);
|
||||
|
@ -118,7 +121,7 @@ int32_t tscAcquireRpc(const char *key, const char *user, const char *secretEncry
|
|||
}
|
||||
|
||||
void taos_init_imp(void) {
|
||||
char temp[128] = {0};
|
||||
char temp[128] = {0};
|
||||
|
||||
errno = TSDB_CODE_SUCCESS;
|
||||
srand(taosGetTimestampSec());
|
||||
|
@ -151,36 +154,41 @@ void taos_init_imp(void) {
|
|||
rpcInit();
|
||||
|
||||
scriptEnvPoolInit();
|
||||
|
||||
tscDebug("starting to initialize TAOS client ...");
|
||||
tscDebug("Local End Point is:%s", tsLocalEp);
|
||||
}
|
||||
|
||||
taosSetCoreDump();
|
||||
tscInitMsgsFp();
|
||||
int queueSize = tsMaxConnections*2;
|
||||
|
||||
double factor = (tscEmbedded == 0)? 2.0:4.0;
|
||||
tscNumOfThreads = (int)(tsNumOfCores * tsNumOfThreadsPerCore / factor);
|
||||
if (tscNumOfThreads < 2) {
|
||||
tscNumOfThreads = 2;
|
||||
}
|
||||
|
||||
int32_t queueSize = tsMaxConnections*2;
|
||||
tscQhandle = taosInitScheduler(queueSize, tscNumOfThreads, "tsc");
|
||||
if (NULL == tscQhandle) {
|
||||
tscError("failed to init scheduler");
|
||||
tscError("failed to init task queue");
|
||||
tscInitRes = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
tscDebug("client task queue is initialized, numOfWorkers: %d", tscNumOfThreads);
|
||||
|
||||
tscTmr = taosTmrInit(tsMaxConnections * 2, 200, 60000, "TSC");
|
||||
if(0 == tscEmbedded){
|
||||
taosTmrReset(tscCheckDiskUsage, 20 * 1000, NULL, tscTmr, &tscCheckDiskUsageTmr);
|
||||
}
|
||||
|
||||
if (tscTableMetaInfo == NULL) {
|
||||
tscObjRef = taosOpenRef(40960, tscFreeRegisteredSqlObj);
|
||||
tscVgroupMap = taosHashInit(256, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_ENTRY_LOCK);
|
||||
tscTableMetaInfo = taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK);
|
||||
tscDebug("TableMeta:%p", tscTableMetaInfo);
|
||||
if (tscTableMetaMap == NULL) {
|
||||
tscObjRef = taosOpenRef(40960, tscFreeRegisteredSqlObj);
|
||||
tscVgroupMap = taosHashInit(256, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_ENTRY_LOCK);
|
||||
tscTableMetaMap = taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK);
|
||||
tscVgroupListBuf = taosCacheInit(TSDB_DATA_TYPE_BINARY, 5, false, NULL, "stable-vgroup-list");
|
||||
tscDebug("TableMeta:%p, vgroup:%p is initialized", tscTableMetaMap, tscVgroupMap);
|
||||
}
|
||||
|
||||
int refreshTime = 5;
|
||||
|
@ -189,14 +197,17 @@ void taos_init_imp(void) {
|
|||
|
||||
tscRefId = taosOpenRef(200, tscCloseTscObj);
|
||||
|
||||
// in other language APIs, taos_cleanup is not available yet.
|
||||
// So, to make sure taos_cleanup will be invoked to clean up the allocated
|
||||
// resource to suppress the valgrind warning.
|
||||
// In the APIs of other program language, taos_cleanup is not available yet.
|
||||
// So, to make sure taos_cleanup will be invoked to clean up the allocated resource to suppress the valgrind warning.
|
||||
atexit(taos_cleanup);
|
||||
|
||||
tscDebug("client is initialized successfully");
|
||||
}
|
||||
|
||||
int taos_init() { pthread_once(&tscinit, taos_init_imp); return tscInitRes;}
|
||||
int taos_init() {
|
||||
pthread_once(&tscinit, taos_init_imp);
|
||||
return tscInitRes;
|
||||
}
|
||||
|
||||
// this function may be called by user or system, or by both simultaneously.
|
||||
void taos_cleanup(void) {
|
||||
|
@ -205,11 +216,13 @@ void taos_cleanup(void) {
|
|||
if (atomic_val_compare_exchange_32(&sentinel, TSC_VAR_NOT_RELEASE, TSC_VAR_RELEASED) != TSC_VAR_NOT_RELEASE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tscEmbedded == 0) {
|
||||
scriptEnvPoolCleanup();
|
||||
}
|
||||
taosHashCleanup(tscTableMetaInfo);
|
||||
tscTableMetaInfo = NULL;
|
||||
|
||||
taosHashCleanup(tscTableMetaMap);
|
||||
tscTableMetaMap = NULL;
|
||||
|
||||
taosHashCleanup(tscVgroupMap);
|
||||
tscVgroupMap = NULL;
|
||||
|
@ -236,6 +249,9 @@ void taos_cleanup(void) {
|
|||
pthread_mutex_destroy(&rpcObjMutex);
|
||||
}
|
||||
|
||||
taosCacheCleanup(tscVgroupListBuf);
|
||||
tscVgroupListBuf = NULL;
|
||||
|
||||
if (tscEmbedded == 0) {
|
||||
rpcCleanup();
|
||||
taosCloseLog();
|
||||
|
|
|
@ -1388,7 +1388,7 @@ void tscResetSqlCmd(SSqlCmd* pCmd, bool clearCachedMeta) {
|
|||
if (pCmd->pTableMetaMap != NULL) {
|
||||
STableMetaVgroupInfo* p = taosHashIterate(pCmd->pTableMetaMap, NULL);
|
||||
while (p) {
|
||||
tscVgroupInfoClear(p->pVgroupInfo);
|
||||
taosArrayDestroy(p->vgroupIdList);
|
||||
tfree(p->pTableMeta);
|
||||
p = taosHashIterate(pCmd->pTableMetaMap, p);
|
||||
}
|
||||
|
@ -1398,6 +1398,22 @@ void tscResetSqlCmd(SSqlCmd* pCmd, bool clearCachedMeta) {
|
|||
}
|
||||
}
|
||||
|
||||
void* tscCleanupTableMetaMap(SHashObj* pTableMetaMap) {
|
||||
if (pTableMetaMap == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
STableMetaVgroupInfo* p = taosHashIterate(pTableMetaMap, NULL);
|
||||
while (p) {
|
||||
taosArrayDestroy(p->vgroupIdList);
|
||||
tfree(p->pTableMeta);
|
||||
p = taosHashIterate(pTableMetaMap, p);
|
||||
}
|
||||
|
||||
taosHashCleanup(pTableMetaMap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void tscFreeSqlResult(SSqlObj* pSql) {
|
||||
SSqlRes* pRes = &pSql->res;
|
||||
|
||||
|
@ -1522,7 +1538,7 @@ void tscDestroyDataBlock(STableDataBlocks* pDataBlock, bool removeMeta) {
|
|||
char name[TSDB_TABLE_FNAME_LEN] = {0};
|
||||
tNameExtractFullName(&pDataBlock->tableName, name);
|
||||
|
||||
taosHashRemove(tscTableMetaInfo, name, strnlen(name, TSDB_TABLE_FNAME_LEN));
|
||||
taosHashRemove(tscTableMetaMap, name, strnlen(name, TSDB_TABLE_FNAME_LEN));
|
||||
}
|
||||
|
||||
if (!pDataBlock->cloned) {
|
||||
|
@ -1848,8 +1864,8 @@ static SMemRow tdGenMemRowFromBuilder(SMemRowBuilder* pBuilder) {
|
|||
while (i < nColsBound) {
|
||||
int16_t colId = payloadColId(p);
|
||||
uint8_t colType = payloadColType(p);
|
||||
tdAppendKvColVal(kvRow, POINTER_SHIFT(pVals,payloadColOffset(p)), colId, colType, toffset);
|
||||
toffset += sizeof(SColIdx);
|
||||
tdAppendKvColVal(kvRow, POINTER_SHIFT(pVals,payloadColOffset(p)), colId, colType, &toffset);
|
||||
//toffset += sizeof(SColIdx);
|
||||
p = payloadNextCol(p);
|
||||
++i;
|
||||
}
|
||||
|
@ -3365,7 +3381,7 @@ void clearAllTableMetaInfo(SQueryInfo* pQueryInfo, bool removeMeta) {
|
|||
if (removeMeta) {
|
||||
char name[TSDB_TABLE_FNAME_LEN] = {0};
|
||||
tNameExtractFullName(&pTableMetaInfo->name, name);
|
||||
taosHashRemove(tscTableMetaInfo, name, strnlen(name, TSDB_TABLE_FNAME_LEN));
|
||||
taosHashRemove(tscTableMetaMap, name, strnlen(name, TSDB_TABLE_FNAME_LEN));
|
||||
}
|
||||
|
||||
tscFreeVgroupTableInfo(pTableMetaInfo->pVgroupTables);
|
||||
|
@ -3481,11 +3497,9 @@ SSqlObj* createSimpleSubObj(SSqlObj* pSql, __async_cb_func_t fp, void* param, in
|
|||
|
||||
SSqlCmd* pCmd = &pNew->cmd;
|
||||
pCmd->command = cmd;
|
||||
tsem_init(&pNew->rspSem, 0 ,0);
|
||||
|
||||
if (tscAddQueryInfo(pCmd) != TSDB_CODE_SUCCESS) {
|
||||
#ifdef __APPLE__
|
||||
// to satisfy later tsem_destroy in taos_free_result
|
||||
tsem_init(&pNew->rspSem, 0, 0);
|
||||
#endif // __APPLE__
|
||||
tscFreeSqlObj(pNew);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -4360,7 +4374,7 @@ int32_t tscCreateTableMetaFromSTableMeta(STableMeta* pChild, const char* name, v
|
|||
assert(pChild != NULL && buf != NULL);
|
||||
|
||||
STableMeta* p = buf;
|
||||
taosHashGetClone(tscTableMetaInfo, pChild->sTableName, strnlen(pChild->sTableName, TSDB_TABLE_FNAME_LEN), NULL, p, -1);
|
||||
taosHashGetClone(tscTableMetaMap, pChild->sTableName, strnlen(pChild->sTableName, TSDB_TABLE_FNAME_LEN), NULL, p);
|
||||
|
||||
// tableMeta exists, build child table meta according to the super table meta
|
||||
// the uid need to be checked in addition to the general name of the super table.
|
||||
|
@ -4374,7 +4388,7 @@ int32_t tscCreateTableMetaFromSTableMeta(STableMeta* pChild, const char* name, v
|
|||
memcpy(pChild->schema, p->schema, sizeof(SSchema) *total);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} else { // super table has been removed, current tableMeta is also expired. remove it here
|
||||
taosHashRemove(tscTableMetaInfo, name, strnlen(name, TSDB_TABLE_FNAME_LEN));
|
||||
taosHashRemove(tscTableMetaMap, name, strnlen(name, TSDB_TABLE_FNAME_LEN));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -4580,6 +4594,22 @@ static int32_t createTagColumnInfo(SQueryAttr* pQueryAttr, SQueryInfo* pQueryInf
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t tscGetColFilterSerializeLen(SQueryInfo* pQueryInfo) {
|
||||
int16_t numOfCols = (int16_t)taosArrayGetSize(pQueryInfo->colList);
|
||||
int32_t len = 0;
|
||||
|
||||
for(int32_t i = 0; i < numOfCols; ++i) {
|
||||
SColumn* pCol = taosArrayGetP(pQueryInfo->colList, i);
|
||||
for (int32_t j = 0; j < pCol->info.flist.numOfFilters; ++j) {
|
||||
len += sizeof(SColumnFilterInfo);
|
||||
if (pCol->info.flist.filterInfo[j].filterstr) {
|
||||
len += (int32_t)pCol->info.flist.filterInfo[j].len + 1 * TSDB_NCHAR_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int32_t tscCreateQueryFromQueryInfo(SQueryInfo* pQueryInfo, SQueryAttr* pQueryAttr, void* addr) {
|
||||
memset(pQueryAttr, 0, sizeof(SQueryAttr));
|
||||
|
||||
|
@ -4598,7 +4628,7 @@ int32_t tscCreateQueryFromQueryInfo(SQueryInfo* pQueryInfo, SQueryAttr* pQueryAt
|
|||
pQueryAttr->queryBlockDist = isBlockDistQuery(pQueryInfo);
|
||||
pQueryAttr->pointInterpQuery = tscIsPointInterpQuery(pQueryInfo);
|
||||
pQueryAttr->timeWindowInterpo = timeWindowInterpoRequired(pQueryInfo);
|
||||
pQueryAttr->distinctTag = pQueryInfo->distinctTag;
|
||||
pQueryAttr->distinct = pQueryInfo->distinct;
|
||||
pQueryAttr->sw = pQueryInfo->sessionWindow;
|
||||
pQueryAttr->stateWindow = pQueryInfo->stateWindow;
|
||||
|
||||
|
@ -4857,3 +4887,19 @@ SNewVgroupInfo createNewVgroupInfo(SVgroupMsg *pVgroupMsg) {
|
|||
|
||||
return info;
|
||||
}
|
||||
|
||||
void tscRemoveTableMetaBuf(STableMetaInfo* pTableMetaInfo, uint64_t id) {
|
||||
char fname[TSDB_TABLE_FNAME_LEN] = {0};
|
||||
tNameExtractFullName(&pTableMetaInfo->name, fname);
|
||||
|
||||
int32_t len = (int32_t) strnlen(fname, TSDB_TABLE_FNAME_LEN);
|
||||
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
|
||||
void* pv = taosCacheAcquireByKey(tscVgroupListBuf, fname, len);
|
||||
if (pv != NULL) {
|
||||
taosCacheRelease(tscVgroupListBuf, &pv, true);
|
||||
}
|
||||
}
|
||||
|
||||
taosHashRemove(tscTableMetaMap, fname, len);
|
||||
tscDebug("0x%"PRIx64" remove table meta %s, numOfRemain:%d", id, fname, (int32_t) taosHashGetSize(tscTableMetaMap));
|
||||
}
|
|
@ -88,10 +88,7 @@ enum {
|
|||
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_SHOW_CREATE_STABLE, "show-create-stable")
|
||||
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_SHOW_CREATE_DATABASE, "show-create-database")
|
||||
|
||||
/*
|
||||
* build empty result instead of accessing dnode to fetch result
|
||||
* reset the client cache
|
||||
*/
|
||||
// build empty result instead of accessing dnode to fetch result reset the client cache
|
||||
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_RETRIEVE_EMPTY_RESULT, "retrieve-empty-result" )
|
||||
|
||||
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_RESET_CACHE, "reset-cache" )
|
||||
|
|
|
@ -55,7 +55,7 @@ extern "C" {
|
|||
typedef struct {
|
||||
int8_t type; // Column type
|
||||
int16_t colId; // column ID
|
||||
uint16_t bytes; // column bytes
|
||||
int16_t bytes; // column bytes (restore to int16_t in case of misuse)
|
||||
uint16_t offset; // point offset in SDataRow after the header part.
|
||||
} STColumn;
|
||||
|
||||
|
@ -232,6 +232,83 @@ static FORCE_INLINE void *tdGetRowDataOfCol(SDataRow row, int8_t type, int32_t o
|
|||
}
|
||||
}
|
||||
|
||||
static FORCE_INLINE void *tdGetPtrToCol(SDataRow row, STSchema *pSchema, int idx) {
|
||||
return POINTER_SHIFT(row, TD_DATA_ROW_HEAD_SIZE + pSchema->columns[idx].offset);
|
||||
}
|
||||
|
||||
static FORCE_INLINE void *tdGetColOfRowBySchema(SDataRow row, STSchema *pSchema, int idx) {
|
||||
int16_t offset = TD_DATA_ROW_HEAD_SIZE + pSchema->columns[idx].offset;
|
||||
int8_t type = pSchema->columns[idx].type;
|
||||
|
||||
return tdGetRowDataOfCol(row, type, offset);
|
||||
}
|
||||
|
||||
static FORCE_INLINE bool tdIsColOfRowNullBySchema(SDataRow row, STSchema *pSchema, int idx) {
|
||||
int16_t offset = TD_DATA_ROW_HEAD_SIZE + pSchema->columns[idx].offset;
|
||||
int8_t type = pSchema->columns[idx].type;
|
||||
|
||||
return isNull(tdGetRowDataOfCol(row, type, offset), type);
|
||||
}
|
||||
|
||||
static FORCE_INLINE void tdSetColOfRowNullBySchema(SDataRow row, STSchema *pSchema, int idx) {
|
||||
int16_t offset = TD_DATA_ROW_HEAD_SIZE + pSchema->columns[idx].offset;
|
||||
int8_t type = pSchema->columns[idx].type;
|
||||
int16_t bytes = pSchema->columns[idx].bytes;
|
||||
|
||||
setNull(tdGetRowDataOfCol(row, type, offset), type, bytes);
|
||||
}
|
||||
|
||||
static FORCE_INLINE void tdCopyColOfRowBySchema(SDataRow dst, STSchema *pDstSchema, int dstIdx, SDataRow src, STSchema *pSrcSchema, int srcIdx) {
|
||||
int8_t type = pDstSchema->columns[dstIdx].type;
|
||||
ASSERT(type == pSrcSchema->columns[srcIdx].type);
|
||||
void *pData = tdGetPtrToCol(dst, pDstSchema, dstIdx);
|
||||
void *value = tdGetPtrToCol(src, pSrcSchema, srcIdx);
|
||||
|
||||
switch (type) {
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
*(VarDataOffsetT *)pData = *(VarDataOffsetT *)value;
|
||||
pData = POINTER_SHIFT(dst, *(VarDataOffsetT *)pData);
|
||||
value = POINTER_SHIFT(src, *(VarDataOffsetT *)value);
|
||||
memcpy(pData, value, varDataTLen(value));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_NULL:
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
case TSDB_DATA_TYPE_UTINYINT:
|
||||
*(uint8_t *)pData = *(uint8_t *)value;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
case TSDB_DATA_TYPE_USMALLINT:
|
||||
*(uint16_t *)pData = *(uint16_t *)value;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
case TSDB_DATA_TYPE_UINT:
|
||||
*(uint32_t *)pData = *(uint32_t *)value;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
*(uint64_t *)pData = *(uint64_t *)value;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
SET_FLOAT_PTR(pData, value);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
SET_DOUBLE_PTR(pData, value);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
if (pSrcSchema->columns[srcIdx].colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
|
||||
*(TSKEY *)pData = tdGetKey(*(TKEY *)value);
|
||||
} else {
|
||||
*(TSKEY *)pData = *(TSKEY *)value;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
memcpy(pData, value, pSrcSchema->columns[srcIdx].bytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------- Data column structure
|
||||
typedef struct SDataCol {
|
||||
int8_t type; // column type
|
||||
|
@ -335,7 +412,7 @@ void tdResetDataCols(SDataCols *pCols);
|
|||
int tdInitDataCols(SDataCols *pCols, STSchema *pSchema);
|
||||
SDataCols *tdDupDataCols(SDataCols *pCols, bool keepData);
|
||||
SDataCols *tdFreeDataCols(SDataCols *pCols);
|
||||
int tdMergeDataCols(SDataCols *target, SDataCols *source, int rowsToMerge, int *pOffset);
|
||||
int tdMergeDataCols(SDataCols *target, SDataCols *source, int rowsToMerge, int *pOffset, bool forceSetNull);
|
||||
|
||||
// ----------------- K-V data row structure
|
||||
/* |<-------------------------------------- len -------------------------------------------->|
|
||||
|
@ -366,6 +443,7 @@ typedef struct {
|
|||
#define kvRowColIdxAt(r, i) (kvRowColIdx(r) + (i))
|
||||
#define kvRowFree(r) tfree(r)
|
||||
#define kvRowEnd(r) POINTER_SHIFT(r, kvRowLen(r))
|
||||
#define kvRowValLen(r) (kvRowLen(r) - TD_KV_ROW_HEAD_SIZE - sizeof(SColIdx) * kvRowNCols(r))
|
||||
#define kvRowTKey(r) (*(TKEY *)(kvRowValues(r)))
|
||||
#define kvRowKey(r) tdGetKey(kvRowTKey(r))
|
||||
#define kvRowDeleted(r) TKEY_IS_DELETED(kvRowTKey(r))
|
||||
|
@ -397,9 +475,9 @@ static FORCE_INLINE void *tdGetKVRowIdxOfCol(SKVRow row, int16_t colId) {
|
|||
}
|
||||
|
||||
// offset here not include kvRow header length
|
||||
static FORCE_INLINE int tdAppendKvColVal(SKVRow row, const void *value, int16_t colId, int8_t type, int32_t offset) {
|
||||
static FORCE_INLINE int tdAppendKvColVal(SKVRow row, const void *value, int16_t colId, int8_t type, int32_t *offset) {
|
||||
ASSERT(value != NULL);
|
||||
int32_t toffset = offset + TD_KV_ROW_HEAD_SIZE;
|
||||
int32_t toffset = *offset + TD_KV_ROW_HEAD_SIZE;
|
||||
SColIdx *pColIdx = (SColIdx *)POINTER_SHIFT(row, toffset);
|
||||
char * ptr = (char *)POINTER_SHIFT(row, kvRowLen(row));
|
||||
|
||||
|
@ -410,7 +488,7 @@ static FORCE_INLINE int tdAppendKvColVal(SKVRow row, const void *value, int16_t
|
|||
memcpy(ptr, value, varDataTLen(value));
|
||||
kvRowLen(row) += varDataTLen(value);
|
||||
} else {
|
||||
if (offset == 0) {
|
||||
if (*offset == 0) {
|
||||
ASSERT(type == TSDB_DATA_TYPE_TIMESTAMP);
|
||||
TKEY tvalue = tdGetTKEY(*(TSKEY *)value);
|
||||
memcpy(ptr, (void *)(&tvalue), TYPE_BYTES[type]);
|
||||
|
@ -419,9 +497,27 @@ static FORCE_INLINE int tdAppendKvColVal(SKVRow row, const void *value, int16_t
|
|||
}
|
||||
kvRowLen(row) += TYPE_BYTES[type];
|
||||
}
|
||||
*offset += sizeof(SColIdx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
// NOTE: offset here including the header size
|
||||
static FORCE_INLINE void *tdGetKvRowDataOfCol(void *row, int32_t offset) { return POINTER_SHIFT(row, offset); }
|
||||
|
||||
static FORCE_INLINE void *tdGetKVRowValOfColEx(SKVRow row, int16_t colId, int32_t *nIdx) {
|
||||
while (*nIdx < kvRowNCols(row)) {
|
||||
SColIdx *pColIdx = kvRowColIdxAt(row, *nIdx);
|
||||
if (pColIdx->colId == colId) {
|
||||
++(*nIdx);
|
||||
return tdGetKvRowDataOfCol(row, pColIdx->offset);
|
||||
} else if (pColIdx->colId > colId) {
|
||||
return NULL;
|
||||
} else {
|
||||
++(*nIdx);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ----------------- K-V data row builder
|
||||
typedef struct {
|
||||
|
@ -494,7 +590,7 @@ typedef void *SMemRow;
|
|||
#define TD_MEM_ROW_KV_VER_SIZE sizeof(int16_t)
|
||||
#define TD_MEM_ROW_KV_TYPE_VER_SIZE (TD_MEM_ROW_TYPE_SIZE + TD_MEM_ROW_KV_VER_SIZE)
|
||||
#define TD_MEM_ROW_DATA_HEAD_SIZE (TD_MEM_ROW_TYPE_SIZE + TD_DATA_ROW_HEAD_SIZE)
|
||||
// #define TD_MEM_ROW_KV_HEAD_SIZE (TD_MEM_ROW_TYPE_SIZE + TD_MEM_ROW_KV_VER_SIZE + TD_KV_ROW_HEAD_SIZE)
|
||||
#define TD_MEM_ROW_KV_HEAD_SIZE (TD_MEM_ROW_TYPE_SIZE + TD_MEM_ROW_KV_VER_SIZE + TD_KV_ROW_HEAD_SIZE)
|
||||
|
||||
#define SMEM_ROW_DATA 0U // SDataRow
|
||||
#define SMEM_ROW_KV 1U // SKVRow
|
||||
|
@ -537,27 +633,80 @@ typedef void *SMemRow;
|
|||
|
||||
#define memRowSetType(r, t) (memRowType(r) = (t))
|
||||
#define memRowSetLen(r, l) (isDataRow(r) ? memRowDataLen(r) = (l) : memRowKvLen(r) = (l))
|
||||
#define memRowSetVersion(r, v) (isDataRow(r) ? dataRowSetVersion(memRowDataBody(r), v) : memRowKvSetVersion(r, v))
|
||||
#define memRowSetVersion(r, v) (isDataRow(r) ? dataRowSetVersion(memRowDataBody(r), v) : memRowSetKvVersion(r, v))
|
||||
#define memRowCpy(dst, r) memcpy((dst), (r), memRowTLen(r))
|
||||
#define memRowMaxBytesFromSchema(s) (schemaTLen(s) + TD_MEM_ROW_DATA_HEAD_SIZE)
|
||||
#define memRowDeleted(r) TKEY_IS_DELETED(memRowTKey(r))
|
||||
|
||||
SMemRow tdMemRowDup(SMemRow row);
|
||||
void tdAppendMemRowToDataCol(SMemRow row, STSchema *pSchema, SDataCols *pCols);
|
||||
void tdAppendMemRowToDataCol(SMemRow row, STSchema *pSchema, SDataCols *pCols, bool forceSetNull);
|
||||
|
||||
// NOTE: offset here including the header size
|
||||
static FORCE_INLINE void *tdGetKvRowDataOfCol(void *row, int32_t offset) { return POINTER_SHIFT(row, offset); }
|
||||
// NOTE: offset here including the header size
|
||||
static FORCE_INLINE void *tdGetMemRowDataOfCol(void *row, int8_t type, int32_t offset) {
|
||||
static FORCE_INLINE void *tdGetMemRowDataOfCol(void *row, int16_t colId, int8_t colType, uint16_t offset) {
|
||||
if (isDataRow(row)) {
|
||||
return tdGetRowDataOfCol(row, type, offset);
|
||||
} else if (isKvRow(row)) {
|
||||
return tdGetKvRowDataOfCol(row, offset);
|
||||
return tdGetRowDataOfCol(memRowDataBody(row), colType, offset);
|
||||
} else {
|
||||
ASSERT(0);
|
||||
return tdGetKVRowValOfCol(memRowKvBody(row), colId);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE:
|
||||
* 1. Applicable to scan columns one by one
|
||||
* 2. offset here including the header size
|
||||
*/
|
||||
static FORCE_INLINE void *tdGetMemRowDataOfColEx(void *row, int16_t colId, int8_t colType, int32_t offset,
|
||||
int32_t *kvNIdx) {
|
||||
if (isDataRow(row)) {
|
||||
return tdGetRowDataOfCol(memRowDataBody(row), colType, offset);
|
||||
} else {
|
||||
return tdGetKVRowValOfColEx(memRowKvBody(row), colId, kvNIdx);
|
||||
}
|
||||
}
|
||||
|
||||
static FORCE_INLINE int tdAppendMemColVal(SMemRow row, const void *value, int16_t colId, int8_t type, int32_t offset,
|
||||
int32_t *kvOffset) {
|
||||
if (isDataRow(row)) {
|
||||
tdAppendColVal(memRowDataBody(row), value, type, offset);
|
||||
} else {
|
||||
tdAppendKvColVal(memRowKvBody(row), value, colId, type, kvOffset);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// make sure schema->flen appended for SDataRow
|
||||
static FORCE_INLINE int32_t tdGetColAppendLen(uint8_t rowType, const void *value, int8_t colType) {
|
||||
int32_t len = 0;
|
||||
if (IS_VAR_DATA_TYPE(colType)) {
|
||||
len += varDataTLen(value);
|
||||
if (rowType == SMEM_ROW_KV) {
|
||||
len += sizeof(SColIdx);
|
||||
}
|
||||
} else {
|
||||
if (rowType == SMEM_ROW_KV) {
|
||||
len += TYPE_BYTES[colType];
|
||||
len += sizeof(SColIdx);
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
int16_t colId;
|
||||
uint8_t colType;
|
||||
char* colVal;
|
||||
} SColInfo;
|
||||
|
||||
static FORCE_INLINE void setSColInfo(SColInfo* colInfo, int16_t colId, uint8_t colType, char* colVal) {
|
||||
colInfo->colId = colId;
|
||||
colInfo->colType = colType;
|
||||
colInfo->colVal = colVal;
|
||||
}
|
||||
|
||||
SMemRow mergeTwoMemRows(void *buffer, SMemRow row1, SMemRow row2, STSchema *pSchema1, STSchema *pSchema2);
|
||||
|
||||
|
||||
// ----------------- Raw payload structure for row:
|
||||
/* |<------------ Head ------------->|<----------- body of column data tuple ------------------->|
|
||||
* | |<----------------- flen ------------->|<--- value part --->|
|
||||
|
@ -607,4 +756,4 @@ static FORCE_INLINE char *payloadNextCol(char *pCol) { return (char *)POINTER_SH
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif // _TD_DATA_FORMAT_H_
|
||||
#endif // _TD_DATA_FORMAT_H_
|
||||
|
|
|
@ -17,9 +17,10 @@
|
|||
#include "talgo.h"
|
||||
#include "tcoding.h"
|
||||
#include "wchar.h"
|
||||
#include "tarray.h"
|
||||
|
||||
static void tdMergeTwoDataCols(SDataCols *target, SDataCols *src1, int *iter1, int limit1, SDataCols *src2, int *iter2,
|
||||
int limit2, int tRows);
|
||||
int limit2, int tRows, bool forceSetNull);
|
||||
|
||||
/**
|
||||
* Duplicate the schema and return a new object
|
||||
|
@ -418,7 +419,8 @@ void tdResetDataCols(SDataCols *pCols) {
|
|||
}
|
||||
}
|
||||
}
|
||||
static void tdAppendDataRowToDataCol(SDataRow row, STSchema *pSchema, SDataCols *pCols) {
|
||||
|
||||
static void tdAppendDataRowToDataCol(SDataRow row, STSchema *pSchema, SDataCols *pCols, bool forceSetNull) {
|
||||
ASSERT(pCols->numOfRows == 0 || dataColsKeyLast(pCols) < dataRowKey(row));
|
||||
|
||||
int rcol = 0;
|
||||
|
@ -452,8 +454,10 @@ static void tdAppendDataRowToDataCol(SDataRow row, STSchema *pSchema, SDataCols
|
|||
} else if (pRowCol->colId < pDataCol->colId) {
|
||||
rcol++;
|
||||
} else {
|
||||
// dataColSetNullAt(pDataCol, pCols->numOfRows);
|
||||
dataColAppendVal(pDataCol, getNullValue(pDataCol->type), pCols->numOfRows, pCols->maxPoints);
|
||||
if(forceSetNull) {
|
||||
//dataColSetNullAt(pDataCol, pCols->numOfRows);
|
||||
dataColAppendVal(pDataCol, getNullValue(pDataCol->type), pCols->numOfRows, pCols->maxPoints);
|
||||
}
|
||||
dcol++;
|
||||
}
|
||||
}
|
||||
|
@ -461,7 +465,7 @@ static void tdAppendDataRowToDataCol(SDataRow row, STSchema *pSchema, SDataCols
|
|||
pCols->numOfRows++;
|
||||
}
|
||||
|
||||
static void tdAppendKvRowToDataCol(SKVRow row, STSchema *pSchema, SDataCols *pCols) {
|
||||
static void tdAppendKvRowToDataCol(SKVRow row, STSchema *pSchema, SDataCols *pCols, bool forceSetNull) {
|
||||
ASSERT(pCols->numOfRows == 0 || dataColsKeyLast(pCols) < kvRowKey(row));
|
||||
|
||||
int rcol = 0;
|
||||
|
@ -498,8 +502,10 @@ static void tdAppendKvRowToDataCol(SKVRow row, STSchema *pSchema, SDataCols *pCo
|
|||
} else if (colIdx->colId < pDataCol->colId) {
|
||||
++rcol;
|
||||
} else {
|
||||
// dataColSetNullAt(pDataCol, pCols->numOfRows);
|
||||
dataColAppendVal(pDataCol, getNullValue(pDataCol->type), pCols->numOfRows, pCols->maxPoints);
|
||||
if (forceSetNull) {
|
||||
// dataColSetNullAt(pDataCol, pCols->numOfRows);
|
||||
dataColAppendVal(pDataCol, getNullValue(pDataCol->type), pCols->numOfRows, pCols->maxPoints);
|
||||
}
|
||||
++dcol;
|
||||
}
|
||||
}
|
||||
|
@ -507,17 +513,17 @@ static void tdAppendKvRowToDataCol(SKVRow row, STSchema *pSchema, SDataCols *pCo
|
|||
pCols->numOfRows++;
|
||||
}
|
||||
|
||||
void tdAppendMemRowToDataCol(SMemRow row, STSchema *pSchema, SDataCols *pCols) {
|
||||
void tdAppendMemRowToDataCol(SMemRow row, STSchema *pSchema, SDataCols *pCols, bool forceSetNull) {
|
||||
if (isDataRow(row)) {
|
||||
tdAppendDataRowToDataCol(memRowDataBody(row), pSchema, pCols);
|
||||
tdAppendDataRowToDataCol(memRowDataBody(row), pSchema, pCols, forceSetNull);
|
||||
} else if (isKvRow(row)) {
|
||||
tdAppendKvRowToDataCol(memRowKvBody(row), pSchema, pCols);
|
||||
tdAppendKvRowToDataCol(memRowKvBody(row), pSchema, pCols, forceSetNull);
|
||||
} else {
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
int tdMergeDataCols(SDataCols *target, SDataCols *source, int rowsToMerge, int *pOffset) {
|
||||
int tdMergeDataCols(SDataCols *target, SDataCols *source, int rowsToMerge, int *pOffset, bool forceSetNull) {
|
||||
ASSERT(rowsToMerge > 0 && rowsToMerge <= source->numOfRows);
|
||||
ASSERT(target->numOfCols == source->numOfCols);
|
||||
int offset = 0;
|
||||
|
@ -546,7 +552,7 @@ int tdMergeDataCols(SDataCols *target, SDataCols *source, int rowsToMerge, int *
|
|||
|
||||
int iter1 = 0;
|
||||
tdMergeTwoDataCols(target, pTarget, &iter1, pTarget->numOfRows, source, pOffset, source->numOfRows,
|
||||
pTarget->numOfRows + rowsToMerge);
|
||||
pTarget->numOfRows + rowsToMerge, forceSetNull);
|
||||
}
|
||||
|
||||
tdFreeDataCols(pTarget);
|
||||
|
@ -559,7 +565,7 @@ _err:
|
|||
|
||||
// src2 data has more priority than src1
|
||||
static void tdMergeTwoDataCols(SDataCols *target, SDataCols *src1, int *iter1, int limit1, SDataCols *src2, int *iter2,
|
||||
int limit2, int tRows) {
|
||||
int limit2, int tRows, bool forceSetNull) {
|
||||
tdResetDataCols(target);
|
||||
ASSERT(limit1 <= src1->numOfRows && limit2 <= src2->numOfRows);
|
||||
|
||||
|
@ -588,7 +594,7 @@ static void tdMergeTwoDataCols(SDataCols *target, SDataCols *src1, int *iter1, i
|
|||
if ((key1 > key2) || (key1 == key2 && !TKEY_IS_DELETED(tkey2))) {
|
||||
for (int i = 0; i < src2->numOfCols; i++) {
|
||||
ASSERT(target->cols[i].type == src2->cols[i].type);
|
||||
if (src2->cols[i].len > 0) {
|
||||
if (src2->cols[i].len > 0 && (forceSetNull || (!forceSetNull && !isNull(src2->cols[i].pData, src2->cols[i].type)))) {
|
||||
dataColAppendVal(&(target->cols[i]), tdGetColDataOfRow(src2->cols + i, *iter2), target->numOfRows,
|
||||
target->maxPoints);
|
||||
}
|
||||
|
@ -634,42 +640,28 @@ int tdSetKVRowDataOfCol(SKVRow *orow, int16_t colId, int8_t type, void *value) {
|
|||
SKVRow nrow = NULL;
|
||||
void * ptr = taosbsearch(&colId, kvRowColIdx(row), kvRowNCols(row), sizeof(SColIdx), comparTagId, TD_GE);
|
||||
|
||||
if (ptr == NULL || ((SColIdx *)ptr)->colId > colId) { // need to add a column value to the row
|
||||
if (ptr == NULL || ((SColIdx *)ptr)->colId > colId) { // need to add a column value to the row
|
||||
int diff = IS_VAR_DATA_TYPE(type) ? varDataTLen(value) : TYPE_BYTES[type];
|
||||
nrow = malloc(kvRowLen(row) + sizeof(SColIdx) + diff);
|
||||
int nRowLen = kvRowLen(row) + sizeof(SColIdx) + diff;
|
||||
int oRowCols = kvRowNCols(row);
|
||||
|
||||
ASSERT(diff > 0);
|
||||
nrow = malloc(nRowLen);
|
||||
if (nrow == NULL) return -1;
|
||||
|
||||
kvRowSetLen(nrow, kvRowLen(row) + (uint16_t)sizeof(SColIdx) + diff);
|
||||
kvRowSetNCols(nrow, kvRowNCols(row) + 1);
|
||||
kvRowSetLen(nrow, nRowLen);
|
||||
kvRowSetNCols(nrow, oRowCols + 1);
|
||||
|
||||
if (ptr == NULL) {
|
||||
memcpy(kvRowColIdx(nrow), kvRowColIdx(row), sizeof(SColIdx) * kvRowNCols(row));
|
||||
memcpy(kvRowValues(nrow), kvRowValues(row), POINTER_DISTANCE(kvRowEnd(row), kvRowValues(row)));
|
||||
int colIdx = kvRowNCols(nrow) - 1;
|
||||
kvRowColIdxAt(nrow, colIdx)->colId = colId;
|
||||
kvRowColIdxAt(nrow, colIdx)->offset = (int16_t)(POINTER_DISTANCE(kvRowEnd(row), kvRowValues(row)));
|
||||
memcpy(kvRowColVal(nrow, kvRowColIdxAt(nrow, colIdx)), value, diff);
|
||||
} else {
|
||||
int16_t tlen = (int16_t)(POINTER_DISTANCE(ptr, kvRowColIdx(row)));
|
||||
if (tlen > 0) {
|
||||
memcpy(kvRowColIdx(nrow), kvRowColIdx(row), tlen);
|
||||
memcpy(kvRowValues(nrow), kvRowValues(row), ((SColIdx *)ptr)->offset);
|
||||
}
|
||||
memcpy(kvRowColIdx(nrow), kvRowColIdx(row), sizeof(SColIdx) * oRowCols);
|
||||
memcpy(kvRowValues(nrow), kvRowValues(row), kvRowValLen(row));
|
||||
|
||||
int colIdx = tlen / sizeof(SColIdx);
|
||||
kvRowColIdxAt(nrow, colIdx)->colId = colId;
|
||||
kvRowColIdxAt(nrow, colIdx)->offset = ((SColIdx *)ptr)->offset;
|
||||
memcpy(kvRowColVal(nrow, kvRowColIdxAt(nrow, colIdx)), value, diff);
|
||||
pColIdx = kvRowColIdxAt(nrow, oRowCols);
|
||||
pColIdx->colId = colId;
|
||||
pColIdx->offset = kvRowValLen(row);
|
||||
|
||||
for (int i = colIdx; i < kvRowNCols(row); i++) {
|
||||
kvRowColIdxAt(nrow, i + 1)->colId = kvRowColIdxAt(row, i)->colId;
|
||||
kvRowColIdxAt(nrow, i + 1)->offset = kvRowColIdxAt(row, i)->offset + diff;
|
||||
}
|
||||
memcpy(kvRowColVal(nrow, kvRowColIdxAt(nrow, colIdx + 1)), kvRowColVal(row, kvRowColIdxAt(row, colIdx)),
|
||||
POINTER_DISTANCE(kvRowEnd(row), kvRowColVal(row, kvRowColIdxAt(row, colIdx)))
|
||||
memcpy(kvRowColVal(nrow, pColIdx), value, diff); // copy new value
|
||||
|
||||
);
|
||||
}
|
||||
tdSortKVRowByColIdx(nrow);
|
||||
|
||||
*orow = nrow;
|
||||
free(row);
|
||||
|
@ -680,9 +672,8 @@ int tdSetKVRowDataOfCol(SKVRow *orow, int16_t colId, int8_t type, void *value) {
|
|||
|
||||
if (varDataTLen(value) == varDataTLen(pOldVal)) { // just update the column value in place
|
||||
memcpy(pOldVal, value, varDataTLen(value));
|
||||
} else { // need to reallocate the memory
|
||||
uint16_t diff = varDataTLen(value) - varDataTLen(pOldVal);
|
||||
uint16_t nlen = kvRowLen(row) + diff;
|
||||
} else { // need to reallocate the memory
|
||||
int16_t nlen = kvRowLen(row) + (varDataTLen(value) - varDataTLen(pOldVal));
|
||||
ASSERT(nlen > 0);
|
||||
nrow = malloc(nlen);
|
||||
if (nrow == NULL) return -1;
|
||||
|
@ -690,30 +681,22 @@ int tdSetKVRowDataOfCol(SKVRow *orow, int16_t colId, int8_t type, void *value) {
|
|||
kvRowSetLen(nrow, nlen);
|
||||
kvRowSetNCols(nrow, kvRowNCols(row));
|
||||
|
||||
// Copy part ahead
|
||||
nlen = (int16_t)(POINTER_DISTANCE(ptr, kvRowColIdx(row)));
|
||||
ASSERT(nlen % sizeof(SColIdx) == 0);
|
||||
if (nlen > 0) {
|
||||
ASSERT(((SColIdx *)ptr)->offset > 0);
|
||||
memcpy(kvRowColIdx(nrow), kvRowColIdx(row), nlen);
|
||||
memcpy(kvRowValues(nrow), kvRowValues(row), ((SColIdx *)ptr)->offset);
|
||||
int zsize = sizeof(SColIdx) * kvRowNCols(row) + ((SColIdx *)ptr)->offset;
|
||||
memcpy(kvRowColIdx(nrow), kvRowColIdx(row), zsize);
|
||||
memcpy(kvRowColVal(nrow, ((SColIdx *)ptr)), value, varDataTLen(value));
|
||||
// Copy left value part
|
||||
int lsize = kvRowLen(row) - TD_KV_ROW_HEAD_SIZE - zsize - varDataTLen(pOldVal);
|
||||
if (lsize > 0) {
|
||||
memcpy(POINTER_SHIFT(nrow, TD_KV_ROW_HEAD_SIZE + zsize + varDataTLen(value)),
|
||||
POINTER_SHIFT(row, TD_KV_ROW_HEAD_SIZE + zsize + varDataTLen(pOldVal)), lsize);
|
||||
}
|
||||
|
||||
// Construct current column value
|
||||
int colIdx = nlen / sizeof(SColIdx);
|
||||
pColIdx = kvRowColIdxAt(nrow, colIdx);
|
||||
pColIdx->colId = ((SColIdx *)ptr)->colId;
|
||||
pColIdx->offset = ((SColIdx *)ptr)->offset;
|
||||
memcpy(kvRowColVal(nrow, pColIdx), value, varDataTLen(value));
|
||||
|
||||
// Construct columns after
|
||||
if (kvRowNCols(nrow) - colIdx - 1 > 0) {
|
||||
for (int i = colIdx + 1; i < kvRowNCols(nrow); i++) {
|
||||
kvRowColIdxAt(nrow, i)->colId = kvRowColIdxAt(row, i)->colId;
|
||||
kvRowColIdxAt(nrow, i)->offset = kvRowColIdxAt(row, i)->offset + diff;
|
||||
for (int i = 0; i < kvRowNCols(nrow); i++) {
|
||||
pColIdx = kvRowColIdxAt(nrow, i);
|
||||
|
||||
if (pColIdx->offset > ((SColIdx *)ptr)->offset) {
|
||||
pColIdx->offset = pColIdx->offset - varDataTLen(pOldVal) + varDataTLen(value);
|
||||
}
|
||||
memcpy(kvRowColVal(nrow, kvRowColIdxAt(nrow, colIdx + 1)), kvRowColVal(row, kvRowColIdxAt(row, colIdx + 1)),
|
||||
POINTER_DISTANCE(kvRowEnd(row), kvRowColVal(row, kvRowColIdxAt(row, colIdx + 1))));
|
||||
}
|
||||
|
||||
*orow = nrow;
|
||||
|
@ -784,4 +767,97 @@ SKVRow tdGetKVRowFromBuilder(SKVRowBuilder *pBuilder) {
|
|||
memcpy(kvRowValues(row), pBuilder->buf, pBuilder->size);
|
||||
|
||||
return row;
|
||||
}
|
||||
}
|
||||
|
||||
SMemRow mergeTwoMemRows(void *buffer, SMemRow row1, SMemRow row2, STSchema *pSchema1, STSchema *pSchema2) {
|
||||
#if 0
|
||||
ASSERT(memRowKey(row1) == memRowKey(row2));
|
||||
ASSERT(schemaVersion(pSchema1) == memRowVersion(row1));
|
||||
ASSERT(schemaVersion(pSchema2) == memRowVersion(row2));
|
||||
ASSERT(schemaVersion(pSchema1) >= schemaVersion(pSchema2));
|
||||
#endif
|
||||
|
||||
SArray *stashRow = taosArrayInit(pSchema1->numOfCols, sizeof(SColInfo));
|
||||
if (stashRow == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SMemRow pRow = buffer;
|
||||
SDataRow dataRow = memRowDataBody(pRow);
|
||||
memRowSetType(pRow, SMEM_ROW_DATA);
|
||||
dataRowSetVersion(dataRow, schemaVersion(pSchema1)); // use latest schema version
|
||||
dataRowSetLen(dataRow, (TDRowLenT)(TD_DATA_ROW_HEAD_SIZE + pSchema1->flen));
|
||||
|
||||
TDRowTLenT dataLen = 0, kvLen = TD_MEM_ROW_KV_HEAD_SIZE;
|
||||
|
||||
int32_t i = 0; // row1
|
||||
int32_t j = 0; // row2
|
||||
int32_t nCols1 = schemaNCols(pSchema1);
|
||||
int32_t nCols2 = schemaNCols(pSchema2);
|
||||
SColInfo colInfo = {0};
|
||||
int32_t kvIdx1 = 0, kvIdx2 = 0;
|
||||
|
||||
while (i < nCols1) {
|
||||
STColumn *pCol = schemaColAt(pSchema1, i);
|
||||
void * val1 = tdGetMemRowDataOfColEx(row1, pCol->colId, pCol->type, TD_DATA_ROW_HEAD_SIZE + pCol->offset, &kvIdx1);
|
||||
// if val1 != NULL, use val1;
|
||||
if (val1 != NULL && !isNull(val1, pCol->type)) {
|
||||
tdAppendColVal(dataRow, val1, pCol->type, pCol->offset);
|
||||
kvLen += tdGetColAppendLen(SMEM_ROW_KV, val1, pCol->type);
|
||||
setSColInfo(&colInfo, pCol->colId, pCol->type, val1);
|
||||
taosArrayPush(stashRow, &colInfo);
|
||||
++i; // next col
|
||||
continue;
|
||||
}
|
||||
|
||||
void *val2 = NULL;
|
||||
while (j < nCols2) {
|
||||
STColumn *tCol = schemaColAt(pSchema2, j);
|
||||
if (tCol->colId < pCol->colId) {
|
||||
++j;
|
||||
continue;
|
||||
}
|
||||
if (tCol->colId == pCol->colId) {
|
||||
val2 = tdGetMemRowDataOfColEx(row2, tCol->colId, tCol->type, TD_DATA_ROW_HEAD_SIZE + tCol->offset, &kvIdx2);
|
||||
} else if (tCol->colId > pCol->colId) {
|
||||
// set NULL
|
||||
}
|
||||
break;
|
||||
} // end of while(j<nCols2)
|
||||
if (val2 == NULL) {
|
||||
val2 = (void *)getNullValue(pCol->type);
|
||||
}
|
||||
tdAppendColVal(dataRow, val2, pCol->type, pCol->offset);
|
||||
if (!isNull(val2, pCol->type)) {
|
||||
kvLen += tdGetColAppendLen(SMEM_ROW_KV, val2, pCol->type);
|
||||
setSColInfo(&colInfo, pCol->colId, pCol->type, val2);
|
||||
taosArrayPush(stashRow, &colInfo);
|
||||
}
|
||||
|
||||
++i; // next col
|
||||
}
|
||||
|
||||
dataLen = memRowTLen(pRow);
|
||||
|
||||
if (kvLen < dataLen) {
|
||||
// scan stashRow and generate SKVRow
|
||||
memset(buffer, 0, sizeof(dataLen));
|
||||
SMemRow tRow = buffer;
|
||||
memRowSetType(tRow, SMEM_ROW_KV);
|
||||
SKVRow kvRow = (SKVRow)memRowKvBody(tRow);
|
||||
int16_t nKvNCols = (int16_t) taosArrayGetSize(stashRow);
|
||||
kvRowSetLen(kvRow, (TDRowLenT)(TD_KV_ROW_HEAD_SIZE + sizeof(SColIdx) * nKvNCols));
|
||||
kvRowSetNCols(kvRow, nKvNCols);
|
||||
memRowSetKvVersion(tRow, pSchema1->version);
|
||||
|
||||
int32_t toffset = 0;
|
||||
int16_t k;
|
||||
for (k = 0; k < nKvNCols; ++k) {
|
||||
SColInfo *pColInfo = taosArrayGet(stashRow, k);
|
||||
tdAppendKvColVal(kvRow, pColInfo->colVal, pColInfo->colId, pColInfo->colType, &toffset);
|
||||
}
|
||||
ASSERT(kvLen == memRowTLen(tRow));
|
||||
}
|
||||
taosArrayDestroy(stashRow);
|
||||
return buffer;
|
||||
}
|
||||
|
|
|
@ -409,7 +409,7 @@ bool isValidDataType(int32_t type) {
|
|||
return type >= TSDB_DATA_TYPE_NULL && type <= TSDB_DATA_TYPE_UBIGINT;
|
||||
}
|
||||
|
||||
void setVardataNull(char* val, int32_t type) {
|
||||
void setVardataNull(void* val, int32_t type) {
|
||||
if (type == TSDB_DATA_TYPE_BINARY) {
|
||||
varDataSetLen(val, sizeof(int8_t));
|
||||
*(uint8_t*) varDataVal(val) = TSDB_DATA_BINARY_NULL;
|
||||
|
@ -421,75 +421,75 @@ void setVardataNull(char* val, int32_t type) {
|
|||
}
|
||||
}
|
||||
|
||||
void setNull(char *val, int32_t type, int32_t bytes) { setNullN(val, type, bytes, 1); }
|
||||
void setNull(void *val, int32_t type, int32_t bytes) { setNullN(val, type, bytes, 1); }
|
||||
|
||||
void setNullN(char *val, int32_t type, int32_t bytes, int32_t numOfElems) {
|
||||
void setNullN(void *val, int32_t type, int32_t bytes, int32_t numOfElems) {
|
||||
switch (type) {
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
for (int32_t i = 0; i < numOfElems; ++i) {
|
||||
*(uint8_t *)(val + i * tDataTypes[type].bytes) = TSDB_DATA_BOOL_NULL;
|
||||
*(uint8_t *)(POINTER_SHIFT(val, i * tDataTypes[type].bytes)) = TSDB_DATA_BOOL_NULL;
|
||||
}
|
||||
break;
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
for (int32_t i = 0; i < numOfElems; ++i) {
|
||||
*(uint8_t *)(val + i * tDataTypes[type].bytes) = TSDB_DATA_TINYINT_NULL;
|
||||
*(uint8_t *)(POINTER_SHIFT(val, i * tDataTypes[type].bytes)) = TSDB_DATA_TINYINT_NULL;
|
||||
}
|
||||
break;
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
for (int32_t i = 0; i < numOfElems; ++i) {
|
||||
*(uint16_t *)(val + i * tDataTypes[type].bytes) = TSDB_DATA_SMALLINT_NULL;
|
||||
*(uint16_t *)(POINTER_SHIFT(val, i * tDataTypes[type].bytes)) = TSDB_DATA_SMALLINT_NULL;
|
||||
}
|
||||
break;
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
for (int32_t i = 0; i < numOfElems; ++i) {
|
||||
*(uint32_t *)(val + i * tDataTypes[type].bytes) = TSDB_DATA_INT_NULL;
|
||||
*(uint32_t *)(POINTER_SHIFT(val, i * tDataTypes[type].bytes)) = TSDB_DATA_INT_NULL;
|
||||
}
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
for (int32_t i = 0; i < numOfElems; ++i) {
|
||||
*(uint64_t *)(val + i * tDataTypes[type].bytes) = TSDB_DATA_BIGINT_NULL;
|
||||
*(uint64_t *)(POINTER_SHIFT(val, i * tDataTypes[type].bytes)) = TSDB_DATA_BIGINT_NULL;
|
||||
}
|
||||
break;
|
||||
case TSDB_DATA_TYPE_UTINYINT:
|
||||
for (int32_t i = 0; i < numOfElems; ++i) {
|
||||
*(uint8_t *)(val + i * tDataTypes[type].bytes) = TSDB_DATA_UTINYINT_NULL;
|
||||
*(uint8_t *)(POINTER_SHIFT(val, i * tDataTypes[type].bytes)) = TSDB_DATA_UTINYINT_NULL;
|
||||
}
|
||||
break;
|
||||
case TSDB_DATA_TYPE_USMALLINT:
|
||||
for (int32_t i = 0; i < numOfElems; ++i) {
|
||||
*(uint16_t *)(val + i * tDataTypes[type].bytes) = TSDB_DATA_USMALLINT_NULL;
|
||||
*(uint16_t *)(POINTER_SHIFT(val, i * tDataTypes[type].bytes)) = TSDB_DATA_USMALLINT_NULL;
|
||||
}
|
||||
break;
|
||||
case TSDB_DATA_TYPE_UINT:
|
||||
for (int32_t i = 0; i < numOfElems; ++i) {
|
||||
*(uint32_t *)(val + i * tDataTypes[type].bytes) = TSDB_DATA_UINT_NULL;
|
||||
*(uint32_t *)(POINTER_SHIFT(val, i * tDataTypes[type].bytes)) = TSDB_DATA_UINT_NULL;
|
||||
}
|
||||
break;
|
||||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
for (int32_t i = 0; i < numOfElems; ++i) {
|
||||
*(uint64_t *)(val + i * tDataTypes[type].bytes) = TSDB_DATA_UBIGINT_NULL;
|
||||
*(uint64_t *)(POINTER_SHIFT(val, i * tDataTypes[type].bytes)) = TSDB_DATA_UBIGINT_NULL;
|
||||
}
|
||||
break;
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
for (int32_t i = 0; i < numOfElems; ++i) {
|
||||
*(uint32_t *)(val + i * tDataTypes[type].bytes) = TSDB_DATA_FLOAT_NULL;
|
||||
*(uint32_t *)(POINTER_SHIFT(val, i * tDataTypes[type].bytes)) = TSDB_DATA_FLOAT_NULL;
|
||||
}
|
||||
break;
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
for (int32_t i = 0; i < numOfElems; ++i) {
|
||||
*(uint64_t *)(val + i * tDataTypes[type].bytes) = TSDB_DATA_DOUBLE_NULL;
|
||||
*(uint64_t *)(POINTER_SHIFT(val, i * tDataTypes[type].bytes)) = TSDB_DATA_DOUBLE_NULL;
|
||||
}
|
||||
break;
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
for (int32_t i = 0; i < numOfElems; ++i) {
|
||||
setVardataNull(val + i * bytes, type);
|
||||
setVardataNull(POINTER_SHIFT(val, i * bytes), type);
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
for (int32_t i = 0; i < numOfElems; ++i) {
|
||||
*(uint32_t *)(val + i * tDataTypes[TSDB_DATA_TYPE_INT].bytes) = TSDB_DATA_INT_NULL;
|
||||
*(uint32_t *)(POINTER_SHIFT(val, i * tDataTypes[TSDB_DATA_TYPE_INT].bytes)) = TSDB_DATA_INT_NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ IF (TD_MVN_INSTALLED)
|
|||
ADD_CUSTOM_COMMAND(OUTPUT ${JDBC_CMD_NAME}
|
||||
POST_BUILD
|
||||
COMMAND mvn -Dmaven.test.skip=true install -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.33-dist.jar ${LIBRARY_OUTPUT_PATH}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.34-dist.jar ${LIBRARY_OUTPUT_PATH}
|
||||
COMMAND mvn -Dmaven.test.skip=true clean -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml
|
||||
COMMENT "build jdbc driver")
|
||||
ADD_CUSTOM_TARGET(${JDBC_TARGET_NAME} ALL WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} DEPENDS ${JDBC_CMD_NAME})
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
<groupId>com.taosdata.jdbc</groupId>
|
||||
<artifactId>taos-jdbcdriver</artifactId>
|
||||
<version>2.0.33</version>
|
||||
<version>2.0.34</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>JDBCDriver</name>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.taosdata.jdbc</groupId>
|
||||
<artifactId>taos-jdbcdriver</artifactId>
|
||||
<version>2.0.33</version>
|
||||
<version>2.0.34</version>
|
||||
<packaging>jar</packaging>
|
||||
<name>JDBCDriver</name>
|
||||
<url>https://github.com/taosdata/TDengine/tree/master/src/connector/jdbc</url>
|
||||
|
|
|
@ -130,7 +130,7 @@ public abstract class TSDBConstants {
|
|||
case TSDBConstants.TSDB_DATA_TYPE_NCHAR:
|
||||
return Types.NCHAR;
|
||||
}
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE);
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN_TAOS_TYPE);
|
||||
}
|
||||
|
||||
public static String taosType2JdbcTypeName(int taosType) throws SQLException {
|
||||
|
@ -160,7 +160,7 @@ public abstract class TSDBConstants {
|
|||
case TSDBConstants.TSDB_DATA_TYPE_NCHAR:
|
||||
return "NCHAR";
|
||||
default:
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE);
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN_TAOS_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,8 +31,8 @@ public class TSDBError {
|
|||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_URL_NOT_SET, "url is not set");
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_INVALID_SQL, "invalid sql");
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE, "numeric value out of range");
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE, "unknown taos type in tdengine");
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TIMESTAMP_PERCISION, "unknown timestamp precision");
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TAOS_TYPE, "unknown taos type in tdengine");
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TIMESTAMP_PRECISION, "unknown timestamp precision");
|
||||
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN, "unknown error");
|
||||
|
||||
|
|
|
@ -25,8 +25,10 @@ public class TSDBErrorNumbers {
|
|||
public static final int ERROR_URL_NOT_SET = 0x2312; // url is not set
|
||||
public static final int ERROR_INVALID_SQL = 0x2313; // invalid sql
|
||||
public static final int ERROR_NUMERIC_VALUE_OUT_OF_RANGE = 0x2314; // numeric value out of range
|
||||
public static final int ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE = 0x2315; //unknown taos type in tdengine
|
||||
public static final int ERROR_UNKNOWN_TIMESTAMP_PERCISION = 0x2316; // unknown timestamp precision
|
||||
public static final int ERROR_UNKNOWN_TAOS_TYPE = 0x2315; //unknown taos type in tdengine
|
||||
public static final int ERROR_UNKNOWN_TIMESTAMP_PRECISION = 0x2316; // unknown timestamp precision
|
||||
public static final int ERROR_RESTFul_Client_Protocol_Exception = 0x2317;
|
||||
public static final int ERROR_RESTFul_Client_IOException = 0x2318;
|
||||
|
||||
public static final int ERROR_UNKNOWN = 0x2350; //unknown error
|
||||
|
||||
|
@ -62,8 +64,11 @@ public class TSDBErrorNumbers {
|
|||
errorNumbers.add(ERROR_URL_NOT_SET);
|
||||
errorNumbers.add(ERROR_INVALID_SQL);
|
||||
errorNumbers.add(ERROR_NUMERIC_VALUE_OUT_OF_RANGE);
|
||||
errorNumbers.add(ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE);
|
||||
errorNumbers.add(ERROR_UNKNOWN_TIMESTAMP_PERCISION);
|
||||
errorNumbers.add(ERROR_UNKNOWN_TAOS_TYPE);
|
||||
errorNumbers.add(ERROR_UNKNOWN_TIMESTAMP_PRECISION);
|
||||
errorNumbers.add(ERROR_RESTFul_Client_IOException);
|
||||
|
||||
errorNumbers.add(ERROR_RESTFul_Client_Protocol_Exception);
|
||||
|
||||
errorNumbers.add(ERROR_SUBSCRIBE_FAILED);
|
||||
errorNumbers.add(ERROR_UNSUPPORTED_ENCODING);
|
||||
|
|
|
@ -213,7 +213,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
|
|||
long nanoAdjustment = Integer.parseInt(value.substring(20));
|
||||
return Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
|
||||
}
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN_TIMESTAMP_PERCISION);
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN_TIMESTAMP_PRECISION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
package com.taosdata.jdbc.utils;
|
||||
|
||||
import com.taosdata.jdbc.TSDBError;
|
||||
import com.taosdata.jdbc.TSDBErrorNumbers;
|
||||
import org.apache.http.HeaderElement;
|
||||
import org.apache.http.HeaderElementIterator;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.apache.http.client.HttpRequestRetryHandler;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.*;
|
||||
import org.apache.http.client.protocol.HttpClientContext;
|
||||
import org.apache.http.conn.ConnectionKeepAliveStrategy;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.apache.http.message.BasicHeaderElementIterator;
|
||||
|
@ -17,35 +20,24 @@ import org.apache.http.protocol.HTTP;
|
|||
import org.apache.http.protocol.HttpContext;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class HttpClientPoolUtil {
|
||||
|
||||
private static final String DEFAULT_CONTENT_TYPE = "application/json";
|
||||
private static final int DEFAULT_MAX_TOTAL = 200;
|
||||
private static final int DEFAULT_MAX_PER_ROUTE = 20;
|
||||
private static final int DEFAULT_TIME_OUT = 15000;
|
||||
private static final int DEFAULT_MAX_PER_ROUTE = 32;
|
||||
private static final int DEFAULT_MAX_TOTAL = 1000;
|
||||
private static final int DEFAULT_HTTP_KEEP_TIME = 15000;
|
||||
|
||||
private static CloseableHttpClient httpClient;
|
||||
|
||||
private static synchronized void initPools() {
|
||||
if (httpClient == null) {
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
|
||||
connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE);
|
||||
connectionManager.setMaxTotal(DEFAULT_MAX_TOTAL);
|
||||
httpClient = HttpClients.custom()
|
||||
.setKeepAliveStrategy(DEFAULT_KEEP_ALIVE_STRATEGY)
|
||||
.setConnectionManager(connectionManager)
|
||||
.setRetryHandler(new DefaultHttpRequestRetryHandler(3, true))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
private static final int DEFAULT_MAX_RETRY_COUNT = 5;
|
||||
|
||||
private static final ConnectionKeepAliveStrategy DEFAULT_KEEP_ALIVE_STRATEGY = (response, context) -> {
|
||||
HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE));
|
||||
int keepTime = DEFAULT_HTTP_KEEP_TIME * 1000;
|
||||
while (it.hasNext()) {
|
||||
HeaderElement headerElement = it.nextElement();
|
||||
String param = headerElement.getName();
|
||||
|
@ -53,34 +45,73 @@ public class HttpClientPoolUtil {
|
|||
if (value != null && param.equalsIgnoreCase("timeout")) {
|
||||
try {
|
||||
return Long.parseLong(value) * 1000;
|
||||
} catch (Exception e) {
|
||||
new Exception("format KeepAlive timeout exception, exception:" + e.toString()).printStackTrace();
|
||||
} catch (NumberFormatException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return keepTime;
|
||||
return DEFAULT_HTTP_KEEP_TIME * 1000;
|
||||
};
|
||||
|
||||
/**
|
||||
* 执行http post请求
|
||||
* 默认采用Content-Type:application/json,Accept:application/json
|
||||
*
|
||||
* @param uri 请求地址
|
||||
* @param data 请求数据
|
||||
* @return responseBody
|
||||
*/
|
||||
public static String execute(String uri, String data, String token) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
private static final HttpRequestRetryHandler retryHandler = (exception, executionCount, httpContext) -> {
|
||||
if (executionCount >= DEFAULT_MAX_RETRY_COUNT)
|
||||
// do not retry if over max retry count
|
||||
return false;
|
||||
if (exception instanceof InterruptedIOException)
|
||||
// timeout
|
||||
return false;
|
||||
if (exception instanceof UnknownHostException)
|
||||
// unknown host
|
||||
return false;
|
||||
if (exception instanceof SSLException)
|
||||
// SSL handshake exception
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
private static CloseableHttpClient httpClient;
|
||||
|
||||
static {
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
|
||||
connectionManager.setMaxTotal(DEFAULT_MAX_TOTAL);
|
||||
connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE);
|
||||
httpClient = HttpClients.custom().setKeepAliveStrategy(DEFAULT_KEEP_ALIVE_STRATEGY).setConnectionManager(connectionManager).setRetryHandler(retryHandler).build();
|
||||
}
|
||||
|
||||
/*** execute GET request ***/
|
||||
public static String execute(String uri) throws SQLException {
|
||||
HttpEntity httpEntity = null;
|
||||
HttpEntityEnclosingRequestBase method = null;
|
||||
String responseBody = "";
|
||||
try {
|
||||
if (httpClient == null) {
|
||||
initPools();
|
||||
HttpRequestBase method = getRequest(uri, HttpGet.METHOD_NAME);
|
||||
HttpContext context = HttpClientContext.create();
|
||||
CloseableHttpResponse httpResponse = httpClient.execute(method, context);
|
||||
httpEntity = httpResponse.getEntity();
|
||||
if (httpEntity != null) {
|
||||
responseBody = EntityUtils.toString(httpEntity, StandardCharsets.UTF_8);
|
||||
}
|
||||
method = (HttpEntityEnclosingRequestBase) getRequest(uri, HttpPost.METHOD_NAME, DEFAULT_CONTENT_TYPE, 0);
|
||||
method.setHeader("Content-Type", "text/plain");
|
||||
method.setHeader("Connection", "keep-alive");
|
||||
} catch (ClientProtocolException e) {
|
||||
e.printStackTrace();
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESTFul_Client_Protocol_Exception, e.getMessage());
|
||||
} catch (IOException exception) {
|
||||
exception.printStackTrace();
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESTFul_Client_IOException, exception.getMessage());
|
||||
} finally {
|
||||
if (httpEntity != null) {
|
||||
EntityUtils.consumeQuietly(httpEntity);
|
||||
}
|
||||
}
|
||||
return responseBody;
|
||||
}
|
||||
|
||||
|
||||
/*** execute POST request ***/
|
||||
public static String execute(String uri, String data, String token) throws SQLException {
|
||||
HttpEntity httpEntity = null;
|
||||
String responseBody = "";
|
||||
try {
|
||||
HttpEntityEnclosingRequestBase method = (HttpEntityEnclosingRequestBase) getRequest(uri, HttpPost.METHOD_NAME);
|
||||
method.setHeader(HTTP.CONTENT_TYPE, "text/plain");
|
||||
method.setHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_KEEP_ALIVE);
|
||||
method.setHeader("Authorization", "Taosd " + token);
|
||||
|
||||
method.setEntity(new StringEntity(data, StandardCharsets.UTF_8));
|
||||
|
@ -88,46 +119,31 @@ public class HttpClientPoolUtil {
|
|||
CloseableHttpResponse httpResponse = httpClient.execute(method, context);
|
||||
httpEntity = httpResponse.getEntity();
|
||||
if (httpEntity != null) {
|
||||
responseBody = EntityUtils.toString(httpEntity, "UTF-8");
|
||||
responseBody = EntityUtils.toString(httpEntity, StandardCharsets.UTF_8);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (method != null) {
|
||||
method.abort();
|
||||
}
|
||||
new Exception("execute post request exception, url:" + uri + ", exception:" + e.toString() + ", cost time(ms):" + (System.currentTimeMillis() - startTime)).printStackTrace();
|
||||
} catch (ClientProtocolException e) {
|
||||
e.printStackTrace();
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESTFul_Client_Protocol_Exception, e.getMessage());
|
||||
} catch (IOException exception) {
|
||||
exception.printStackTrace();
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESTFul_Client_IOException, exception.getMessage());
|
||||
} finally {
|
||||
if (httpEntity != null) {
|
||||
try {
|
||||
EntityUtils.consumeQuietly(httpEntity);
|
||||
} catch (Exception e) {
|
||||
new Exception("close response exception, url:" + uri + ", exception:" + e.toString() + ", cost time(ms):" + (System.currentTimeMillis() - startTime)).printStackTrace();
|
||||
}
|
||||
EntityUtils.consumeQuietly(httpEntity);
|
||||
}
|
||||
}
|
||||
return responseBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* * 创建请求
|
||||
*
|
||||
* @param uri 请求url
|
||||
* @param methodName 请求的方法类型
|
||||
* @param contentType contentType类型
|
||||
* @param timeout 超时时间
|
||||
* @return HttpRequestBase 返回类型
|
||||
* @author lisc
|
||||
*/
|
||||
private static HttpRequestBase getRequest(String uri, String methodName, String contentType, int timeout) {
|
||||
if (httpClient == null) {
|
||||
initPools();
|
||||
}
|
||||
/*** create http request ***/
|
||||
private static HttpRequestBase getRequest(String uri, String methodName) {
|
||||
HttpRequestBase method;
|
||||
if (timeout <= 0) {
|
||||
timeout = DEFAULT_TIME_OUT;
|
||||
}
|
||||
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeout * 1000)
|
||||
.setConnectTimeout(timeout * 1000).setConnectionRequestTimeout(timeout * 1000)
|
||||
.setExpectContinueEnabled(false).build();
|
||||
RequestConfig requestConfig = RequestConfig.custom()
|
||||
.setSocketTimeout(DEFAULT_TIME_OUT * 1000)
|
||||
.setConnectTimeout(DEFAULT_TIME_OUT * 1000)
|
||||
.setConnectionRequestTimeout(DEFAULT_TIME_OUT * 1000)
|
||||
.setExpectContinueEnabled(false)
|
||||
.build();
|
||||
if (HttpPut.METHOD_NAME.equalsIgnoreCase(methodName)) {
|
||||
method = new HttpPut(uri);
|
||||
} else if (HttpPost.METHOD_NAME.equalsIgnoreCase(methodName)) {
|
||||
|
@ -137,52 +153,10 @@ public class HttpClientPoolUtil {
|
|||
} else {
|
||||
method = new HttpPost(uri);
|
||||
}
|
||||
|
||||
if (contentType == null || contentType.isEmpty() || contentType.replaceAll("\\s", "").isEmpty()) {
|
||||
contentType = DEFAULT_CONTENT_TYPE;
|
||||
}
|
||||
method.addHeader("Content-Type", contentType);
|
||||
method.addHeader("Accept", contentType);
|
||||
method.addHeader(HTTP.CONTENT_TYPE, DEFAULT_CONTENT_TYPE);
|
||||
method.addHeader("Accept", DEFAULT_CONTENT_TYPE);
|
||||
method.setConfig(requestConfig);
|
||||
return method;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行GET 请求
|
||||
*
|
||||
* @param uri 网址
|
||||
* @return responseBody
|
||||
*/
|
||||
public static String execute(String uri) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
HttpEntity httpEntity = null;
|
||||
HttpRequestBase method = null;
|
||||
String responseBody = "";
|
||||
try {
|
||||
if (httpClient == null) {
|
||||
initPools();
|
||||
}
|
||||
method = getRequest(uri, HttpGet.METHOD_NAME, DEFAULT_CONTENT_TYPE, 0);
|
||||
HttpContext context = HttpClientContext.create();
|
||||
CloseableHttpResponse httpResponse = httpClient.execute(method, context);
|
||||
httpEntity = httpResponse.getEntity();
|
||||
if (httpEntity != null) {
|
||||
responseBody = EntityUtils.toString(httpEntity, "UTF-8");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (method != null) {
|
||||
method.abort();
|
||||
}
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (httpEntity != null) {
|
||||
try {
|
||||
EntityUtils.consumeQuietly(httpEntity);
|
||||
} catch (Exception e) {
|
||||
new Exception("close response exception, url:" + uri + ", exception:" + e.toString() + ",cost time(ms):" + (System.currentTimeMillis() - startTime)).printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return responseBody;
|
||||
}
|
||||
}
|
|
@ -245,7 +245,7 @@ static void* telemetryThread(void* param) {
|
|||
clock_gettime(CLOCK_REALTIME, &end);
|
||||
end.tv_sec += 300; // wait 5 minutes before send first report
|
||||
|
||||
setThreadName("telemetryThrd");
|
||||
setThreadName("telemetry");
|
||||
|
||||
while (!tsExit) {
|
||||
int r = 0;
|
||||
|
|
|
@ -118,10 +118,11 @@ static void *dnodeProcessReadQueue(void *wparam) {
|
|||
SVReadMsg * pRead;
|
||||
int32_t qtype;
|
||||
void * pVnode;
|
||||
char name[16];
|
||||
|
||||
memset(name, 0, 16);
|
||||
snprintf(name, 16, "%s-dnReadQ", pPool->name);
|
||||
char* threadname = strcmp(pPool->name, "vquery") == 0? "dnodeQueryQ":"dnodeFetchQ";
|
||||
|
||||
char name[16] = {0};
|
||||
snprintf(name, tListLen(name), "%s", threadname);
|
||||
setThreadName(name);
|
||||
|
||||
while (1) {
|
||||
|
|
|
@ -90,7 +90,6 @@ static void *dnodeOpenVnode(void *param) {
|
|||
char stepDesc[TSDB_STEP_DESC_LEN] = {0};
|
||||
|
||||
dDebug("thread:%d, start to open %d vnodes", pThread->threadIndex, pThread->vnodeNum);
|
||||
|
||||
setThreadName("dnodeOpenVnode");
|
||||
|
||||
for (int32_t v = 0; v < pThread->vnodeNum; ++v) {
|
||||
|
|
|
@ -307,7 +307,7 @@ do { \
|
|||
#define TSDB_DEFAULT_WAL_LEVEL 1
|
||||
|
||||
#define TSDB_MIN_DB_UPDATE 0
|
||||
#define TSDB_MAX_DB_UPDATE 1
|
||||
#define TSDB_MAX_DB_UPDATE 2
|
||||
#define TSDB_DEFAULT_DB_UPDATE_OPTION 0
|
||||
|
||||
#define TSDB_MIN_DB_CACHE_LAST_ROW 0
|
||||
|
@ -435,6 +435,12 @@ typedef enum {
|
|||
TSDB_CHECK_ITEM_MAX
|
||||
} ECheckItemType;
|
||||
|
||||
typedef enum {
|
||||
TD_ROW_DISCARD_UPDATE = 0,
|
||||
TD_ROW_OVERWRITE_UPDATE = 1,
|
||||
TD_ROW_PARTIAL_UPDATE = 2
|
||||
} TDUpdateConfig;
|
||||
|
||||
extern char *qtypeStr[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -809,7 +809,7 @@ typedef struct SMultiTableMeta {
|
|||
int32_t contLen;
|
||||
uint8_t compressed; // denote if compressed or not
|
||||
uint32_t rawLen; // size before compress
|
||||
uint8_t metaClone; // make meta clone after retrieve meta from mnode
|
||||
uint8_t metaClone; // make meta clone after retrieve meta from mnode
|
||||
char meta[];
|
||||
} SMultiTableMeta;
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ typedef struct {
|
|||
uint64_t superUid;
|
||||
STSchema * schema;
|
||||
STSchema * tagSchema;
|
||||
SDataRow tagValues;
|
||||
SKVRow tagValues;
|
||||
char * sql;
|
||||
} STableCfg;
|
||||
|
||||
|
|
|
@ -138,8 +138,10 @@ typedef struct {
|
|||
#define IS_VALID_USMALLINT(_t) ((_t) >= 0 && (_t) < UINT16_MAX)
|
||||
#define IS_VALID_UINT(_t) ((_t) >= 0 && (_t) < UINT32_MAX)
|
||||
#define IS_VALID_UBIGINT(_t) ((_t) >= 0 && (_t) < UINT64_MAX)
|
||||
#define IS_VALID_FLOAT(_t) ((_t) >= -FLT_MAX && (_t) <= FLT_MAX)
|
||||
#define IS_VALID_DOUBLE(_t) ((_t) >= -DBL_MAX && (_t) <= DBL_MAX)
|
||||
|
||||
static FORCE_INLINE bool isNull(const char *val, int32_t type) {
|
||||
static FORCE_INLINE bool isNull(const void *val, int32_t type) {
|
||||
switch (type) {
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
return *(uint8_t *)val == TSDB_DATA_BOOL_NULL;
|
||||
|
@ -191,9 +193,9 @@ extern tDataTypeDescriptor tDataTypes[15];
|
|||
|
||||
bool isValidDataType(int32_t type);
|
||||
|
||||
void setVardataNull(char* val, int32_t type);
|
||||
void setNull(char *val, int32_t type, int32_t bytes);
|
||||
void setNullN(char *val, int32_t type, int32_t bytes, int32_t numOfElems);
|
||||
void setVardataNull(void* val, int32_t type);
|
||||
void setNull(void *val, int32_t type, int32_t bytes);
|
||||
void setNullN(void *val, int32_t type, int32_t bytes, int32_t numOfElems);
|
||||
const void *getNullValue(int32_t type);
|
||||
|
||||
void assignVal(char *val, const char *src, int32_t len, int32_t type);
|
||||
|
|
|
@ -35,6 +35,8 @@ struct Command {
|
|||
};
|
||||
|
||||
extern void backspaceChar(Command *cmd);
|
||||
extern void clearLineBefore(Command *cmd);
|
||||
extern void clearLineAfter(Command *cmd);
|
||||
extern void deleteChar(Command *cmd);
|
||||
extern void moveCursorLeft(Command *cmd);
|
||||
extern void moveCursorRight(Command *cmd);
|
||||
|
|
|
@ -102,6 +102,28 @@ void backspaceChar(Command *cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
void clearLineBefore(Command *cmd) {
|
||||
assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);
|
||||
|
||||
clearScreen(cmd->endOffset + prompt_size, cmd->screenOffset + prompt_size);
|
||||
memmove(cmd->command, cmd->command + cmd->cursorOffset,
|
||||
cmd->commandSize - cmd->cursorOffset);
|
||||
cmd->commandSize -= cmd->cursorOffset;
|
||||
cmd->cursorOffset = 0;
|
||||
cmd->screenOffset = 0;
|
||||
cmd->endOffset = cmd->commandSize;
|
||||
showOnScreen(cmd);
|
||||
}
|
||||
|
||||
void clearLineAfter(Command *cmd) {
|
||||
assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);
|
||||
|
||||
clearScreen(cmd->endOffset + prompt_size, cmd->screenOffset + prompt_size);
|
||||
cmd->commandSize -= cmd->endOffset - cmd->cursorOffset;
|
||||
cmd->endOffset = cmd->cursorOffset;
|
||||
showOnScreen(cmd);
|
||||
}
|
||||
|
||||
void deleteChar(Command *cmd) {
|
||||
assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset);
|
||||
|
||||
|
|
|
@ -238,10 +238,16 @@ int32_t shellReadCommand(TAOS *con, char *command) {
|
|||
updateBuffer(&cmd);
|
||||
}
|
||||
break;
|
||||
case 11: // Ctrl + K;
|
||||
clearLineAfter(&cmd);
|
||||
break;
|
||||
case 12: // Ctrl + L;
|
||||
system("clear");
|
||||
showOnScreen(&cmd);
|
||||
break;
|
||||
case 21: // Ctrl + U
|
||||
clearLineBefore(&cmd);
|
||||
break;
|
||||
}
|
||||
} else if (c == '\033') {
|
||||
c = getchar();
|
||||
|
|
|
@ -238,10 +238,16 @@ int32_t shellReadCommand(TAOS *con, char *command) {
|
|||
updateBuffer(&cmd);
|
||||
}
|
||||
break;
|
||||
case 11: // Ctrl + K;
|
||||
clearLineAfter(&cmd);
|
||||
break;
|
||||
case 12: // Ctrl + L;
|
||||
system("clear");
|
||||
showOnScreen(&cmd);
|
||||
break;
|
||||
case 21: // Ctrl + U;
|
||||
clearLineBefore(&cmd);
|
||||
break;
|
||||
}
|
||||
} else if (c == '\033') {
|
||||
c = (char)getchar();
|
||||
|
|
|
@ -92,7 +92,6 @@ extern char configDir[];
|
|||
#define MAX_SUPER_TABLE_COUNT 200
|
||||
|
||||
#define MAX_QUERY_SQL_COUNT 100
|
||||
#define MAX_QUERY_SQL_LENGTH BUFFER_SIZE
|
||||
|
||||
#define MAX_DATABASE_COUNT 256
|
||||
#define INPUT_BUF_LEN 256
|
||||
|
@ -383,7 +382,7 @@ typedef struct SpecifiedQueryInfo_S {
|
|||
uint64_t queryTimes;
|
||||
bool subscribeRestart;
|
||||
int subscribeKeepProgress;
|
||||
char sql[MAX_QUERY_SQL_COUNT][MAX_QUERY_SQL_LENGTH+1];
|
||||
char sql[MAX_QUERY_SQL_COUNT][BUFFER_SIZE+1];
|
||||
char result[MAX_QUERY_SQL_COUNT][MAX_FILE_NAME_LEN];
|
||||
int resubAfterConsume[MAX_QUERY_SQL_COUNT];
|
||||
int endAfterConsume[MAX_QUERY_SQL_COUNT];
|
||||
|
@ -406,7 +405,7 @@ typedef struct SuperQueryInfo_S {
|
|||
int64_t childTblCount;
|
||||
char childTblPrefix[TBNAME_PREFIX_LEN]; // 20 characters reserved for seq
|
||||
int sqlCount;
|
||||
char sql[MAX_QUERY_SQL_COUNT][MAX_QUERY_SQL_LENGTH+1];
|
||||
char sql[MAX_QUERY_SQL_COUNT][BUFFER_SIZE+1];
|
||||
char result[MAX_QUERY_SQL_COUNT][MAX_FILE_NAME_LEN];
|
||||
int resubAfterConsume;
|
||||
int endAfterConsume;
|
||||
|
@ -648,7 +647,7 @@ static FILE * g_fpOfInsertResult = NULL;
|
|||
fprintf(stderr, "PERF: "fmt, __VA_ARGS__); } while(0)
|
||||
|
||||
#define errorPrint(fmt, ...) \
|
||||
do { fprintf(stderr, "ERROR: "fmt, __VA_ARGS__); } while(0)
|
||||
do { fprintf(stderr, " \033[31m"); fprintf(stderr, "ERROR: "fmt, __VA_ARGS__); fprintf(stderr, " \033[0m"); } while(0)
|
||||
|
||||
// for strncpy buffer overflow
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
|
@ -1253,14 +1252,14 @@ static void fetchResult(TAOS_RES *res, threadInfo* pThreadInfo) {
|
|||
|
||||
// fetch the records row by row
|
||||
while((row = taos_fetch_row(res))) {
|
||||
if (totalLen >= 100*1024*1024 - 32000) {
|
||||
if (totalLen >= (100*1024*1024 - HEAD_BUFF_LEN*2)) {
|
||||
if (strlen(pThreadInfo->filePath) > 0)
|
||||
appendResultBufToFile(databuf, pThreadInfo);
|
||||
totalLen = 0;
|
||||
memset(databuf, 0, 100*1024*1024);
|
||||
}
|
||||
num_rows++;
|
||||
char temp[16000] = {0};
|
||||
char temp[HEAD_BUFF_LEN] = {0};
|
||||
int len = taos_print_row(temp, row, fields, num_fields);
|
||||
len += sprintf(temp + len, "\n");
|
||||
//printf("query result:%s\n", temp);
|
||||
|
@ -2165,15 +2164,15 @@ static void printfDbInfoForQueryToFile(
|
|||
}
|
||||
|
||||
static void printfQuerySystemInfo(TAOS * taos) {
|
||||
char filename[MAX_QUERY_SQL_LENGTH+1] = {0};
|
||||
char buffer[MAX_QUERY_SQL_LENGTH+1] = {0};
|
||||
char filename[BUFFER_SIZE+1] = {0};
|
||||
char buffer[BUFFER_SIZE+1] = {0};
|
||||
TAOS_RES* res;
|
||||
|
||||
time_t t;
|
||||
struct tm* lt;
|
||||
time(&t);
|
||||
lt = localtime(&t);
|
||||
snprintf(filename, MAX_QUERY_SQL_LENGTH, "querySystemInfo-%d-%d-%d %d:%d:%d",
|
||||
snprintf(filename, BUFFER_SIZE, "querySystemInfo-%d-%d-%d %d:%d:%d",
|
||||
lt->tm_year+1900, lt->tm_mon, lt->tm_mday, lt->tm_hour, lt->tm_min,
|
||||
lt->tm_sec);
|
||||
|
||||
|
@ -2205,12 +2204,12 @@ static void printfQuerySystemInfo(TAOS * taos) {
|
|||
printfDbInfoForQueryToFile(filename, dbInfos[i], i);
|
||||
|
||||
// show db.vgroups
|
||||
snprintf(buffer, MAX_QUERY_SQL_LENGTH, "show %s.vgroups;", dbInfos[i]->name);
|
||||
snprintf(buffer, BUFFER_SIZE, "show %s.vgroups;", dbInfos[i]->name);
|
||||
res = taos_query(taos, buffer);
|
||||
xDumpResultToFile(filename, res);
|
||||
|
||||
// show db.stables
|
||||
snprintf(buffer, MAX_QUERY_SQL_LENGTH, "show %s.stables;", dbInfos[i]->name);
|
||||
snprintf(buffer, BUFFER_SIZE, "show %s.stables;", dbInfos[i]->name);
|
||||
res = taos_query(taos, buffer);
|
||||
xDumpResultToFile(filename, res);
|
||||
free(dbInfos[i]);
|
||||
|
@ -4549,7 +4548,7 @@ static bool getMetaFromQueryJsonFile(cJSON* root) {
|
|||
goto PARSE_OVER;
|
||||
}
|
||||
tstrncpy(g_queryInfo.specifiedQueryInfo.sql[j],
|
||||
sqlStr->valuestring, MAX_QUERY_SQL_LENGTH);
|
||||
sqlStr->valuestring, BUFFER_SIZE);
|
||||
|
||||
// default value is -1, which mean infinite loop
|
||||
g_queryInfo.specifiedQueryInfo.endAfterConsume[j] = -1;
|
||||
|
@ -4771,7 +4770,7 @@ static bool getMetaFromQueryJsonFile(cJSON* root) {
|
|||
goto PARSE_OVER;
|
||||
}
|
||||
tstrncpy(g_queryInfo.superQueryInfo.sql[j], sqlStr->valuestring,
|
||||
MAX_QUERY_SQL_LENGTH);
|
||||
BUFFER_SIZE);
|
||||
|
||||
cJSON *result = cJSON_GetObjectItem(sql, "result");
|
||||
if (result != NULL && result->type == cJSON_String
|
||||
|
@ -5156,6 +5155,8 @@ static int32_t execInsert(threadInfo *pThreadInfo, uint32_t k)
|
|||
if (0 != taos_stmt_execute(pThreadInfo->stmt)) {
|
||||
errorPrint("%s() LN%d, failied to execute insert statement. reason: %s\n",
|
||||
__func__, __LINE__, taos_stmt_errstr(pThreadInfo->stmt));
|
||||
|
||||
fprintf(stderr, "\n\033[31m === Please reduce batch number if WAL size exceeds limit. ===\033[0m\n\n");
|
||||
exit(-1);
|
||||
}
|
||||
affectedRows = k;
|
||||
|
@ -7423,14 +7424,14 @@ static void replaceChildTblName(char* inSql, char* outSql, int tblIndex) {
|
|||
|
||||
tstrncpy(outSql, inSql, pos - inSql + 1);
|
||||
//printf("1: %s\n", outSql);
|
||||
strncat(outSql, subTblName, MAX_QUERY_SQL_LENGTH - 1);
|
||||
strncat(outSql, subTblName, BUFFER_SIZE - 1);
|
||||
//printf("2: %s\n", outSql);
|
||||
strncat(outSql, pos+strlen(sourceString), MAX_QUERY_SQL_LENGTH - 1);
|
||||
strncat(outSql, pos+strlen(sourceString), BUFFER_SIZE - 1);
|
||||
//printf("3: %s\n", outSql);
|
||||
}
|
||||
|
||||
static void *superTableQuery(void *sarg) {
|
||||
char sqlstr[MAX_QUERY_SQL_LENGTH];
|
||||
char sqlstr[BUFFER_SIZE];
|
||||
threadInfo *pThreadInfo = (threadInfo *)sarg;
|
||||
|
||||
setThreadName("superTableQuery");
|
||||
|
@ -7733,7 +7734,7 @@ static TAOS_SUB* subscribeImpl(
|
|||
|
||||
static void *superSubscribe(void *sarg) {
|
||||
threadInfo *pThreadInfo = (threadInfo *)sarg;
|
||||
char subSqlstr[MAX_QUERY_SQL_LENGTH];
|
||||
char subSqlstr[BUFFER_SIZE];
|
||||
TAOS_SUB* tsub[MAX_QUERY_SQL_COUNT] = {0};
|
||||
uint64_t tsubSeq;
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ typedef struct {
|
|||
fprintf(stderr, "VERB: "fmt, __VA_ARGS__); } while(0)
|
||||
|
||||
#define errorPrint(fmt, ...) \
|
||||
do { fprintf(stderr, "ERROR: "fmt, __VA_ARGS__); } while(0)
|
||||
do { fprintf(stderr, "\033[31m"); fprintf(stderr, "ERROR: "fmt, __VA_ARGS__); fprintf(stderr, "\033[0m"); } while(0)
|
||||
|
||||
|
||||
// -------------------------- SHOW DATABASE INTERFACE-----------------------
|
||||
|
@ -234,9 +234,9 @@ static struct argp_option options[] = {
|
|||
{"start-time", 'S', "START_TIME", 0, "Start time to dump. Either epoch or ISO8601/RFC3339 format is acceptable. ISO8601 format example: 2017-10-01T18:00:00.000+0800 or 2017-10-0100:00:00.000+0800 or '2017-10-01 00:00:00.000+0800'", 4},
|
||||
{"end-time", 'E', "END_TIME", 0, "End time to dump. Either epoch or ISO8601/RFC3339 format is acceptable. ISO8601 format example: 2017-10-01T18:00:00.000+0800 or 2017-10-0100:00:00.000+0800 or '2017-10-01 00:00:00.000+0800'", 5},
|
||||
#if TSDB_SUPPORT_NANOSECOND == 1
|
||||
{"precision", 'C', "PRECISION", 0, "Epoch precision. Valid value is one of ms, us, and ns. Default is ms.", 6},
|
||||
{"precision", 'C', "PRECISION", 0, "Specify precision for converting human-readable time to epoch. Valid value is one of ms, us, and ns. Default is ms.", 6},
|
||||
#else
|
||||
{"precision", 'C', "PRECISION", 0, "Epoch precision. Valid value is one of ms and us. Default is ms.", 6},
|
||||
{"precision", 'C', "PRECISION", 0, "Use specified precision to convert human-readable time. Valid value is one of ms and us. Default is ms.", 6},
|
||||
#endif
|
||||
{"data-batch", 'B', "DATA_BATCH", 0, "Number of data point per insert statement. Max value is 32766. Default is 1.", 3},
|
||||
{"max-sql-len", 'L', "SQL_LEN", 0, "Max length of one sql. Default is 65480.", 3},
|
||||
|
@ -547,8 +547,8 @@ static void parse_precision_first(
|
|||
free(tmp);
|
||||
exit(-1);
|
||||
}
|
||||
strncpy(g_args.precision, tmp,
|
||||
min(DB_PRECISION_LEN - 1, strlen(tmp)));
|
||||
tstrncpy(g_args.precision, tmp,
|
||||
min(DB_PRECISION_LEN, strlen(tmp) + 1));
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
|
@ -599,6 +599,7 @@ static void parse_timestamp(
|
|||
return;
|
||||
}
|
||||
} else {
|
||||
tstrncpy(arguments->precision, "n/a", strlen("n/a") + 1);
|
||||
tmpEpoch = atoll(tmp);
|
||||
}
|
||||
|
||||
|
@ -794,12 +795,14 @@ static int taosGetTableRecordInfo(
|
|||
while ((row = taos_fetch_row(result)) != NULL) {
|
||||
isSet = true;
|
||||
pTableRecordInfo->isMetric = false;
|
||||
strncpy(pTableRecordInfo->tableRecord.name,
|
||||
tstrncpy(pTableRecordInfo->tableRecord.name,
|
||||
(char *)row[TSDB_SHOW_TABLES_NAME_INDEX],
|
||||
fields[TSDB_SHOW_TABLES_NAME_INDEX].bytes);
|
||||
strncpy(pTableRecordInfo->tableRecord.metric,
|
||||
min(TSDB_TABLE_NAME_LEN,
|
||||
fields[TSDB_SHOW_TABLES_NAME_INDEX].bytes) + 1);
|
||||
tstrncpy(pTableRecordInfo->tableRecord.metric,
|
||||
(char *)row[TSDB_SHOW_TABLES_METRIC_INDEX],
|
||||
fields[TSDB_SHOW_TABLES_METRIC_INDEX].bytes);
|
||||
min(TSDB_TABLE_NAME_LEN,
|
||||
fields[TSDB_SHOW_TABLES_METRIC_INDEX].bytes) + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1080,8 +1083,8 @@ _dump_db_point:
|
|||
goto _exit_failure;
|
||||
}
|
||||
|
||||
strncpy(g_dbInfos[count]->name, (char *)row[TSDB_SHOW_DB_NAME_INDEX],
|
||||
fields[TSDB_SHOW_DB_NAME_INDEX].bytes);
|
||||
tstrncpy(g_dbInfos[count]->name, (char *)row[TSDB_SHOW_DB_NAME_INDEX],
|
||||
min(TSDB_DB_NAME_LEN, fields[TSDB_SHOW_DB_NAME_INDEX].bytes) + 1);
|
||||
if (g_args.with_property) {
|
||||
g_dbInfos[count]->ntables = *((int32_t *)row[TSDB_SHOW_DB_NTABLES_INDEX]);
|
||||
g_dbInfos[count]->vgroups = *((int32_t *)row[TSDB_SHOW_DB_VGROUPS_INDEX]);
|
||||
|
@ -1089,8 +1092,8 @@ _dump_db_point:
|
|||
g_dbInfos[count]->quorum = *((int16_t *)row[TSDB_SHOW_DB_QUORUM_INDEX]);
|
||||
g_dbInfos[count]->days = *((int16_t *)row[TSDB_SHOW_DB_DAYS_INDEX]);
|
||||
|
||||
strncpy(g_dbInfos[count]->keeplist, (char *)row[TSDB_SHOW_DB_KEEP_INDEX],
|
||||
fields[TSDB_SHOW_DB_KEEP_INDEX].bytes);
|
||||
tstrncpy(g_dbInfos[count]->keeplist, (char *)row[TSDB_SHOW_DB_KEEP_INDEX],
|
||||
min(32, fields[TSDB_SHOW_DB_KEEP_INDEX].bytes) + 1);
|
||||
//g_dbInfos[count]->daysToKeep = *((int16_t *)row[TSDB_SHOW_DB_KEEP_INDEX]);
|
||||
//g_dbInfos[count]->daysToKeep1;
|
||||
//g_dbInfos[count]->daysToKeep2;
|
||||
|
@ -1103,8 +1106,8 @@ _dump_db_point:
|
|||
g_dbInfos[count]->comp = (int8_t)(*((int8_t *)row[TSDB_SHOW_DB_COMP_INDEX]));
|
||||
g_dbInfos[count]->cachelast = (int8_t)(*((int8_t *)row[TSDB_SHOW_DB_CACHELAST_INDEX]));
|
||||
|
||||
strncpy(g_dbInfos[count]->precision, (char *)row[TSDB_SHOW_DB_PRECISION_INDEX],
|
||||
fields[TSDB_SHOW_DB_PRECISION_INDEX].bytes);
|
||||
tstrncpy(g_dbInfos[count]->precision, (char *)row[TSDB_SHOW_DB_PRECISION_INDEX],
|
||||
min(8, fields[TSDB_SHOW_DB_PRECISION_INDEX].bytes) + 1);
|
||||
//g_dbInfos[count]->precision = *((int8_t *)row[TSDB_SHOW_DB_PRECISION_INDEX]);
|
||||
g_dbInfos[count]->update = *((int8_t *)row[TSDB_SHOW_DB_UPDATE_INDEX]);
|
||||
}
|
||||
|
@ -1255,17 +1258,19 @@ static int taosGetTableDes(
|
|||
|
||||
tstrncpy(tableDes->name, table, TSDB_TABLE_NAME_LEN);
|
||||
while ((row = taos_fetch_row(res)) != NULL) {
|
||||
strncpy(tableDes->cols[count].field,
|
||||
tstrncpy(tableDes->cols[count].field,
|
||||
(char *)row[TSDB_DESCRIBE_METRIC_FIELD_INDEX],
|
||||
fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes);
|
||||
strncpy(tableDes->cols[count].type,
|
||||
min(TSDB_COL_NAME_LEN + 1,
|
||||
fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes + 1));
|
||||
tstrncpy(tableDes->cols[count].type,
|
||||
(char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX],
|
||||
min(15, fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes));
|
||||
min(16, fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes) + 1);
|
||||
tableDes->cols[count].length =
|
||||
*((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]);
|
||||
strncpy(tableDes->cols[count].note,
|
||||
tstrncpy(tableDes->cols[count].note,
|
||||
(char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX],
|
||||
fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes);
|
||||
min(COL_NOTE_LEN,
|
||||
fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes + 1));
|
||||
|
||||
count++;
|
||||
}
|
||||
|
@ -1700,8 +1705,9 @@ static int32_t taosDumpCreateSuperTableClause(TAOS* taosCon, char* dbName, FILE
|
|||
|
||||
while ((row = taos_fetch_row(res)) != NULL) {
|
||||
memset(&tableRecord, 0, sizeof(STableRecord));
|
||||
strncpy(tableRecord.name, (char *)row[TSDB_SHOW_TABLES_NAME_INDEX],
|
||||
fields[TSDB_SHOW_TABLES_NAME_INDEX].bytes);
|
||||
tstrncpy(tableRecord.name, (char *)row[TSDB_SHOW_TABLES_NAME_INDEX],
|
||||
min(TSDB_TABLE_NAME_LEN,
|
||||
fields[TSDB_SHOW_TABLES_NAME_INDEX].bytes) + 1);
|
||||
taosWrite(fd, &tableRecord, sizeof(STableRecord));
|
||||
}
|
||||
|
||||
|
@ -1775,9 +1781,11 @@ static int taosDumpDb(SDbInfo *dbInfo, FILE *fp, TAOS *taosCon) {
|
|||
while ((row = taos_fetch_row(res)) != NULL) {
|
||||
memset(&tableRecord, 0, sizeof(STableRecord));
|
||||
tstrncpy(tableRecord.name, (char *)row[TSDB_SHOW_TABLES_NAME_INDEX],
|
||||
fields[TSDB_SHOW_TABLES_NAME_INDEX].bytes);
|
||||
min(TSDB_TABLE_NAME_LEN,
|
||||
fields[TSDB_SHOW_TABLES_NAME_INDEX].bytes) + 1);
|
||||
tstrncpy(tableRecord.metric, (char *)row[TSDB_SHOW_TABLES_METRIC_INDEX],
|
||||
min(TSDB_TABLE_NAME_LEN, fields[TSDB_SHOW_TABLES_METRIC_INDEX].bytes));
|
||||
min(TSDB_TABLE_NAME_LEN,
|
||||
fields[TSDB_SHOW_TABLES_METRIC_INDEX].bytes) + 1);
|
||||
|
||||
taosWrite(fd, &tableRecord, sizeof(STableRecord));
|
||||
|
||||
|
@ -2165,7 +2173,7 @@ static int taosCheckParam(struct arguments *arguments) {
|
|||
|
||||
if (g_args.arg_list_len == 0) {
|
||||
if ((!g_args.all_databases) && (!g_args.isDumpIn)) {
|
||||
fprintf(stderr, "taosdump requires parameters\n");
|
||||
errorPrint("%s", "taosdump requires parameters for database and operation\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1812,12 +1812,8 @@ static int32_t getVgroupInfoLength(SSTableVgroupMsg* pInfo, int32_t numOfTable)
|
|||
}
|
||||
|
||||
static char* serializeVgroupInfo(SSTableObj *pTable, char* name, char* msg, SMnodeMsg* pMsgBody, void* handle) {
|
||||
SName sn = {0};
|
||||
tNameFromString(&sn, name, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE);
|
||||
const char* tableName = tNameGetTableName(&sn);
|
||||
|
||||
strncpy(msg, tableName, TSDB_TABLE_NAME_LEN);
|
||||
msg += TSDB_TABLE_NAME_LEN;
|
||||
strncpy(msg, name, TSDB_TABLE_FNAME_LEN);
|
||||
msg += TSDB_TABLE_FNAME_LEN;
|
||||
|
||||
if (pTable->vgHash == NULL) {
|
||||
mDebug("msg:%p, app:%p stable:%s, no vgroup exist while get stable vgroup info", pMsgBody, handle, name);
|
||||
|
|
|
@ -199,7 +199,7 @@ bool gcBuildQueryJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result,
|
|||
|
||||
for (int32_t i = dataFields; i >= 0; i--) {
|
||||
httpJsonItemToken(jsonBuf);
|
||||
if (row[i] == NULL) {
|
||||
if (row == NULL || i >= num_fields || row[i] == NULL) {
|
||||
httpJsonOriginString(jsonBuf, "null", 4);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -264,8 +264,7 @@ void httpJsonUInt64(JsonBuf* buf, uint64_t num) {
|
|||
|
||||
void httpJsonTimestamp(JsonBuf* buf, int64_t t, int32_t timePrecision) {
|
||||
char ts[35] = {0};
|
||||
struct tm* ptm;
|
||||
|
||||
|
||||
int32_t fractionLen;
|
||||
char* format = NULL;
|
||||
time_t quot = 0;
|
||||
|
@ -301,8 +300,9 @@ void httpJsonTimestamp(JsonBuf* buf, int64_t t, int32_t timePrecision) {
|
|||
assert(false);
|
||||
}
|
||||
|
||||
ptm = localtime(");
|
||||
int32_t length = (int32_t)strftime(ts, 35, "%Y-%m-%d %H:%M:%S", ptm);
|
||||
struct tm ptm = {0};
|
||||
localtime_r(", &ptm);
|
||||
int32_t length = (int32_t)strftime(ts, 35, "%Y-%m-%d %H:%M:%S", &ptm);
|
||||
length += snprintf(ts + length, fractionLen, format, mod);
|
||||
|
||||
httpJsonString(buf, ts, length);
|
||||
|
|
|
@ -114,7 +114,7 @@ int32_t monStartSystem() {
|
|||
|
||||
static void *monThreadFunc(void *param) {
|
||||
monDebug("starting to initialize monitor module ...");
|
||||
setThreadName("monThrd");
|
||||
setThreadName("monitor");
|
||||
|
||||
while (1) {
|
||||
static int32_t accessTimes = 0;
|
||||
|
|
|
@ -216,7 +216,7 @@ typedef struct SQueryAttr {
|
|||
bool simpleAgg;
|
||||
bool pointInterpQuery; // point interpolation query
|
||||
bool needReverseScan; // need reverse scan
|
||||
bool distinctTag; // distinct tag query
|
||||
bool distinct; // distinct query or not
|
||||
bool stateWindow; // window State on sub/normal table
|
||||
bool createFilterOperator; // if filter operator is needed
|
||||
int32_t interBufSize; // intermediate buffer sizse
|
||||
|
@ -514,6 +514,7 @@ typedef struct SDistinctOperatorInfo {
|
|||
bool recordNullVal; //has already record the null value, no need to try again
|
||||
int64_t threshold;
|
||||
int64_t outputCapacity;
|
||||
int32_t colIndex;
|
||||
} SDistinctOperatorInfo;
|
||||
|
||||
struct SGlobalMerger;
|
||||
|
|
|
@ -121,7 +121,8 @@ typedef struct SQueryInfo {
|
|||
int64_t vgroupLimit; // table limit in case of super table projection query + global order + limit
|
||||
|
||||
int32_t udColumnId; // current user-defined constant output field column id, monotonically decreases from TSDB_UD_COLUMN_INDEX
|
||||
bool distinctTag; // distinct tag or not
|
||||
bool distinct; // distinct tag or not
|
||||
bool onlyHasTagCond;
|
||||
int32_t round; // 0/1/....
|
||||
int32_t bufLen;
|
||||
char* buf;
|
||||
|
|
|
@ -97,12 +97,47 @@ static UNUSED_FUNC void* u_realloc(void* p, size_t __size) {
|
|||
#define GET_NUM_OF_TABLEGROUP(q) taosArrayGetSize((q)->tableqinfoGroupInfo.pGroupList)
|
||||
#define QUERY_IS_INTERVAL_QUERY(_q) ((_q)->interval.interval > 0)
|
||||
|
||||
#define TSKEY_MAX_ADD(a,b) \
|
||||
do { \
|
||||
if (a < 0) { a = a + b; break;} \
|
||||
if (sizeof(a) == sizeof(int32_t)) { \
|
||||
if((b) > 0 && ((b) >= INT32_MAX - (a))){\
|
||||
a = INT32_MAX; \
|
||||
} else { \
|
||||
a = a + b; \
|
||||
} \
|
||||
} else { \
|
||||
if((b) > 0 && ((b) >= INT64_MAX - (a))){\
|
||||
a = INT64_MAX; \
|
||||
} else { \
|
||||
a = a + b; \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define TSKEY_MIN_SUB(a,b) \
|
||||
do { \
|
||||
if (a >= 0) { a = a + b; break;} \
|
||||
if (sizeof(a) == sizeof(int32_t)){ \
|
||||
if((b) < 0 && ((b) <= INT32_MIN - (a))){\
|
||||
a = INT32_MIN; \
|
||||
} else { \
|
||||
a = a + b; \
|
||||
} \
|
||||
} else { \
|
||||
if((b) < 0 && ((b) <= INT64_MIN-(a))) {\
|
||||
a = INT64_MIN; \
|
||||
} else { \
|
||||
a = a + b; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
uint64_t queryHandleId = 0;
|
||||
|
||||
int32_t getMaximumIdleDurationSec() {
|
||||
return tsShellActivityTimer * 2;
|
||||
}
|
||||
|
||||
int64_t genQueryId(void) {
|
||||
int64_t uid = 0;
|
||||
int64_t did = tsDnodeId;
|
||||
|
@ -149,12 +184,12 @@ static void getNextTimeWindow(SQueryAttr* pQueryAttr, STimeWindow* tw) {
|
|||
int mon = (int)(tm.tm_year * 12 + tm.tm_mon + interval * factor);
|
||||
tm.tm_year = mon / 12;
|
||||
tm.tm_mon = mon % 12;
|
||||
tw->skey = convertTimePrecision(mktime(&tm) * 1000L, TSDB_TIME_PRECISION_MILLI, pQueryAttr->precision);
|
||||
tw->skey = convertTimePrecision((int64_t)mktime(&tm) * 1000L, TSDB_TIME_PRECISION_MILLI, pQueryAttr->precision);
|
||||
|
||||
mon = (int)(mon + interval);
|
||||
tm.tm_year = mon / 12;
|
||||
tm.tm_mon = mon % 12;
|
||||
tw->ekey = convertTimePrecision(mktime(&tm) * 1000L, TSDB_TIME_PRECISION_MILLI, pQueryAttr->precision);
|
||||
tw->ekey = convertTimePrecision((int64_t)mktime(&tm) * 1000L, TSDB_TIME_PRECISION_MILLI, pQueryAttr->precision);
|
||||
|
||||
tw->ekey -= 1;
|
||||
}
|
||||
|
@ -3124,7 +3159,9 @@ void setTagValue(SOperatorInfo* pOperatorInfo, void *pTable, SQLFunctionCtx* pCt
|
|||
|| pLocalExprInfo->base.resType == TSDB_DATA_TYPE_TIMESTAMP) {
|
||||
memcpy(pRuntimeEnv->tagVal + offset, &pCtx[idx].tag.i64, pLocalExprInfo->base.resBytes);
|
||||
} else {
|
||||
memcpy(pRuntimeEnv->tagVal + offset, pCtx[idx].tag.pz, pCtx[idx].tag.nLen);
|
||||
if (pCtx[idx].tag.pz != NULL) {
|
||||
memcpy(pRuntimeEnv->tagVal + offset, pCtx[idx].tag.pz, pCtx[idx].tag.nLen);
|
||||
}
|
||||
}
|
||||
|
||||
offset += pLocalExprInfo->base.resBytes;
|
||||
|
@ -3934,8 +3971,8 @@ static void toSSDataBlock(SGroupResInfo *pGroupResInfo, SQueryRuntimeEnv* pRunti
|
|||
|
||||
// refactor : extract method
|
||||
SColumnInfoData* pInfoData = taosArrayGet(pBlock->pDataBlock, 0);
|
||||
|
||||
if (pInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP) {
|
||||
//add condition (pBlock->info.rows >= 1) just to runtime happy
|
||||
if (pInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP && pBlock->info.rows >= 1) {
|
||||
STimeWindow* w = &pBlock->info.window;
|
||||
w->skey = *(int64_t*)pInfoData->pData;
|
||||
w->ekey = *(int64_t*)(((char*)pInfoData->pData) + TSDB_KEYSIZE * (pBlock->info.rows - 1));
|
||||
|
@ -5273,7 +5310,15 @@ static SSDataBlock* doSTableAggregate(void* param, bool* newgroup) {
|
|||
// the pDataBlock are always the same one, no need to call this again
|
||||
setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order);
|
||||
|
||||
TSKEY key = QUERY_IS_ASC_QUERY(pQueryAttr)? pBlock->info.window.ekey + 1:pBlock->info.window.skey-1;
|
||||
TSKEY key = 0;
|
||||
if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
|
||||
key = pBlock->info.window.ekey;
|
||||
TSKEY_MAX_ADD(key, 1);
|
||||
} else {
|
||||
key = pBlock->info.window.skey;
|
||||
TSKEY_MIN_SUB(key, -1);
|
||||
}
|
||||
|
||||
setExecutionContext(pRuntimeEnv, pInfo, pOperator->numOfOutput, pRuntimeEnv->current->groupIndex, key);
|
||||
doAggregateImpl(pOperator, pQueryAttr->window.skey, pInfo->pCtx, pBlock);
|
||||
}
|
||||
|
@ -6479,7 +6524,7 @@ static SSDataBlock* doTagScan(void* param, bool* newgroup) {
|
|||
pOperator->status = OP_EXEC_DONE;
|
||||
qDebug("QInfo:0x%"PRIx64" create count(tbname) query, res:%d rows:1", GET_QID(pRuntimeEnv), count);
|
||||
} else { // return only the tags|table name etc.
|
||||
SExprInfo* pExprInfo = pOperator->pExpr; // todo use the column list instead of exprinfo
|
||||
SExprInfo* pExprInfo = &pOperator->pExpr[0]; // todo use the column list instead of exprinfo
|
||||
|
||||
count = 0;
|
||||
while(pInfo->curPos < pInfo->totalTables && count < maxNumOfTables) {
|
||||
|
@ -6554,9 +6599,11 @@ static SSDataBlock* hashDistinct(void* param, bool* newgroup) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
SDistinctOperatorInfo* pInfo = pOperator->info;
|
||||
SSDataBlock* pRes = pInfo->pRes;
|
||||
|
||||
|
||||
pRes->info.rows = 0;
|
||||
SSDataBlock* pBlock = NULL;
|
||||
while(1) {
|
||||
|
@ -6565,13 +6612,25 @@ static SSDataBlock* hashDistinct(void* param, bool* newgroup) {
|
|||
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
|
||||
|
||||
if (pBlock == NULL) {
|
||||
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
|
||||
pOperator->status = OP_EXEC_DONE;
|
||||
break;
|
||||
}
|
||||
if (pInfo->colIndex == -1) {
|
||||
for (int i = 0; i < taosArrayGetSize(pBlock->pDataBlock); i++) {
|
||||
SColumnInfoData* pColDataInfo = taosArrayGet(pBlock->pDataBlock, i);
|
||||
if (pColDataInfo->info.colId == pOperator->pExpr[0].base.resColId) {
|
||||
pInfo->colIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pInfo->colIndex == -1) {
|
||||
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
|
||||
pOperator->status = OP_EXEC_DONE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
assert(pBlock->info.numOfCols == 1);
|
||||
SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, 0);
|
||||
SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, pInfo->colIndex);
|
||||
|
||||
int16_t bytes = pColInfoData->info.bytes;
|
||||
int16_t type = pColInfoData->info.type;
|
||||
|
@ -6623,7 +6682,8 @@ static SSDataBlock* hashDistinct(void* param, bool* newgroup) {
|
|||
|
||||
SOperatorInfo* createDistinctOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
|
||||
SDistinctOperatorInfo* pInfo = calloc(1, sizeof(SDistinctOperatorInfo));
|
||||
|
||||
pInfo->colIndex = -1;
|
||||
pInfo->threshold = 10000000; // distinct result threshold
|
||||
pInfo->outputCapacity = 4096;
|
||||
pInfo->pSet = taosHashInit(64, taosGetDefaultHashFunction(pExpr->base.colType), false, HASH_NO_LOCK);
|
||||
pInfo->pRes = createOutputBuf(pExpr, numOfOutput, (int32_t) pInfo->outputCapacity);
|
||||
|
@ -6638,6 +6698,7 @@ SOperatorInfo* createDistinctOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperat
|
|||
pOperator->info = pInfo;
|
||||
pOperator->pRuntimeEnv = pRuntimeEnv;
|
||||
pOperator->exec = hashDistinct;
|
||||
pOperator->pExpr = pExpr;
|
||||
pOperator->cleanup = destroyDistinctOperatorInfo;
|
||||
|
||||
appendUpstream(pOperator, upstream);
|
||||
|
|
|
@ -104,7 +104,7 @@ static SQueryNode* doAddTableColumnNode(SQueryInfo* pQueryInfo, STableMetaInfo*
|
|||
int32_t num = (int32_t) taosArrayGetSize(pExprs);
|
||||
SQueryNode* pNode = createQueryNode(QNODE_TAGSCAN, "TableTagScan", NULL, 0, pExprs->pData, num, info, NULL);
|
||||
|
||||
if (pQueryInfo->distinctTag) {
|
||||
if (pQueryInfo->distinct) {
|
||||
pNode = createQueryNode(QNODE_DISTINCT, "Distinct", &pNode, 1, pExprs->pData, num, info, NULL);
|
||||
}
|
||||
|
||||
|
@ -551,9 +551,11 @@ SArray* createExecOperatorPlan(SQueryAttr* pQueryAttr) {
|
|||
int32_t op = 0;
|
||||
|
||||
if (onlyQueryTags(pQueryAttr)) { // do nothing for tags query
|
||||
op = OP_TagScan;
|
||||
taosArrayPush(plan, &op);
|
||||
if (pQueryAttr->distinctTag) {
|
||||
if (onlyQueryTags(pQueryAttr)) {
|
||||
op = OP_TagScan;
|
||||
taosArrayPush(plan, &op);
|
||||
}
|
||||
if (pQueryAttr->distinct) {
|
||||
op = OP_Distinct;
|
||||
taosArrayPush(plan, &op);
|
||||
}
|
||||
|
@ -630,8 +632,13 @@ SArray* createExecOperatorPlan(SQueryAttr* pQueryAttr) {
|
|||
} else {
|
||||
op = OP_Project;
|
||||
taosArrayPush(plan, &op);
|
||||
if (pQueryAttr->distinct) {
|
||||
op = OP_Distinct;
|
||||
taosArrayPush(plan, &op);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (pQueryAttr->limit.limit > 0 || pQueryAttr->limit.offset > 0) {
|
||||
op = OP_Limit;
|
||||
|
@ -651,7 +658,7 @@ SArray* createGlobalMergePlan(SQueryAttr* pQueryAttr) {
|
|||
int32_t op = OP_MultiwayMergeSort;
|
||||
taosArrayPush(plan, &op);
|
||||
|
||||
if (pQueryAttr->distinctTag) {
|
||||
if (pQueryAttr->distinct) {
|
||||
op = OP_Distinct;
|
||||
taosArrayPush(plan, &op);
|
||||
}
|
||||
|
|
|
@ -342,6 +342,7 @@ int32_t scriptEnvPoolInit() {
|
|||
env->lua_state = createLuaEnv();
|
||||
tdListAppend(pool->scriptEnvs, (void *)(&env));
|
||||
}
|
||||
|
||||
pool->mSize = size;
|
||||
pool->cSize = size;
|
||||
return 0;
|
||||
|
|
|
@ -529,10 +529,9 @@ static void *taosProcessTcpData(void *param) {
|
|||
SFdObj *pFdObj;
|
||||
struct epoll_event events[maxEvents];
|
||||
SRecvInfo recvInfo;
|
||||
char name[16];
|
||||
|
||||
memset(name, 0, sizeof(name));
|
||||
snprintf(name, 16, "%s-tcpData", pThreadObj->label);
|
||||
char name[16] = {0};
|
||||
snprintf(name, tListLen(name), "%s-tcp", pThreadObj->label);
|
||||
setThreadName(name);
|
||||
|
||||
while (1) {
|
||||
|
|
|
@ -48,8 +48,6 @@ static void *sendRequest(void *param) {
|
|||
SInfo *pInfo = (SInfo *)param;
|
||||
SRpcMsg rpcMsg = {0};
|
||||
|
||||
setThreadName("sendCliReq");
|
||||
|
||||
tDebug("thread:%d, start to send request", pInfo->index);
|
||||
|
||||
while ( pInfo->numOfReqs == 0 || pInfo->num < pInfo->numOfReqs) {
|
||||
|
|
|
@ -40,9 +40,7 @@ static int terror = 0;
|
|||
static void *sendRequest(void *param) {
|
||||
SInfo *pInfo = (SInfo *)param;
|
||||
SRpcMsg rpcMsg, rspMsg;
|
||||
|
||||
setThreadName("sendSrvReq");
|
||||
|
||||
|
||||
tDebug("thread:%d, start to send request", pInfo->index);
|
||||
|
||||
while ( pInfo->numOfReqs == 0 || pInfo->num < pInfo->numOfReqs) {
|
||||
|
|
|
@ -415,7 +415,6 @@ static int32_t syncRetrieveDataStepByStep(SSyncPeer *pPeer) {
|
|||
}
|
||||
|
||||
void *syncRetrieveData(void *param) {
|
||||
setThreadName("syncRetrievData");
|
||||
int64_t rid = (int64_t)param;
|
||||
SSyncPeer *pPeer = syncAcquirePeer(rid);
|
||||
if (pPeer == NULL) {
|
||||
|
|
|
@ -48,8 +48,6 @@ void *sendRequest(void *param) {
|
|||
SInfo * pInfo = (SInfo *)param;
|
||||
SRpcMsg rpcMsg = {0};
|
||||
|
||||
setThreadName("sendCliReq");
|
||||
|
||||
uDebug("thread:%d, start to send request", pInfo->index);
|
||||
|
||||
while (pInfo->numOfReqs == 0 || pInfo->num < pInfo->numOfReqs) {
|
||||
|
|
|
@ -178,7 +178,7 @@ void *processWriteQueue(void *param) {
|
|||
int type;
|
||||
void *item;
|
||||
|
||||
setThreadName("writeQ");
|
||||
setThreadName("syncWrite");
|
||||
|
||||
while (1) {
|
||||
int ret = taosReadQitem(qhandle, &type, &item);
|
||||
|
|
|
@ -40,7 +40,7 @@ void tsdbFreeBufPool(STsdbBufPool* pBufPool);
|
|||
int tsdbOpenBufPool(STsdbRepo* pRepo);
|
||||
void tsdbCloseBufPool(STsdbRepo* pRepo);
|
||||
SListNode* tsdbAllocBufBlockFromPool(STsdbRepo* pRepo);
|
||||
int tsdbExpendPool(STsdbRepo* pRepo, int32_t oldTotalBlocks);
|
||||
int tsdbExpandPool(STsdbRepo* pRepo, int32_t oldTotalBlocks);
|
||||
void tsdbRecycleBufferBlock(STsdbBufPool* pPool, SListNode *pNode);
|
||||
|
||||
#endif /* _TD_TSDB_BUFFER_H_ */
|
||||
#endif /* _TD_TSDB_BUFFER_H_ */
|
||||
|
|
|
@ -16,6 +16,13 @@
|
|||
#ifndef _TD_TSDB_READ_IMPL_H_
|
||||
#define _TD_TSDB_READ_IMPL_H_
|
||||
|
||||
#include "tfs.h"
|
||||
#include "tsdb.h"
|
||||
#include "os.h"
|
||||
#include "tsdbFile.h"
|
||||
#include "tskiplist.h"
|
||||
#include "tsdbMeta.h"
|
||||
|
||||
typedef struct SReadH SReadH;
|
||||
|
||||
typedef struct {
|
||||
|
@ -143,4 +150,4 @@ static FORCE_INLINE int tsdbMakeRoom(void **ppBuf, size_t size) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif /*_TD_TSDB_READ_IMPL_H_*/
|
||||
#endif /*_TD_TSDB_READ_IMPL_H_*/
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TSDB_ROW_MERGE_BUF_H
|
||||
#define TSDB_ROW_MERGE_BUF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "tsdb.h"
|
||||
#include "tchecksum.h"
|
||||
#include "tsdbReadImpl.h"
|
||||
|
||||
typedef void* SMergeBuf;
|
||||
|
||||
SDataRow tsdbMergeTwoRows(SMergeBuf *pBuf, SMemRow row1, SMemRow row2, STSchema *pSchema1, STSchema *pSchema2);
|
||||
|
||||
static FORCE_INLINE int tsdbMergeBufMakeSureRoom(SMergeBuf *pBuf, STSchema* pSchema1, STSchema* pSchema2) {
|
||||
return tsdbMakeRoom(pBuf, MAX(dataRowMaxBytesFromSchema(pSchema1), dataRowMaxBytesFromSchema(pSchema2)));
|
||||
}
|
||||
|
||||
static FORCE_INLINE void tsdbFreeMergeBuf(SMergeBuf buf) {
|
||||
taosTZfree(buf);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ifndef TSDB_ROW_MERGE_BUF_H */
|
|
@ -68,6 +68,8 @@ extern "C" {
|
|||
#include "tsdbCompact.h"
|
||||
// Commit Queue
|
||||
#include "tsdbCommitQueue.h"
|
||||
|
||||
#include "tsdbRowMergeBuf.h"
|
||||
// Main definitions
|
||||
struct STsdbRepo {
|
||||
uint8_t state;
|
||||
|
@ -92,6 +94,7 @@ struct STsdbRepo {
|
|||
pthread_mutex_t mutex;
|
||||
bool repoLocked;
|
||||
int32_t code; // Commit code
|
||||
SMergeBuf mergeBuf; //used when update=2
|
||||
bool inCompact; // is in compact process?
|
||||
};
|
||||
|
||||
|
@ -139,4 +142,4 @@ static FORCE_INLINE int tsdbGetNextMaxTables(int tid) {
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TD_TSDB_INT_H_ */
|
||||
#endif /* _TD_TSDB_INT_H_ */
|
||||
|
|
|
@ -159,7 +159,7 @@ _err:
|
|||
|
||||
static void tsdbFreeBufBlock(STsdbBufBlock *pBufBlock) { tfree(pBufBlock); }
|
||||
|
||||
int tsdbExpendPool(STsdbRepo* pRepo, int32_t oldTotalBlocks) {
|
||||
int tsdbExpandPool(STsdbRepo* pRepo, int32_t oldTotalBlocks) {
|
||||
if (oldTotalBlocks == pRepo->config.totalBlocks) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
@ -199,4 +199,4 @@ void tsdbRecycleBufferBlock(STsdbBufPool* pPool, SListNode *pNode) {
|
|||
tsdbFreeBufBlock(pBufBlock);
|
||||
free(pNode);
|
||||
pPool->nBufBlocks--;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1290,7 +1290,7 @@ static void tsdbLoadAndMergeFromCache(SDataCols *pDataCols, int *iter, SCommitIt
|
|||
ASSERT(pSchema != NULL);
|
||||
}
|
||||
|
||||
tdAppendMemRowToDataCol(row, pSchema, pTarget);
|
||||
tdAppendMemRowToDataCol(row, pSchema, pTarget, true);
|
||||
}
|
||||
|
||||
tSkipListIterNext(pCommitIter->pIter);
|
||||
|
@ -1302,7 +1302,7 @@ static void tsdbLoadAndMergeFromCache(SDataCols *pDataCols, int *iter, SCommitIt
|
|||
ASSERT(pSchema != NULL);
|
||||
}
|
||||
|
||||
tdAppendMemRowToDataCol(row, pSchema, pTarget);
|
||||
tdAppendMemRowToDataCol(row, pSchema, pTarget, update == TD_ROW_OVERWRITE_UPDATE);
|
||||
}
|
||||
} else {
|
||||
ASSERT(!isRowDel);
|
||||
|
|
|
@ -138,7 +138,7 @@ static void tsdbApplyRepoConfig(STsdbRepo *pRepo) {
|
|||
pSaveCfg->compression, pSaveCfg->keep,pSaveCfg->keep1, pSaveCfg->keep2,
|
||||
pSaveCfg->totalBlocks, oldCfg.cacheLastRow, pSaveCfg->cacheLastRow, oldTotalBlocks, pSaveCfg->totalBlocks);
|
||||
|
||||
int err = tsdbExpendPool(pRepo, oldTotalBlocks);
|
||||
int err = tsdbExpandPool(pRepo, oldTotalBlocks);
|
||||
if (!TAOS_SUCCEEDED(err)) {
|
||||
tsdbError("vgId:%d expand pool from %d to %d fail,reason:%s",
|
||||
REPO_ID(pRepo), oldTotalBlocks, pSaveCfg->totalBlocks, tstrerror(err));
|
||||
|
|
|
@ -455,7 +455,7 @@ static int tsdbCompactMeta(STsdbRepo *pRepo) {
|
|||
if (pReadh->pDCols[0]->numOfRows - ridx == 0) break;
|
||||
int rowsToMerge = MIN(pReadh->pDCols[0]->numOfRows - ridx, defaultRows - pComph->pDataCols->numOfRows);
|
||||
|
||||
tdMergeDataCols(pComph->pDataCols, pReadh->pDCols[0], rowsToMerge, &ridx);
|
||||
tdMergeDataCols(pComph->pDataCols, pReadh->pDCols[0], rowsToMerge, &ridx, pCfg->update != TD_ROW_PARTIAL_UPDATE);
|
||||
|
||||
if (pComph->pDataCols->numOfRows < defaultRows) {
|
||||
break;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
*/
|
||||
|
||||
// no test file errors here
|
||||
#include "taosdef.h"
|
||||
#include "tsdbint.h"
|
||||
|
||||
#define IS_VALID_PRECISION(precision) \
|
||||
|
@ -106,6 +107,8 @@ STsdbRepo *tsdbOpenRepo(STsdbCfg *pCfg, STsdbAppH *pAppH) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
pRepo->mergeBuf = NULL;
|
||||
|
||||
tsdbStartStream(pRepo);
|
||||
|
||||
tsdbDebug("vgId:%d, TSDB repository opened", REPO_ID(pRepo));
|
||||
|
@ -518,7 +521,8 @@ static int32_t tsdbCheckAndSetDefaultCfg(STsdbCfg *pCfg) {
|
|||
}
|
||||
|
||||
// update check
|
||||
if (pCfg->update != 0) pCfg->update = 1;
|
||||
if (pCfg->update < TD_ROW_DISCARD_UPDATE || pCfg->update > TD_ROW_PARTIAL_UPDATE)
|
||||
pCfg->update = TD_ROW_DISCARD_UPDATE;
|
||||
|
||||
// update cacheLastRow
|
||||
if (pCfg->cacheLastRow != 0) {
|
||||
|
@ -597,6 +601,7 @@ static void tsdbFreeRepo(STsdbRepo *pRepo) {
|
|||
tsdbFreeFS(pRepo->fs);
|
||||
tsdbFreeBufPool(pRepo->pPool);
|
||||
tsdbFreeMeta(pRepo->tsdbMeta);
|
||||
tsdbFreeMergeBuf(pRepo->mergeBuf);
|
||||
// tsdbFreeMemTable(pRepo->mem);
|
||||
// tsdbFreeMemTable(pRepo->imem);
|
||||
tsem_destroy(&(pRepo->readyToCommit));
|
||||
|
@ -722,7 +727,8 @@ static int tsdbRestoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pRea
|
|||
// OK,let's load row from backward to get not-null column
|
||||
for (int32_t rowId = pBlock->numOfRows - 1; rowId >= 0; rowId--) {
|
||||
SDataCol *pDataCol = pReadh->pDCols[0]->cols + i;
|
||||
tdAppendColVal(memRowDataBody(row), tdGetColDataOfRow(pDataCol, rowId), pCol->type, pCol->offset);
|
||||
const void* pColData = tdGetColDataOfRow(pDataCol, rowId);
|
||||
tdAppendColVal(memRowDataBody(row), pColData, pCol->type, pCol->offset);
|
||||
//SDataCol *pDataCol = readh.pDCols[0]->cols + j;
|
||||
void *value = tdGetRowDataOfCol(memRowDataBody(row), (int8_t)pCol->type, TD_DATA_ROW_HEAD_SIZE + pCol->offset);
|
||||
if (isNull(value, pCol->type)) {
|
||||
|
@ -735,11 +741,12 @@ static int tsdbRestoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pRea
|
|||
continue;
|
||||
}
|
||||
// save not-null column
|
||||
uint16_t bytes = IS_VAR_DATA_TYPE(pCol->type) ? varDataTLen(pColData) : pCol->bytes;
|
||||
SDataCol *pLastCol = &(pTable->lastCols[idx]);
|
||||
pLastCol->pData = malloc(pCol->bytes);
|
||||
pLastCol->bytes = pCol->bytes;
|
||||
pLastCol->pData = malloc(bytes);
|
||||
pLastCol->bytes = bytes;
|
||||
pLastCol->colId = pCol->colId;
|
||||
memcpy(pLastCol->pData, value, pCol->bytes);
|
||||
memcpy(pLastCol->pData, value, bytes);
|
||||
|
||||
// save row ts(in column 0)
|
||||
pDataCol = pReadh->pDCols[0]->cols + 0;
|
||||
|
@ -991,4 +998,4 @@ int tsdbCacheLastData(STsdbRepo *pRepo, STsdbCfg* oldCfg) {
|
|||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,11 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "tdataformat.h"
|
||||
#include "tfunctional.h"
|
||||
#include "tsdbint.h"
|
||||
#include "tskiplist.h"
|
||||
#include "tsdbRowMergeBuf.h"
|
||||
|
||||
#define TSDB_DATA_SKIPLIST_LEVEL 5
|
||||
#define TSDB_MAX_INSERT_BATCH 512
|
||||
|
@ -30,24 +34,22 @@ typedef struct {
|
|||
void * pMsg;
|
||||
} SSubmitMsgIter;
|
||||
|
||||
static SMemTable * tsdbNewMemTable(STsdbRepo *pRepo);
|
||||
static void tsdbFreeMemTable(SMemTable *pMemTable);
|
||||
static STableData *tsdbNewTableData(STsdbCfg *pCfg, STable *pTable);
|
||||
static void tsdbFreeTableData(STableData *pTableData);
|
||||
static char * tsdbGetTsTupleKey(const void *data);
|
||||
static SMemTable * tsdbNewMemTable(STsdbRepo *pRepo);
|
||||
static void tsdbFreeMemTable(SMemTable *pMemTable);
|
||||
static STableData* tsdbNewTableData(STsdbCfg *pCfg, STable *pTable);
|
||||
static void tsdbFreeTableData(STableData *pTableData);
|
||||
static char * tsdbGetTsTupleKey(const void *data);
|
||||
static int tsdbAdjustMemMaxTables(SMemTable *pMemTable, int maxTables);
|
||||
static int tsdbAppendTableRowToCols(STable *pTable, SDataCols *pCols, STSchema **ppSchema, SMemRow row);
|
||||
static int tsdbAppendTableRowToCols(STable *pTable, SDataCols *pCols, STSchema **ppSchema, SMemRow row);
|
||||
static int tsdbInitSubmitBlkIter(SSubmitBlk *pBlock, SSubmitBlkIter *pIter);
|
||||
static SMemRow tsdbGetSubmitBlkNext(SSubmitBlkIter *pIter);
|
||||
static SMemRow tsdbGetSubmitBlkNext(SSubmitBlkIter *pIter);
|
||||
static int tsdbScanAndConvertSubmitMsg(STsdbRepo *pRepo, SSubmitMsg *pMsg);
|
||||
static int tsdbInsertDataToTable(STsdbRepo *pRepo, SSubmitBlk *pBlock, int32_t *affectedrows);
|
||||
static int tsdbCopyRowToMem(STsdbRepo *pRepo, SMemRow row, STable *pTable, void **ppRow);
|
||||
static int tsdbInitSubmitMsgIter(SSubmitMsg *pMsg, SSubmitMsgIter *pIter);
|
||||
static int tsdbGetSubmitMsgNext(SSubmitMsgIter *pIter, SSubmitBlk **pPBlock);
|
||||
static int tsdbCheckTableSchema(STsdbRepo *pRepo, SSubmitBlk *pBlock, STable *pTable);
|
||||
static int tsdbInsertDataToTableImpl(STsdbRepo *pRepo, STable *pTable, void **rows, int rowCounter);
|
||||
static void tsdbFreeRows(STsdbRepo *pRepo, void **rows, int rowCounter);
|
||||
static int tsdbUpdateTableLatestInfo(STsdbRepo *pRepo, STable *pTable, SMemRow row);
|
||||
static int tsdbUpdateTableLatestInfo(STsdbRepo *pRepo, STable *pTable, SMemRow row);
|
||||
|
||||
static FORCE_INLINE int tsdbCheckRowRange(STsdbRepo *pRepo, STable *pTable, SMemRow row, TSKEY minKey, TSKEY maxKey,
|
||||
TSKEY now);
|
||||
|
||||
|
@ -342,7 +344,7 @@ int tsdbSyncCommit(STsdbRepo *repo) {
|
|||
* 3. rowsIncreased = rowsInserted - rowsDeleteSucceed >= maxRowsToRead
|
||||
* 4. operations in pCols not exceeds its max capacity if pCols is given
|
||||
*
|
||||
* The function tries to procceed AS MUSH AS POSSIBLE.
|
||||
* The function tries to procceed AS MUCH AS POSSIBLE.
|
||||
*/
|
||||
int tsdbLoadDataFromCache(STable *pTable, SSkipListIterator *pIter, TSKEY maxKey, int maxRowsToRead, SDataCols *pCols,
|
||||
TKEY *filterKeys, int nFilterKeys, bool keepDup, SMergeInfo *pMergeInfo) {
|
||||
|
@ -523,9 +525,15 @@ static STableData *tsdbNewTableData(STsdbCfg *pCfg, STable *pTable) {
|
|||
pTableData->keyLast = 0;
|
||||
pTableData->numOfRows = 0;
|
||||
|
||||
uint8_t skipListCreateFlags;
|
||||
if(pCfg->update == TD_ROW_DISCARD_UPDATE)
|
||||
skipListCreateFlags = SL_DISCARD_DUP_KEY;
|
||||
else
|
||||
skipListCreateFlags = SL_UPDATE_DUP_KEY;
|
||||
|
||||
pTableData->pData =
|
||||
tSkipListCreate(TSDB_DATA_SKIPLIST_LEVEL, TSDB_DATA_TYPE_TIMESTAMP, TYPE_BYTES[TSDB_DATA_TYPE_TIMESTAMP],
|
||||
tkeyComparFn, pCfg->update ? SL_UPDATE_DUP_KEY : SL_DISCARD_DUP_KEY, tsdbGetTsTupleKey);
|
||||
tkeyComparFn, skipListCreateFlags, tsdbGetTsTupleKey);
|
||||
if (pTableData->pData == NULL) {
|
||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
||||
free(pTableData);
|
||||
|
@ -581,7 +589,7 @@ static int tsdbAppendTableRowToCols(STable *pTable, SDataCols *pCols, STSchema *
|
|||
}
|
||||
}
|
||||
|
||||
tdAppendMemRowToDataCol(row, *ppSchema, pCols);
|
||||
tdAppendMemRowToDataCol(row, *ppSchema, pCols, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -693,45 +701,152 @@ static int tsdbScanAndConvertSubmitMsg(STsdbRepo *pRepo, SSubmitMsg *pMsg) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int tsdbInsertDataToTable(STsdbRepo *pRepo, SSubmitBlk *pBlock, int32_t *affectedrows) {
|
||||
STsdbMeta * pMeta = pRepo->tsdbMeta;
|
||||
int64_t points = 0;
|
||||
STable * pTable = NULL;
|
||||
SSubmitBlkIter blkIter = {0};
|
||||
SMemRow row = NULL;
|
||||
void * rows[TSDB_MAX_INSERT_BATCH] = {0};
|
||||
int rowCounter = 0;
|
||||
//row1 has higher priority
|
||||
static SMemRow tsdbInsertDupKeyMerge(SMemRow row1, SMemRow row2, STsdbRepo* pRepo, STSchema **ppSchema1, STSchema **ppSchema2, STable* pTable, int32_t* pAffectedRows, int64_t* pPoints, SMemRow* pLastRow) {
|
||||
|
||||
//for compatiblity, duplicate key inserted when update=0 should be also calculated as affected rows!
|
||||
if(row1 == NULL && row2 == NULL && pRepo->config.update == TD_ROW_DISCARD_UPDATE) {
|
||||
(*pAffectedRows)++;
|
||||
(*pPoints)++;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ASSERT(pBlock->tid < pMeta->maxTables);
|
||||
pTable = pMeta->tables[pBlock->tid];
|
||||
ASSERT(pTable != NULL && TABLE_UID(pTable) == pBlock->uid);
|
||||
if(row2 == NULL || pRepo->config.update != TD_ROW_PARTIAL_UPDATE) {
|
||||
void* pMem = tsdbAllocBytes(pRepo, memRowTLen(row1));
|
||||
if(pMem == NULL) return NULL;
|
||||
memRowCpy(pMem, row1);
|
||||
(*pAffectedRows)++;
|
||||
(*pPoints)++;
|
||||
*pLastRow = pMem;
|
||||
return pMem;
|
||||
}
|
||||
|
||||
tsdbInitSubmitBlkIter(pBlock, &blkIter);
|
||||
while ((row = tsdbGetSubmitBlkNext(&blkIter)) != NULL) {
|
||||
if (tsdbCopyRowToMem(pRepo, row, pTable, &(rows[rowCounter])) < 0) {
|
||||
tsdbFreeRows(pRepo, rows, rowCounter);
|
||||
goto _err;
|
||||
STSchema *pSchema1 = *ppSchema1;
|
||||
STSchema *pSchema2 = *ppSchema2;
|
||||
SMergeBuf * pBuf = &pRepo->mergeBuf;
|
||||
int dv1 = memRowVersion(row1);
|
||||
int dv2 = memRowVersion(row2);
|
||||
if(pSchema1 == NULL || schemaVersion(pSchema1) != dv1) {
|
||||
if(pSchema2 != NULL && schemaVersion(pSchema2) == dv1) {
|
||||
*ppSchema1 = pSchema2;
|
||||
} else {
|
||||
*ppSchema1 = tsdbGetTableSchemaImpl(pTable, false, false, memRowVersion(row1));
|
||||
}
|
||||
pSchema1 = *ppSchema1;
|
||||
}
|
||||
|
||||
(*affectedrows)++;
|
||||
points++;
|
||||
|
||||
if (rows[rowCounter] != NULL) {
|
||||
rowCounter++;
|
||||
}
|
||||
|
||||
if (rowCounter == TSDB_MAX_INSERT_BATCH) {
|
||||
if (tsdbInsertDataToTableImpl(pRepo, pTable, rows, rowCounter) < 0) {
|
||||
goto _err;
|
||||
}
|
||||
|
||||
rowCounter = 0;
|
||||
memset(rows, 0, sizeof(rows));
|
||||
if(pSchema2 == NULL || schemaVersion(pSchema2) != dv2) {
|
||||
if(schemaVersion(pSchema1) == dv2) {
|
||||
pSchema2 = pSchema1;
|
||||
} else {
|
||||
*ppSchema2 = tsdbGetTableSchemaImpl(pTable, false, false, memRowVersion(row2));
|
||||
pSchema2 = *ppSchema2;
|
||||
}
|
||||
}
|
||||
|
||||
if (rowCounter > 0 && tsdbInsertDataToTableImpl(pRepo, pTable, rows, rowCounter) < 0) {
|
||||
goto _err;
|
||||
SMemRow tmp = tsdbMergeTwoRows(pBuf, row1, row2, pSchema1, pSchema2);
|
||||
|
||||
void* pMem = tsdbAllocBytes(pRepo, memRowTLen(tmp));
|
||||
if(pMem == NULL) return NULL;
|
||||
memRowCpy(pMem, tmp);
|
||||
|
||||
(*pAffectedRows)++;
|
||||
(*pPoints)++;
|
||||
|
||||
*pLastRow = pMem;
|
||||
return pMem;
|
||||
}
|
||||
|
||||
static void* tsdbInsertDupKeyMergePacked(void** args) {
|
||||
return tsdbInsertDupKeyMerge(args[0], args[1], args[2], (STSchema**)&args[3], (STSchema**)&args[4], args[5], args[6], args[7], args[8]);
|
||||
}
|
||||
|
||||
static void tsdbSetupSkipListHookFns(SSkipList* pSkipList, STsdbRepo *pRepo, STable *pTable, int32_t* pAffectedRows, int64_t* pPoints, SMemRow* pLastRow) {
|
||||
|
||||
if(pSkipList->insertHandleFn == NULL) {
|
||||
tGenericSavedFunc *dupHandleSavedFunc = genericSavedFuncInit((GenericVaFunc)&tsdbInsertDupKeyMergePacked, 9);
|
||||
dupHandleSavedFunc->args[2] = pRepo;
|
||||
dupHandleSavedFunc->args[3] = NULL;
|
||||
dupHandleSavedFunc->args[4] = NULL;
|
||||
dupHandleSavedFunc->args[5] = pTable;
|
||||
dupHandleSavedFunc->args[6] = pAffectedRows;
|
||||
dupHandleSavedFunc->args[7] = pPoints;
|
||||
dupHandleSavedFunc->args[8] = pLastRow;
|
||||
pSkipList->insertHandleFn = dupHandleSavedFunc;
|
||||
}
|
||||
}
|
||||
|
||||
static int tsdbInsertDataToTable(STsdbRepo* pRepo, SSubmitBlk* pBlock, int32_t *pAffectedRows) {
|
||||
|
||||
STsdbMeta *pMeta = pRepo->tsdbMeta;
|
||||
int64_t points = 0;
|
||||
STable *pTable = NULL;
|
||||
SSubmitBlkIter blkIter = {0};
|
||||
SMemTable *pMemTable = NULL;
|
||||
STableData *pTableData = NULL;
|
||||
STsdbCfg *pCfg = &(pRepo->config);
|
||||
|
||||
tsdbInitSubmitBlkIter(pBlock, &blkIter);
|
||||
if(blkIter.row == NULL) return 0;
|
||||
TSKEY firstRowKey = memRowKey(blkIter.row);
|
||||
|
||||
tsdbAllocBytes(pRepo, 0);
|
||||
pMemTable = pRepo->mem;
|
||||
|
||||
ASSERT(pMemTable != NULL);
|
||||
ASSERT(pBlock->tid < pMeta->maxTables);
|
||||
|
||||
pTable = pMeta->tables[pBlock->tid];
|
||||
|
||||
ASSERT(pTable != NULL && TABLE_UID(pTable) == pBlock->uid);
|
||||
|
||||
|
||||
if (TABLE_TID(pTable) >= pMemTable->maxTables) {
|
||||
if (tsdbAdjustMemMaxTables(pMemTable, pMeta->maxTables) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
pTableData = pMemTable->tData[TABLE_TID(pTable)];
|
||||
|
||||
if (pTableData == NULL || pTableData->uid != TABLE_UID(pTable)) {
|
||||
if (pTableData != NULL) {
|
||||
taosWLockLatch(&(pMemTable->latch));
|
||||
pMemTable->tData[TABLE_TID(pTable)] = NULL;
|
||||
tsdbFreeTableData(pTableData);
|
||||
taosWUnLockLatch(&(pMemTable->latch));
|
||||
}
|
||||
|
||||
pTableData = tsdbNewTableData(pCfg, pTable);
|
||||
if (pTableData == NULL) {
|
||||
tsdbError("vgId:%d failed to insert data to table %s uid %" PRId64 " tid %d since %s", REPO_ID(pRepo),
|
||||
TABLE_CHAR_NAME(pTable), TABLE_UID(pTable), TABLE_TID(pTable), tstrerror(terrno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
pRepo->mem->tData[TABLE_TID(pTable)] = pTableData;
|
||||
}
|
||||
|
||||
ASSERT((pTableData != NULL) && pTableData->uid == TABLE_UID(pTable));
|
||||
|
||||
SMemRow lastRow = NULL;
|
||||
int64_t osize = SL_SIZE(pTableData->pData);
|
||||
tsdbSetupSkipListHookFns(pTableData->pData, pRepo, pTable, pAffectedRows, &points, &lastRow);
|
||||
tSkipListPutBatchByIter(pTableData->pData, &blkIter, (iter_next_fn_t)tsdbGetSubmitBlkNext);
|
||||
int64_t dsize = SL_SIZE(pTableData->pData) - osize;
|
||||
|
||||
|
||||
if(lastRow != NULL) {
|
||||
TSKEY lastRowKey = memRowKey(lastRow);
|
||||
if (pMemTable->keyFirst > firstRowKey) pMemTable->keyFirst = firstRowKey;
|
||||
pMemTable->numOfRows += dsize;
|
||||
|
||||
if (pTableData->keyFirst > firstRowKey) pTableData->keyFirst = firstRowKey;
|
||||
pTableData->numOfRows += dsize;
|
||||
if (pMemTable->keyLast < lastRowKey) pMemTable->keyLast = lastRowKey;
|
||||
if (pTableData->keyLast < lastRowKey) pTableData->keyLast = lastRowKey;
|
||||
if (tsdbUpdateTableLatestInfo(pRepo, pTable, lastRow) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
STSchema *pSchema = tsdbGetTableSchemaByVersion(pTable, pBlock->sversion);
|
||||
|
@ -739,48 +854,8 @@ static int tsdbInsertDataToTable(STsdbRepo *pRepo, SSubmitBlk *pBlock, int32_t *
|
|||
pRepo->stat.totalStorage += points * schemaVLen(pSchema);
|
||||
|
||||
return 0;
|
||||
|
||||
_err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int tsdbCopyRowToMem(STsdbRepo *pRepo, SMemRow row, STable *pTable, void **ppRow) {
|
||||
STsdbCfg * pCfg = &pRepo->config;
|
||||
TKEY tkey = memRowTKey(row);
|
||||
TSKEY key = memRowKey(row);
|
||||
bool isRowDelete = TKEY_IS_DELETED(tkey);
|
||||
|
||||
if (isRowDelete) {
|
||||
if (!pCfg->update) {
|
||||
tsdbWarn("vgId:%d vnode is not allowed to update but try to delete a data row", REPO_ID(pRepo));
|
||||
terrno = TSDB_CODE_TDB_INVALID_ACTION;
|
||||
return -1;
|
||||
}
|
||||
|
||||
TSKEY lastKey = tsdbGetTableLastKeyImpl(pTable);
|
||||
if (key > lastKey) {
|
||||
tsdbTrace("vgId:%d skip to delete row key %" PRId64 " which is larger than table lastKey %" PRId64,
|
||||
REPO_ID(pRepo), key, lastKey);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void *pRow = tsdbAllocBytes(pRepo, memRowTLen(row));
|
||||
if (pRow == NULL) {
|
||||
tsdbError("vgId:%d failed to insert row with key %" PRId64 " to table %s while allocate %" PRIu32 " bytes since %s",
|
||||
REPO_ID(pRepo), key, TABLE_CHAR_NAME(pTable), memRowTLen(row), tstrerror(terrno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
memRowCpy(pRow, row);
|
||||
ppRow[0] = pRow; // save the memory address of data rows
|
||||
|
||||
tsdbTrace("vgId:%d a row is %s table %s tid %d uid %" PRIu64 " key %" PRIu64, REPO_ID(pRepo),
|
||||
isRowDelete ? "deleted from" : "updated in", TABLE_CHAR_NAME(pTable), TABLE_TID(pTable), TABLE_UID(pTable),
|
||||
key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tsdbInitSubmitMsgIter(SSubmitMsg *pMsg, SSubmitMsgIter *pIter) {
|
||||
if (pMsg == NULL) {
|
||||
|
@ -889,106 +964,6 @@ static int tsdbCheckTableSchema(STsdbRepo *pRepo, SSubmitBlk *pBlock, STable *pT
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int tsdbInsertDataToTableImpl(STsdbRepo *pRepo, STable *pTable, void **rows, int rowCounter) {
|
||||
if (rowCounter < 1) return 0;
|
||||
|
||||
SMemTable * pMemTable = NULL;
|
||||
STableData *pTableData = NULL;
|
||||
STsdbMeta * pMeta = pRepo->tsdbMeta;
|
||||
STsdbCfg * pCfg = &(pRepo->config);
|
||||
|
||||
ASSERT(pRepo->mem != NULL);
|
||||
pMemTable = pRepo->mem;
|
||||
|
||||
if (TABLE_TID(pTable) >= pMemTable->maxTables) {
|
||||
if (tsdbAdjustMemMaxTables(pMemTable, pMeta->maxTables) < 0) {
|
||||
tsdbFreeRows(pRepo, rows, rowCounter);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
pTableData = pMemTable->tData[TABLE_TID(pTable)];
|
||||
|
||||
if (pTableData == NULL || pTableData->uid != TABLE_UID(pTable)) {
|
||||
if (pTableData != NULL) {
|
||||
taosWLockLatch(&(pMemTable->latch));
|
||||
pMemTable->tData[TABLE_TID(pTable)] = NULL;
|
||||
tsdbFreeTableData(pTableData);
|
||||
taosWUnLockLatch(&(pMemTable->latch));
|
||||
}
|
||||
|
||||
pTableData = tsdbNewTableData(pCfg, pTable);
|
||||
if (pTableData == NULL) {
|
||||
tsdbError("vgId:%d failed to insert data to table %s uid %" PRId64 " tid %d since %s", REPO_ID(pRepo),
|
||||
TABLE_CHAR_NAME(pTable), TABLE_UID(pTable), TABLE_TID(pTable), tstrerror(terrno));
|
||||
tsdbFreeRows(pRepo, rows, rowCounter);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pRepo->mem->tData[TABLE_TID(pTable)] = pTableData;
|
||||
}
|
||||
|
||||
ASSERT((pTableData != NULL) && pTableData->uid == TABLE_UID(pTable));
|
||||
|
||||
int64_t osize = SL_SIZE(pTableData->pData);
|
||||
tSkipListPutBatch(pTableData->pData, rows, rowCounter);
|
||||
int64_t dsize = SL_SIZE(pTableData->pData) - osize;
|
||||
TSKEY keyFirstRow = memRowKey(rows[0]);
|
||||
TSKEY keyLastRow = memRowKey(rows[rowCounter - 1]);
|
||||
|
||||
if (pMemTable->keyFirst > keyFirstRow) pMemTable->keyFirst = keyFirstRow;
|
||||
if (pMemTable->keyLast < keyLastRow) pMemTable->keyLast = keyLastRow;
|
||||
pMemTable->numOfRows += dsize;
|
||||
|
||||
if (pTableData->keyFirst > keyFirstRow) pTableData->keyFirst = keyFirstRow;
|
||||
if (pTableData->keyLast < keyLastRow) pTableData->keyLast = keyLastRow;
|
||||
pTableData->numOfRows += dsize;
|
||||
|
||||
// update table latest info
|
||||
if (tsdbUpdateTableLatestInfo(pRepo, pTable, rows[rowCounter - 1]) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tsdbFreeRows(STsdbRepo *pRepo, void **rows, int rowCounter) {
|
||||
ASSERT(pRepo->mem != NULL);
|
||||
STsdbBufPool *pBufPool = pRepo->pPool;
|
||||
|
||||
for (int i = rowCounter - 1; i >= 0; --i) {
|
||||
SMemRow row = (SMemRow)rows[i];
|
||||
int bytes = (int)memRowTLen(row);
|
||||
|
||||
if (pRepo->mem->extraBuffList == NULL) {
|
||||
STsdbBufBlock *pBufBlock = tsdbGetCurrBufBlock(pRepo);
|
||||
ASSERT(pBufBlock != NULL && pBufBlock->offset >= bytes);
|
||||
|
||||
pBufBlock->offset -= bytes;
|
||||
pBufBlock->remain += bytes;
|
||||
ASSERT(row == POINTER_SHIFT(pBufBlock->data, pBufBlock->offset));
|
||||
tsdbTrace("vgId:%d free %d bytes to TSDB buffer pool, nBlocks %d offset %d remain %d", REPO_ID(pRepo), bytes,
|
||||
listNEles(pRepo->mem->bufBlockList), pBufBlock->offset, pBufBlock->remain);
|
||||
|
||||
if (pBufBlock->offset == 0) { // return the block to buffer pool
|
||||
if (tsdbLockRepo(pRepo) < 0) return;
|
||||
SListNode *pNode = tdListPopTail(pRepo->mem->bufBlockList);
|
||||
tdListPrependNode(pBufPool->bufBlockList, pNode);
|
||||
if (tsdbUnlockRepo(pRepo) < 0) return;
|
||||
}
|
||||
} else {
|
||||
ASSERT(listNEles(pRepo->mem->extraBuffList) > 0);
|
||||
SListNode *pNode = tdListPopTail(pRepo->mem->extraBuffList);
|
||||
ASSERT(row == pNode->data);
|
||||
free(pNode);
|
||||
tsdbTrace("vgId:%d free %d bytes to SYSTEM buffer pool", REPO_ID(pRepo), bytes);
|
||||
|
||||
if (listNEles(pRepo->mem->extraBuffList) == 0) {
|
||||
tdListFree(pRepo->mem->extraBuffList);
|
||||
pRepo->mem->extraBuffList = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void updateTableLatestColumn(STsdbRepo *pRepo, STable *pTable, SMemRow row) {
|
||||
tsdbDebug("vgId:%d updateTableLatestColumn, %s row version:%d", REPO_ID(pRepo), pTable->name->data,
|
||||
|
@ -1005,8 +980,8 @@ static void updateTableLatestColumn(STsdbRepo *pRepo, STable *pTable, SMemRow ro
|
|||
}
|
||||
|
||||
SDataCol *pLatestCols = pTable->lastCols;
|
||||
int32_t kvIdx = 0;
|
||||
|
||||
bool isDataRow = isDataRow(row);
|
||||
for (int16_t j = 0; j < schemaNCols(pSchema); j++) {
|
||||
STColumn *pTCol = schemaColAt(pSchema, j);
|
||||
// ignore not exist colId
|
||||
|
@ -1017,16 +992,8 @@ static void updateTableLatestColumn(STsdbRepo *pRepo, STable *pTable, SMemRow ro
|
|||
|
||||
void *value = NULL;
|
||||
|
||||
if (isDataRow) {
|
||||
value = tdGetRowDataOfCol(memRowDataBody(row), (int8_t)pTCol->type,
|
||||
TD_DATA_ROW_HEAD_SIZE + pSchema->columns[j].offset);
|
||||
} else {
|
||||
// SKVRow
|
||||
SColIdx *pColIdx = tdGetKVRowIdxOfCol(memRowKvBody(row), pTCol->colId);
|
||||
if (pColIdx) {
|
||||
value = tdGetKvRowDataOfCol(memRowKvBody(row), pColIdx->offset);
|
||||
}
|
||||
}
|
||||
value = tdGetMemRowDataOfColEx(row, pTCol->colId, (int8_t)pTCol->type,
|
||||
TD_DATA_ROW_HEAD_SIZE + pSchema->columns[j].offset, &kvIdx);
|
||||
|
||||
if ((value == NULL) || isNull(value, pTCol->type)) {
|
||||
continue;
|
||||
|
@ -1034,14 +1001,17 @@ static void updateTableLatestColumn(STsdbRepo *pRepo, STable *pTable, SMemRow ro
|
|||
|
||||
SDataCol *pDataCol = &(pLatestCols[idx]);
|
||||
if (pDataCol->pData == NULL) {
|
||||
pDataCol->pData = malloc(pSchema->columns[j].bytes);
|
||||
pDataCol->bytes = pSchema->columns[j].bytes;
|
||||
} else if (pDataCol->bytes < pSchema->columns[j].bytes) {
|
||||
pDataCol->pData = realloc(pDataCol->pData, pSchema->columns[j].bytes);
|
||||
pDataCol->bytes = pSchema->columns[j].bytes;
|
||||
pDataCol->pData = malloc(pTCol->bytes);
|
||||
pDataCol->bytes = pTCol->bytes;
|
||||
} else if (pDataCol->bytes < pTCol->bytes) {
|
||||
pDataCol->pData = realloc(pDataCol->pData, pTCol->bytes);
|
||||
pDataCol->bytes = pTCol->bytes;
|
||||
}
|
||||
|
||||
memcpy(pDataCol->pData, value, pDataCol->bytes);
|
||||
// the actual value size
|
||||
uint16_t bytes = IS_VAR_DATA_TYPE(pTCol->type) ? varDataTLen(value) : pTCol->bytes;
|
||||
// the actual data size CANNOT larger than column size
|
||||
assert(pTCol->bytes >= bytes);
|
||||
memcpy(pDataCol->pData, value, bytes);
|
||||
//tsdbInfo("updateTableLatestColumn vgId:%d cache column %d for %d,%s", REPO_ID(pRepo), j, pDataCol->bytes, (char*)pDataCol->pData);
|
||||
pDataCol->ts = memRowKey(row);
|
||||
}
|
||||
|
@ -1052,13 +1022,14 @@ static int tsdbUpdateTableLatestInfo(STsdbRepo *pRepo, STable *pTable, SMemRow r
|
|||
|
||||
// if cacheLastRow config has been reset, free the lastRow
|
||||
if (!pCfg->cacheLastRow && pTable->lastRow != NULL) {
|
||||
taosTZfree(pTable->lastRow);
|
||||
SMemRow cachedLastRow = pTable->lastRow;
|
||||
TSDB_WLOCK_TABLE(pTable);
|
||||
pTable->lastRow = NULL;
|
||||
TSDB_WUNLOCK_TABLE(pTable);
|
||||
taosTZfree(cachedLastRow);
|
||||
}
|
||||
|
||||
if (tsdbGetTableLastKeyImpl(pTable) < memRowKey(row)) {
|
||||
if (tsdbGetTableLastKeyImpl(pTable) <= memRowKey(row)) {
|
||||
if (CACHE_LAST_ROW(pCfg) || pTable->lastRow != NULL) {
|
||||
SMemRow nrow = pTable->lastRow;
|
||||
if (taosTSizeof(nrow) < memRowTLen(row)) {
|
||||
|
|
|
@ -14,11 +14,14 @@
|
|||
*/
|
||||
|
||||
#include "os.h"
|
||||
#include "tdataformat.h"
|
||||
#include "tskiplist.h"
|
||||
#include "tulog.h"
|
||||
#include "talgo.h"
|
||||
#include "tcompare.h"
|
||||
#include "exception.h"
|
||||
|
||||
#include "taosdef.h"
|
||||
#include "tlosertree.h"
|
||||
#include "tsdbint.h"
|
||||
#include "texpr.h"
|
||||
|
@ -68,6 +71,12 @@ typedef struct SLoadCompBlockInfo {
|
|||
int32_t fileId;
|
||||
} SLoadCompBlockInfo;
|
||||
|
||||
enum {
|
||||
CHECKINFO_CHOSEN_MEM = 0,
|
||||
CHECKINFO_CHOSEN_IMEM = 1,
|
||||
CHECKINFO_CHOSEN_BOTH = 2 //for update=2(merge case)
|
||||
};
|
||||
|
||||
|
||||
typedef struct STableCheckInfo {
|
||||
STableId tableId;
|
||||
|
@ -76,7 +85,7 @@ typedef struct STableCheckInfo {
|
|||
SBlockInfo* pCompInfo;
|
||||
int32_t compSize;
|
||||
int32_t numOfBlocks:29; // number of qualified data blocks not the original blocks
|
||||
int8_t chosen:2; // indicate which iterator should move forward
|
||||
uint8_t chosen:2; // indicate which iterator should move forward
|
||||
bool initBuf; // whether to initialize the in-memory skip list iterator or not
|
||||
SSkipListIterator* iter; // mem buffer skip list iterator
|
||||
SSkipListIterator* iiter; // imem buffer skip list iterator
|
||||
|
@ -640,7 +649,7 @@ static STableGroupInfo* trimTableGroup(STimeWindow* window, STableGroupInfo* pGr
|
|||
size_t numOfGroup = taosArrayGetSize(pGroupList->pGroupList);
|
||||
|
||||
STableGroupInfo* pNew = calloc(1, sizeof(STableGroupInfo));
|
||||
pNew->pGroupList = taosArrayInit(numOfGroup, sizeof(SArray));
|
||||
pNew->pGroupList = taosArrayInit(numOfGroup, POINTER_BYTES);
|
||||
|
||||
for(int32_t i = 0; i < numOfGroup; ++i) {
|
||||
SArray* oneGroup = taosArrayGetP(pGroupList->pGroupList, i);
|
||||
|
@ -781,7 +790,62 @@ static void destroyTableMemIterator(STableCheckInfo* pCheckInfo) {
|
|||
tSkipListDestroyIter(pCheckInfo->iiter);
|
||||
}
|
||||
|
||||
static SMemRow getSDataRowInTableMem(STableCheckInfo* pCheckInfo, int32_t order, int32_t update) {
|
||||
static TSKEY extractFirstTraverseKey(STableCheckInfo* pCheckInfo, int32_t order, int32_t update) {
|
||||
SMemRow rmem = NULL, rimem = NULL;
|
||||
if (pCheckInfo->iter) {
|
||||
SSkipListNode* node = tSkipListIterGet(pCheckInfo->iter);
|
||||
if (node != NULL) {
|
||||
rmem = (SMemRow)SL_GET_NODE_DATA(node);
|
||||
}
|
||||
}
|
||||
|
||||
if (pCheckInfo->iiter) {
|
||||
SSkipListNode* node = tSkipListIterGet(pCheckInfo->iiter);
|
||||
if (node != NULL) {
|
||||
rimem = (SMemRow)SL_GET_NODE_DATA(node);
|
||||
}
|
||||
}
|
||||
|
||||
if (rmem == NULL && rimem == NULL) {
|
||||
return TSKEY_INITIAL_VAL;
|
||||
}
|
||||
|
||||
if (rmem != NULL && rimem == NULL) {
|
||||
pCheckInfo->chosen = CHECKINFO_CHOSEN_MEM;
|
||||
return memRowKey(rmem);
|
||||
}
|
||||
|
||||
if (rmem == NULL && rimem != NULL) {
|
||||
pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
|
||||
return memRowKey(rimem);
|
||||
}
|
||||
|
||||
TSKEY r1 = memRowKey(rmem);
|
||||
TSKEY r2 = memRowKey(rimem);
|
||||
|
||||
if (r1 == r2) {
|
||||
if(update == TD_ROW_DISCARD_UPDATE){
|
||||
pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
|
||||
tSkipListIterNext(pCheckInfo->iter);
|
||||
}
|
||||
else if(update == TD_ROW_OVERWRITE_UPDATE) {
|
||||
pCheckInfo->chosen = CHECKINFO_CHOSEN_MEM;
|
||||
tSkipListIterNext(pCheckInfo->iiter);
|
||||
} else {
|
||||
pCheckInfo->chosen = CHECKINFO_CHOSEN_BOTH;
|
||||
}
|
||||
return r1;
|
||||
} else if (r1 < r2 && ASCENDING_TRAVERSE(order)) {
|
||||
pCheckInfo->chosen = CHECKINFO_CHOSEN_MEM;
|
||||
return r1;
|
||||
}
|
||||
else {
|
||||
pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
|
||||
return r2;
|
||||
}
|
||||
}
|
||||
|
||||
static SMemRow getSMemRowInTableMem(STableCheckInfo* pCheckInfo, int32_t order, int32_t update, SMemRow* extraRow) {
|
||||
SMemRow rmem = NULL, rimem = NULL;
|
||||
if (pCheckInfo->iter) {
|
||||
SSkipListNode* node = tSkipListIterGet(pCheckInfo->iter);
|
||||
|
@ -814,31 +878,35 @@ static SMemRow getSDataRowInTableMem(STableCheckInfo* pCheckInfo, int32_t order,
|
|||
TSKEY r1 = memRowKey(rmem);
|
||||
TSKEY r2 = memRowKey(rimem);
|
||||
|
||||
if (r1 == r2) { // data ts are duplicated, ignore the data in mem
|
||||
if (!update) {
|
||||
if (r1 == r2) {
|
||||
if (update == TD_ROW_DISCARD_UPDATE) {
|
||||
tSkipListIterNext(pCheckInfo->iter);
|
||||
pCheckInfo->chosen = 1;
|
||||
pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
|
||||
return rimem;
|
||||
} else {
|
||||
} else if(update == TD_ROW_OVERWRITE_UPDATE){
|
||||
tSkipListIterNext(pCheckInfo->iiter);
|
||||
pCheckInfo->chosen = 0;
|
||||
pCheckInfo->chosen = CHECKINFO_CHOSEN_MEM;
|
||||
return rmem;
|
||||
} else {
|
||||
pCheckInfo->chosen = CHECKINFO_CHOSEN_BOTH;
|
||||
extraRow = rimem;
|
||||
return rmem;
|
||||
}
|
||||
} else {
|
||||
if (ASCENDING_TRAVERSE(order)) {
|
||||
if (r1 < r2) {
|
||||
pCheckInfo->chosen = 0;
|
||||
pCheckInfo->chosen = CHECKINFO_CHOSEN_MEM;
|
||||
return rmem;
|
||||
} else {
|
||||
pCheckInfo->chosen = 1;
|
||||
pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
|
||||
return rimem;
|
||||
}
|
||||
} else {
|
||||
if (r1 < r2) {
|
||||
pCheckInfo->chosen = 1;
|
||||
pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
|
||||
return rimem;
|
||||
} else {
|
||||
pCheckInfo->chosen = 0;
|
||||
pCheckInfo->chosen = CHECKINFO_CHOSEN_IMEM;
|
||||
return rmem;
|
||||
}
|
||||
}
|
||||
|
@ -847,7 +915,7 @@ static SMemRow getSDataRowInTableMem(STableCheckInfo* pCheckInfo, int32_t order,
|
|||
|
||||
static bool moveToNextRowInMem(STableCheckInfo* pCheckInfo) {
|
||||
bool hasNext = false;
|
||||
if (pCheckInfo->chosen == 0) {
|
||||
if (pCheckInfo->chosen == CHECKINFO_CHOSEN_MEM) {
|
||||
if (pCheckInfo->iter != NULL) {
|
||||
hasNext = tSkipListIterNext(pCheckInfo->iter);
|
||||
}
|
||||
|
@ -859,7 +927,7 @@ static bool moveToNextRowInMem(STableCheckInfo* pCheckInfo) {
|
|||
if (pCheckInfo->iiter != NULL) {
|
||||
return tSkipListIterGet(pCheckInfo->iiter) != NULL;
|
||||
}
|
||||
} else { //pCheckInfo->chosen == 1
|
||||
} else if (pCheckInfo->chosen == CHECKINFO_CHOSEN_IMEM){
|
||||
if (pCheckInfo->iiter != NULL) {
|
||||
hasNext = tSkipListIterNext(pCheckInfo->iiter);
|
||||
}
|
||||
|
@ -871,6 +939,13 @@ static bool moveToNextRowInMem(STableCheckInfo* pCheckInfo) {
|
|||
if (pCheckInfo->iter != NULL) {
|
||||
return tSkipListIterGet(pCheckInfo->iter) != NULL;
|
||||
}
|
||||
} else {
|
||||
if (pCheckInfo->iter != NULL) {
|
||||
hasNext = tSkipListIterNext(pCheckInfo->iter);
|
||||
}
|
||||
if (pCheckInfo->iiter != NULL) {
|
||||
hasNext = tSkipListIterNext(pCheckInfo->iiter) || hasNext;
|
||||
}
|
||||
}
|
||||
|
||||
return hasNext;
|
||||
|
@ -891,7 +966,7 @@ static bool hasMoreDataInCache(STsdbQueryHandle* pHandle) {
|
|||
initTableMemIterator(pHandle, pCheckInfo);
|
||||
}
|
||||
|
||||
SMemRow row = getSDataRowInTableMem(pCheckInfo, pHandle->order, pCfg->update);
|
||||
SMemRow row = getSMemRowInTableMem(pCheckInfo, pHandle->order, pCfg->update, NULL);
|
||||
if (row == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1147,25 +1222,28 @@ static int32_t doCopyRowsFromFileBlock(STsdbQueryHandle* pQueryHandle, int32_t c
|
|||
static void moveDataToFront(STsdbQueryHandle* pQueryHandle, int32_t numOfRows, int32_t numOfCols);
|
||||
static void doCheckGeneratedBlockRange(STsdbQueryHandle* pQueryHandle);
|
||||
static void copyAllRemainRowsFromFileBlock(STsdbQueryHandle* pQueryHandle, STableCheckInfo* pCheckInfo, SDataBlockInfo* pBlockInfo, int32_t endPos);
|
||||
static TSKEY extractFirstTraverseKey(STableCheckInfo* pCheckInfo, int32_t order, int32_t update);
|
||||
|
||||
static int32_t handleDataMergeIfNeeded(STsdbQueryHandle* pQueryHandle, SBlock* pBlock, STableCheckInfo* pCheckInfo){
|
||||
SQueryFilePos* cur = &pQueryHandle->cur;
|
||||
STsdbCfg* pCfg = &pQueryHandle->pTsdb->config;
|
||||
SDataBlockInfo binfo = GET_FILE_DATA_BLOCK_INFO(pCheckInfo, pBlock);
|
||||
TSKEY key;
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
|
||||
/*bool hasData = */ initTableMemIterator(pQueryHandle, pCheckInfo);
|
||||
SMemRow row = getSDataRowInTableMem(pCheckInfo, pQueryHandle->order, pCfg->update);
|
||||
|
||||
assert(cur->pos >= 0 && cur->pos <= binfo.rows);
|
||||
|
||||
TSKEY key = (row != NULL) ? memRowKey(row) : TSKEY_INITIAL_VAL;
|
||||
key = extractFirstTraverseKey(pCheckInfo, pQueryHandle->order, pCfg->update);
|
||||
|
||||
if (key != TSKEY_INITIAL_VAL) {
|
||||
tsdbDebug("%p key in mem:%"PRId64", 0x%"PRIx64, pQueryHandle, key, pQueryHandle->qId);
|
||||
} else {
|
||||
tsdbDebug("%p no data in mem, 0x%"PRIx64, pQueryHandle, pQueryHandle->qId);
|
||||
}
|
||||
|
||||
|
||||
if ((ASCENDING_TRAVERSE(pQueryHandle->order) && (key != TSKEY_INITIAL_VAL && key <= binfo.window.ekey)) ||
|
||||
(!ASCENDING_TRAVERSE(pQueryHandle->order) && (key != TSKEY_INITIAL_VAL && key >= binfo.window.skey))) {
|
||||
|
||||
|
@ -1190,6 +1268,7 @@ static int32_t handleDataMergeIfNeeded(STsdbQueryHandle* pQueryHandle, SBlock* p
|
|||
return code;
|
||||
}
|
||||
|
||||
|
||||
// return error, add test cases
|
||||
if ((code = doLoadFileDataBlock(pQueryHandle, pBlock, pCheckInfo, cur->slot)) != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
|
@ -1452,186 +1531,204 @@ int32_t doCopyRowsFromFileBlock(STsdbQueryHandle* pQueryHandle, int32_t capacity
|
|||
return numOfRows + num;
|
||||
}
|
||||
|
||||
static void copyOneRowFromMem(STsdbQueryHandle* pQueryHandle, int32_t capacity, int32_t numOfRows, SMemRow row,
|
||||
int32_t numOfCols, STable* pTable, STSchema* pSchema) {
|
||||
// Note: row1 always has high priority
|
||||
static void mergeTwoRowFromMem(STsdbQueryHandle* pQueryHandle, int32_t capacity, int32_t numOfRows,
|
||||
SMemRow row1, SMemRow row2, int32_t numOfCols, STable* pTable,
|
||||
STSchema* pSchema1, STSchema* pSchema2, bool forceSetNull) {
|
||||
char* pData = NULL;
|
||||
STSchema* pSchema;
|
||||
SMemRow row;
|
||||
int16_t colId;
|
||||
int16_t offset;
|
||||
|
||||
// the schema version info is embedded in SDataRow, and use latest schema version for SKVRow
|
||||
int32_t numOfRowCols = 0;
|
||||
if (pSchema == NULL) {
|
||||
pSchema = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row));
|
||||
numOfRowCols = schemaNCols(pSchema);
|
||||
bool isRow1DataRow = isDataRow(row1);
|
||||
bool isRow2DataRow;
|
||||
bool isChosenRowDataRow;
|
||||
int32_t chosen_itr;
|
||||
void *value;
|
||||
|
||||
// the schema version info is embeded in SDataRow
|
||||
int32_t numOfColsOfRow1 = 0;
|
||||
|
||||
if (pSchema1 == NULL) {
|
||||
pSchema1 = tsdbGetTableSchemaByVersion(pTable, dataRowVersion(row1));
|
||||
}
|
||||
if(isRow1DataRow) {
|
||||
numOfColsOfRow1 = schemaNCols(pSchema1);
|
||||
} else {
|
||||
numOfRowCols = schemaNCols(pSchema);
|
||||
numOfColsOfRow1 = kvRowNCols(memRowKvBody(row1));
|
||||
}
|
||||
|
||||
int32_t i = 0;
|
||||
|
||||
if (isDataRow(row)) {
|
||||
SDataRow dataRow = memRowDataBody(row);
|
||||
int32_t j = 0;
|
||||
while (i < numOfCols && j < numOfRowCols) {
|
||||
SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, i);
|
||||
if (pSchema->columns[j].colId < pColInfo->info.colId) {
|
||||
j++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ASCENDING_TRAVERSE(pQueryHandle->order)) {
|
||||
pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes;
|
||||
} else {
|
||||
pData = (char*)pColInfo->pData + (capacity - numOfRows - 1) * pColInfo->info.bytes;
|
||||
}
|
||||
|
||||
if (pSchema->columns[j].colId == pColInfo->info.colId) {
|
||||
void* value =
|
||||
tdGetRowDataOfCol(dataRow, (int8_t)pColInfo->info.type, TD_DATA_ROW_HEAD_SIZE + pSchema->columns[j].offset);
|
||||
switch (pColInfo->info.type) {
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
memcpy(pData, value, varDataTLen(value));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_NULL:
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
case TSDB_DATA_TYPE_UTINYINT:
|
||||
*(uint8_t*)pData = *(uint8_t*)value;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
case TSDB_DATA_TYPE_USMALLINT:
|
||||
*(uint16_t*)pData = *(uint16_t*)value;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
case TSDB_DATA_TYPE_UINT:
|
||||
*(uint32_t*)pData = *(uint32_t*)value;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
*(uint64_t*)pData = *(uint64_t*)value;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
SET_FLOAT_PTR(pData, value);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
SET_DOUBLE_PTR(pData, value);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
if (pColInfo->info.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
|
||||
*(TSKEY*)pData = tdGetKey(*(TKEY*)value);
|
||||
} else {
|
||||
*(TSKEY*)pData = *(TSKEY*)value;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
memcpy(pData, value, pColInfo->info.bytes);
|
||||
}
|
||||
|
||||
j++;
|
||||
i++;
|
||||
} else { // pColInfo->info.colId < pSchema->columns[j].colId, it is a NULL data
|
||||
if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) {
|
||||
setVardataNull(pData, pColInfo->info.type);
|
||||
} else {
|
||||
setNull(pData, pColInfo->info.type, pColInfo->info.bytes);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
int32_t numOfColsOfRow2 = 0;
|
||||
if(row2) {
|
||||
isRow2DataRow = isDataRow(row2);
|
||||
if (pSchema2 == NULL) {
|
||||
pSchema2 = tsdbGetTableSchemaByVersion(pTable, dataRowVersion(row2));
|
||||
}
|
||||
} else if (isKvRow(row)) {
|
||||
SKVRow kvRow = memRowKvBody(row);
|
||||
int32_t k = 0;
|
||||
int32_t nKvRowCols = kvRowNCols(kvRow);
|
||||
|
||||
while (i < numOfCols && k < nKvRowCols) {
|
||||
SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, i);
|
||||
SColIdx* pColIdx = kvRowColIdxAt(kvRow, k);
|
||||
|
||||
if (pColIdx->colId < pColInfo->info.colId) {
|
||||
++k;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ASCENDING_TRAVERSE(pQueryHandle->order)) {
|
||||
pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes;
|
||||
} else {
|
||||
pData = (char*)pColInfo->pData + (capacity - numOfRows - 1) * pColInfo->info.bytes;
|
||||
}
|
||||
|
||||
if (pColIdx->colId == pColInfo->info.colId) {
|
||||
// offset of pColIdx for SKVRow including the TD_KV_ROW_HEAD_SIZE
|
||||
void* value = tdGetKvRowDataOfCol(kvRow, pColIdx->offset);
|
||||
switch (pColInfo->info.type) {
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
memcpy(pData, value, varDataTLen(value));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_NULL:
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
case TSDB_DATA_TYPE_UTINYINT:
|
||||
*(uint8_t*)pData = *(uint8_t*)value;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
case TSDB_DATA_TYPE_USMALLINT:
|
||||
*(uint16_t*)pData = *(uint16_t*)value;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
case TSDB_DATA_TYPE_UINT:
|
||||
*(uint32_t*)pData = *(uint32_t*)value;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
*(uint64_t*)pData = *(uint64_t*)value;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
SET_FLOAT_PTR(pData, value);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
SET_DOUBLE_PTR(pData, value);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
if (pColInfo->info.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
|
||||
*(TSKEY*)pData = tdGetKey(*(TKEY*)value);
|
||||
} else {
|
||||
*(TSKEY*)pData = *(TSKEY*)value;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
memcpy(pData, value, pColInfo->info.bytes);
|
||||
}
|
||||
++k;
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
// If (pColInfo->info.colId < pColIdx->colId), it is NULL data
|
||||
if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) {
|
||||
setVardataNull(pData, pColInfo->info.type);
|
||||
} else {
|
||||
setNull(pData, pColInfo->info.type, pColInfo->info.bytes);
|
||||
}
|
||||
++i;
|
||||
if(isRow2DataRow) {
|
||||
numOfColsOfRow2 = schemaNCols(pSchema2);
|
||||
} else {
|
||||
numOfColsOfRow2 = kvRowNCols(memRowKvBody(row2));
|
||||
}
|
||||
} else {
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
while (i < numOfCols) { // the remain columns are all null data
|
||||
|
||||
int32_t i = 0, j = 0, k = 0;
|
||||
while(i < numOfCols && (j < numOfColsOfRow1 || k < numOfColsOfRow2)) {
|
||||
SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, i);
|
||||
|
||||
if (ASCENDING_TRAVERSE(pQueryHandle->order)) {
|
||||
pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes;
|
||||
} else {
|
||||
pData = (char*)pColInfo->pData + (capacity - numOfRows - 1) * pColInfo->info.bytes;
|
||||
}
|
||||
|
||||
if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) {
|
||||
setVardataNull(pData, pColInfo->info.type);
|
||||
int32_t colIdOfRow1;
|
||||
if(j >= numOfColsOfRow1) {
|
||||
colIdOfRow1 = INT32_MAX;
|
||||
} else if(isRow1DataRow) {
|
||||
colIdOfRow1 = pSchema1->columns[j].colId;
|
||||
} else {
|
||||
setNull(pData, pColInfo->info.type, pColInfo->info.bytes);
|
||||
void *rowBody = memRowKvBody(row1);
|
||||
SColIdx *pColIdx = kvRowColIdxAt(rowBody, j);
|
||||
colIdOfRow1 = pColIdx->colId;
|
||||
}
|
||||
|
||||
i++;
|
||||
int32_t colIdOfRow2;
|
||||
if(k >= numOfColsOfRow2) {
|
||||
colIdOfRow2 = INT32_MAX;
|
||||
} else if(isRow2DataRow) {
|
||||
colIdOfRow2 = pSchema2->columns[k].colId;
|
||||
} else {
|
||||
void *rowBody = memRowKvBody(row2);
|
||||
SColIdx *pColIdx = kvRowColIdxAt(rowBody, k);
|
||||
colIdOfRow2 = pColIdx->colId;
|
||||
}
|
||||
|
||||
if(colIdOfRow1 == colIdOfRow2) {
|
||||
if(colIdOfRow1 < pColInfo->info.colId) {
|
||||
j++;
|
||||
k++;
|
||||
continue;
|
||||
}
|
||||
row = row1;
|
||||
pSchema = pSchema1;
|
||||
isChosenRowDataRow = isRow1DataRow;
|
||||
chosen_itr = j;
|
||||
} else if(colIdOfRow1 < colIdOfRow2) {
|
||||
if(colIdOfRow1 < pColInfo->info.colId) {
|
||||
j++;
|
||||
continue;
|
||||
}
|
||||
row = row1;
|
||||
pSchema = pSchema1;
|
||||
isChosenRowDataRow = isRow1DataRow;
|
||||
chosen_itr = j;
|
||||
} else {
|
||||
if(colIdOfRow2 < pColInfo->info.colId) {
|
||||
k++;
|
||||
continue;
|
||||
}
|
||||
row = row2;
|
||||
pSchema = pSchema2;
|
||||
chosen_itr = k;
|
||||
isChosenRowDataRow = isRow2DataRow;
|
||||
}
|
||||
if(isChosenRowDataRow) {
|
||||
colId = pSchema->columns[chosen_itr].colId;
|
||||
offset = pSchema->columns[chosen_itr].offset;
|
||||
void *rowBody = memRowDataBody(row);
|
||||
value = tdGetRowDataOfCol(rowBody, (int8_t)pColInfo->info.type, TD_DATA_ROW_HEAD_SIZE + offset);
|
||||
} else {
|
||||
void *rowBody = memRowKvBody(row);
|
||||
SColIdx *pColIdx = kvRowColIdxAt(rowBody, chosen_itr);
|
||||
colId = pColIdx->colId;
|
||||
offset = pColIdx->offset;
|
||||
value = tdGetKvRowDataOfCol(rowBody, pColIdx->offset);
|
||||
}
|
||||
|
||||
|
||||
if (colId == pColInfo->info.colId) {
|
||||
if(forceSetNull || (!isNull(value, (int8_t)pColInfo->info.type))) {
|
||||
switch (pColInfo->info.type) {
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
memcpy(pData, value, varDataTLen(value));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_NULL:
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
case TSDB_DATA_TYPE_UTINYINT:
|
||||
*(uint8_t *)pData = *(uint8_t *)value;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
case TSDB_DATA_TYPE_USMALLINT:
|
||||
*(uint16_t *)pData = *(uint16_t *)value;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
case TSDB_DATA_TYPE_UINT:
|
||||
*(uint32_t *)pData = *(uint32_t *)value;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
*(uint64_t *)pData = *(uint64_t *)value;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
SET_FLOAT_PTR(pData, value);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
SET_DOUBLE_PTR(pData, value);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
if (pColInfo->info.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
|
||||
*(TSKEY *)pData = tdGetKey(*(TKEY *)value);
|
||||
} else {
|
||||
*(TSKEY *)pData = *(TSKEY *)value;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
memcpy(pData, value, pColInfo->info.bytes);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
|
||||
if(row == row1) {
|
||||
j++;
|
||||
} else {
|
||||
k++;
|
||||
}
|
||||
} else {
|
||||
if(forceSetNull) {
|
||||
if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) {
|
||||
setVardataNull(pData, pColInfo->info.type);
|
||||
} else {
|
||||
setNull(pData, pColInfo->info.type, pColInfo->info.bytes);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if(forceSetNull) {
|
||||
while (i < numOfCols) { // the remain columns are all null data
|
||||
SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, i);
|
||||
if (ASCENDING_TRAVERSE(pQueryHandle->order)) {
|
||||
pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes;
|
||||
} else {
|
||||
pData = (char*)pColInfo->pData + (capacity - numOfRows - 1) * pColInfo->info.bytes;
|
||||
}
|
||||
|
||||
if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) {
|
||||
setVardataNull(pData, pColInfo->info.type);
|
||||
} else {
|
||||
setNull(pData, pColInfo->info.type, pColInfo->info.bytes);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void moveDataToFront(STsdbQueryHandle* pQueryHandle, int32_t numOfRows, int32_t numOfCols) {
|
||||
if (numOfRows == 0 || ASCENDING_TRAVERSE(pQueryHandle->order)) {
|
||||
return;
|
||||
|
@ -1798,8 +1895,10 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo*
|
|||
// compared with the data from in-memory buffer, to generate the correct timestamp array list
|
||||
int32_t numOfRows = 0;
|
||||
|
||||
int16_t rv = -1;
|
||||
STSchema* pSchema = NULL;
|
||||
int16_t rv1 = -1;
|
||||
int16_t rv2 = -1;
|
||||
STSchema* pSchema1 = NULL;
|
||||
STSchema* pSchema2 = NULL;
|
||||
|
||||
int32_t pos = cur->pos;
|
||||
cur->win = TSWINDOW_INITIALIZER;
|
||||
|
@ -1811,12 +1910,13 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo*
|
|||
} else if (pCheckInfo->iter != NULL || pCheckInfo->iiter != NULL) {
|
||||
SSkipListNode* node = NULL;
|
||||
do {
|
||||
SMemRow row = getSDataRowInTableMem(pCheckInfo, pQueryHandle->order, pCfg->update);
|
||||
if (row == NULL) {
|
||||
SMemRow row2 = NULL;
|
||||
SMemRow row1 = getSMemRowInTableMem(pCheckInfo, pQueryHandle->order, pCfg->update, &row2);
|
||||
if (row1 == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
TSKEY key = memRowKey(row);
|
||||
TSKEY key = memRowKey(row1);
|
||||
if ((key > pQueryHandle->window.ekey && ASCENDING_TRAVERSE(pQueryHandle->order)) ||
|
||||
(key < pQueryHandle->window.ekey && !ASCENDING_TRAVERSE(pQueryHandle->order))) {
|
||||
break;
|
||||
|
@ -1829,12 +1929,16 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo*
|
|||
|
||||
if ((key < tsArray[pos] && ASCENDING_TRAVERSE(pQueryHandle->order)) ||
|
||||
(key > tsArray[pos] && !ASCENDING_TRAVERSE(pQueryHandle->order))) {
|
||||
if (rv != memRowVersion(row)) {
|
||||
pSchema = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row));
|
||||
rv = memRowVersion(row);
|
||||
if (rv1 != memRowVersion(row1)) {
|
||||
pSchema1 = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row1));
|
||||
rv1 = memRowVersion(row1);
|
||||
}
|
||||
|
||||
copyOneRowFromMem(pQueryHandle, pQueryHandle->outputCapacity, numOfRows, row, numOfCols, pTable, pSchema);
|
||||
if(row2 && rv2 != memRowVersion(row2)) {
|
||||
pSchema2 = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row2));
|
||||
rv2 = memRowVersion(row2);
|
||||
}
|
||||
|
||||
mergeTwoRowFromMem(pQueryHandle, pQueryHandle->outputCapacity, numOfRows, row1, row2, numOfCols, pTable, pSchema1, pSchema2, true);
|
||||
numOfRows += 1;
|
||||
if (cur->win.skey == TSKEY_INITIAL_VAL) {
|
||||
cur->win.skey = key;
|
||||
|
@ -1847,12 +1951,20 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo*
|
|||
moveToNextRowInMem(pCheckInfo);
|
||||
} else if (key == tsArray[pos]) { // data in buffer has the same timestamp of data in file block, ignore it
|
||||
if (pCfg->update) {
|
||||
if (rv != memRowVersion(row)) {
|
||||
pSchema = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row));
|
||||
rv = memRowVersion(row);
|
||||
if(pCfg->update == TD_ROW_PARTIAL_UPDATE) {
|
||||
doCopyRowsFromFileBlock(pQueryHandle, pQueryHandle->outputCapacity, numOfRows, pos, pos);
|
||||
}
|
||||
|
||||
copyOneRowFromMem(pQueryHandle, pQueryHandle->outputCapacity, numOfRows, row, numOfCols, pTable, pSchema);
|
||||
if (rv1 != memRowVersion(row1)) {
|
||||
pSchema1 = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row1));
|
||||
rv1 = memRowVersion(row1);
|
||||
}
|
||||
if(row2 && rv2 != memRowVersion(row2)) {
|
||||
pSchema2 = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row2));
|
||||
rv2 = memRowVersion(row2);
|
||||
}
|
||||
|
||||
bool forceSetNull = pCfg->update != TD_ROW_PARTIAL_UPDATE;
|
||||
mergeTwoRowFromMem(pQueryHandle, pQueryHandle->outputCapacity, numOfRows, row1, row2, numOfCols, pTable, pSchema1, pSchema2, forceSetNull);
|
||||
numOfRows += 1;
|
||||
if (cur->win.skey == TSKEY_INITIAL_VAL) {
|
||||
cur->win.skey = key;
|
||||
|
@ -1877,7 +1989,7 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo*
|
|||
assert(end != -1);
|
||||
|
||||
if (tsArray[end] == key) { // the value of key in cache equals to the end timestamp value, ignore it
|
||||
if (!pCfg->update) {
|
||||
if (pCfg->update == TD_ROW_DISCARD_UPDATE) {
|
||||
moveToNextRowInMem(pCheckInfo);
|
||||
} else {
|
||||
end -= step;
|
||||
|
@ -2490,7 +2602,7 @@ static int tsdbReadRowsFromCache(STableCheckInfo* pCheckInfo, TSKEY maxKey, int
|
|||
STSchema* pSchema = NULL;
|
||||
|
||||
do {
|
||||
SMemRow row = getSDataRowInTableMem(pCheckInfo, pQueryHandle->order, pCfg->update);
|
||||
SMemRow row = getSMemRowInTableMem(pCheckInfo, pQueryHandle->order, pCfg->update, NULL);
|
||||
if (row == NULL) {
|
||||
break;
|
||||
}
|
||||
|
@ -2512,7 +2624,7 @@ static int tsdbReadRowsFromCache(STableCheckInfo* pCheckInfo, TSKEY maxKey, int
|
|||
pSchema = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row));
|
||||
rv = memRowVersion(row);
|
||||
}
|
||||
copyOneRowFromMem(pQueryHandle, maxRowsToRead, numOfRows, row, numOfCols, pTable, pSchema);
|
||||
mergeTwoRowFromMem(pQueryHandle, maxRowsToRead, numOfRows, row, NULL, numOfCols, pTable, pSchema, NULL, true);
|
||||
|
||||
if (++numOfRows >= maxRowsToRead) {
|
||||
moveToNextRowInMem(pCheckInfo);
|
||||
|
@ -2637,7 +2749,7 @@ static bool loadCachedLastRow(STsdbQueryHandle* pQueryHandle) {
|
|||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
copyOneRowFromMem(pQueryHandle, pQueryHandle->outputCapacity, 0, pRow, numOfCols, pCheckInfo->pTableObj, NULL);
|
||||
mergeTwoRowFromMem(pQueryHandle, pQueryHandle->outputCapacity, 0, pRow, NULL, numOfCols, pCheckInfo->pTableObj, NULL, NULL, true);
|
||||
tfree(pRow);
|
||||
|
||||
// update the last key value
|
||||
|
@ -2920,7 +3032,7 @@ static int32_t doGetExternalRow(STsdbQueryHandle* pQueryHandle, int16_t type, SM
|
|||
}
|
||||
}
|
||||
|
||||
SArray* row = (type == TSDB_PREV_ROW)? pQueryHandle->prev:pQueryHandle->next;
|
||||
SArray* row = (type == TSDB_PREV_ROW)? pQueryHandle->prev : pQueryHandle->next;
|
||||
|
||||
for (int32_t i = 0; i < numOfCols; ++i) {
|
||||
SColumnInfoData* pCol = taosArrayGet(pQueryHandle->pColumns, i);
|
||||
|
@ -3383,11 +3495,13 @@ static int32_t tableGroupComparFn(const void *p1, const void *p2, const void *pa
|
|||
type = TSDB_DATA_TYPE_BINARY;
|
||||
bytes = tGetTbnameColumnSchema()->bytes;
|
||||
} else {
|
||||
STColumn* pCol = schemaColAt(pTableGroupSupp->pTagSchema, colIndex);
|
||||
bytes = pCol->bytes;
|
||||
type = pCol->type;
|
||||
f1 = tdGetKVRowValOfCol(pTable1->tagVal, pCol->colId);
|
||||
f2 = tdGetKVRowValOfCol(pTable2->tagVal, pCol->colId);
|
||||
if (pTableGroupSupp->pTagSchema && colIndex < pTableGroupSupp->pTagSchema->numOfCols) {
|
||||
STColumn* pCol = schemaColAt(pTableGroupSupp->pTagSchema, colIndex);
|
||||
bytes = pCol->bytes;
|
||||
type = pCol->type;
|
||||
f1 = tdGetKVRowValOfCol(pTable1->tagVal, pCol->colId);
|
||||
f2 = tdGetKVRowValOfCol(pTable2->tagVal, pCol->colId);
|
||||
}
|
||||
}
|
||||
|
||||
// this tags value may be NULL
|
||||
|
@ -3785,10 +3899,6 @@ static void* doFreeColumnInfoData(SArray* pColumnInfoData) {
|
|||
}
|
||||
|
||||
static void* destroyTableCheckInfo(SArray* pTableCheckInfo) {
|
||||
if (pTableCheckInfo == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t size = taosArrayGetSize(pTableCheckInfo);
|
||||
for (int32_t i = 0; i < size; ++i) {
|
||||
STableCheckInfo* p = taosArrayGet(pTableCheckInfo, i);
|
||||
|
@ -3832,6 +3942,7 @@ void tsdbCleanupQueryHandle(TsdbQueryHandleT queryHandle) {
|
|||
pQueryHandle->next = doFreeColumnInfoData(pQueryHandle->next);
|
||||
|
||||
SIOCostSummary* pCost = &pQueryHandle->cost;
|
||||
|
||||
tsdbDebug("%p :io-cost summary: head-file read cnt:%"PRIu64", head-file time:%"PRIu64" us, statis-info:%"PRId64" us, datablock:%" PRId64" us, check data:%"PRId64" us, 0x%"PRIx64,
|
||||
pQueryHandle, pCost->headFileLoad, pCost->headFileLoadTime, pCost->statisInfoLoadTime, pCost->blockLoadTime, pCost->checkForNextTime, pQueryHandle->qId);
|
||||
|
||||
|
|
|
@ -244,6 +244,7 @@ int tsdbLoadBlockInfo(SReadH *pReadh, void *pTarget) {
|
|||
|
||||
int tsdbLoadBlockData(SReadH *pReadh, SBlock *pBlock, SBlockInfo *pBlkInfo) {
|
||||
ASSERT(pBlock->numOfSubBlocks > 0);
|
||||
int8_t update = pReadh->pRepo->config.update;
|
||||
|
||||
SBlock *iBlock = pBlock;
|
||||
if (pBlock->numOfSubBlocks > 1) {
|
||||
|
@ -258,7 +259,7 @@ int tsdbLoadBlockData(SReadH *pReadh, SBlock *pBlock, SBlockInfo *pBlkInfo) {
|
|||
for (int i = 1; i < pBlock->numOfSubBlocks; i++) {
|
||||
iBlock++;
|
||||
if (tsdbLoadBlockDataImpl(pReadh, iBlock, pReadh->pDCols[1]) < 0) return -1;
|
||||
if (tdMergeDataCols(pReadh->pDCols[0], pReadh->pDCols[1], pReadh->pDCols[1]->numOfRows, NULL) < 0) return -1;
|
||||
if (tdMergeDataCols(pReadh->pDCols[0], pReadh->pDCols[1], pReadh->pDCols[1]->numOfRows, NULL, update != TD_ROW_PARTIAL_UPDATE) < 0) return -1;
|
||||
}
|
||||
|
||||
ASSERT(pReadh->pDCols[0]->numOfRows == pBlock->numOfRows);
|
||||
|
@ -270,6 +271,7 @@ int tsdbLoadBlockData(SReadH *pReadh, SBlock *pBlock, SBlockInfo *pBlkInfo) {
|
|||
|
||||
int tsdbLoadBlockDataCols(SReadH *pReadh, SBlock *pBlock, SBlockInfo *pBlkInfo, int16_t *colIds, int numOfColsIds) {
|
||||
ASSERT(pBlock->numOfSubBlocks > 0);
|
||||
int8_t update = pReadh->pRepo->config.update;
|
||||
|
||||
SBlock *iBlock = pBlock;
|
||||
if (pBlock->numOfSubBlocks > 1) {
|
||||
|
@ -284,7 +286,7 @@ int tsdbLoadBlockDataCols(SReadH *pReadh, SBlock *pBlock, SBlockInfo *pBlkInfo,
|
|||
for (int i = 1; i < pBlock->numOfSubBlocks; i++) {
|
||||
iBlock++;
|
||||
if (tsdbLoadBlockDataColsImpl(pReadh, iBlock, pReadh->pDCols[1], colIds, numOfColsIds) < 0) return -1;
|
||||
if (tdMergeDataCols(pReadh->pDCols[0], pReadh->pDCols[1], pReadh->pDCols[1]->numOfRows, NULL) < 0) return -1;
|
||||
if (tdMergeDataCols(pReadh->pDCols[0], pReadh->pDCols[1], pReadh->pDCols[1]->numOfRows, NULL, update != TD_ROW_PARTIAL_UPDATE) < 0) return -1;
|
||||
}
|
||||
|
||||
ASSERT(pReadh->pDCols[0]->numOfRows == pBlock->numOfRows);
|
||||
|
@ -657,4 +659,4 @@ static int tsdbLoadColData(SReadH *pReadh, SDFile *pDFile, SBlock *pBlock, SBloc
|
|||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "tsdbRowMergeBuf.h"
|
||||
#include "tdataformat.h"
|
||||
|
||||
// row1 has higher priority
|
||||
SMemRow tsdbMergeTwoRows(SMergeBuf *pBuf, SMemRow row1, SMemRow row2, STSchema *pSchema1, STSchema *pSchema2) {
|
||||
if(row2 == NULL) return row1;
|
||||
if(row1 == NULL) return row2;
|
||||
ASSERT(pSchema1->version == memRowVersion(row1));
|
||||
ASSERT(pSchema2->version == memRowVersion(row2));
|
||||
|
||||
if(tsdbMergeBufMakeSureRoom(pBuf, pSchema1, pSchema2) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
return mergeTwoMemRows(*pBuf, row1, row2, pSchema1, pSchema2);
|
||||
}
|
|
@ -123,10 +123,9 @@ void *taosHashGet(SHashObj *pHashObj, const void *key, size_t keyLen);
|
|||
* @param keyLen
|
||||
* @param fp
|
||||
* @param d
|
||||
* @param dsize
|
||||
* @return
|
||||
*/
|
||||
void* taosHashGetClone(SHashObj *pHashObj, const void *key, size_t keyLen, void (*fp)(void *), void* d, size_t dsize);
|
||||
void* taosHashGetClone(SHashObj *pHashObj, const void *key, size_t keyLen, void (*fp)(void *), void* d);
|
||||
|
||||
/**
|
||||
* remove item with the specified key
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef TD_TFUNCTIONAL_H
|
||||
#define TD_TFUNCTIONAL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "os.h"
|
||||
|
||||
//TODO: hard to use, trying to rewrite it using va_list
|
||||
|
||||
typedef void* (*GenericVaFunc)(void* args[]);
|
||||
typedef int32_t (*I32VaFunc) (void* args[]);
|
||||
typedef void (*VoidVaFunc) (void* args[]);
|
||||
|
||||
typedef struct GenericSavedFunc {
|
||||
GenericVaFunc func;
|
||||
void * args[];
|
||||
} tGenericSavedFunc;
|
||||
|
||||
typedef struct I32SavedFunc {
|
||||
I32VaFunc func;
|
||||
void * args[];
|
||||
} tI32SavedFunc;
|
||||
|
||||
typedef struct VoidSavedFunc {
|
||||
VoidVaFunc func;
|
||||
void * args[];
|
||||
} tVoidSavedFunc;
|
||||
|
||||
tGenericSavedFunc* genericSavedFuncInit(GenericVaFunc func, int numOfArgs);
|
||||
tI32SavedFunc* i32SavedFuncInit(I32VaFunc func, int numOfArgs);
|
||||
tVoidSavedFunc* voidSavedFuncInit(VoidVaFunc func, int numOfArgs);
|
||||
void* genericInvoke(tGenericSavedFunc* const pSavedFunc);
|
||||
int32_t i32Invoke(tI32SavedFunc* const pSavedFunc);
|
||||
void voidInvoke(tVoidSavedFunc* const pSavedFunc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -23,6 +23,7 @@ extern "C" {
|
|||
#include "os.h"
|
||||
#include "taosdef.h"
|
||||
#include "tarray.h"
|
||||
#include "tfunctional.h"
|
||||
|
||||
#define MAX_SKIP_LIST_LEVEL 15
|
||||
#define SKIP_LIST_RECORD_PERFORMANCE 0
|
||||
|
@ -30,13 +31,17 @@ extern "C" {
|
|||
// For key property setting
|
||||
#define SL_ALLOW_DUP_KEY (uint8_t)0x0 // Allow duplicate key exists (for tag index usage)
|
||||
#define SL_DISCARD_DUP_KEY (uint8_t)0x1 // Discard duplicate key (for data update=0 case)
|
||||
#define SL_UPDATE_DUP_KEY (uint8_t)0x2 // Update duplicate key by remove/insert (for data update=1 case)
|
||||
#define SL_UPDATE_DUP_KEY (uint8_t)0x2 // Update duplicate key by remove/insert (for data update!=0 case)
|
||||
|
||||
// For thread safety setting
|
||||
#define SL_THREAD_SAFE (uint8_t)0x4
|
||||
|
||||
typedef char *SSkipListKey;
|
||||
typedef char *(*__sl_key_fn_t)(const void *);
|
||||
|
||||
typedef void (*sl_patch_row_fn_t)(void * pDst, const void * pSrc);
|
||||
typedef void* (*iter_next_fn_t)(void *iter);
|
||||
|
||||
typedef struct SSkipListNode {
|
||||
uint8_t level;
|
||||
void * pData;
|
||||
|
@ -95,6 +100,12 @@ typedef struct tSkipListState {
|
|||
uint64_t nTotalElapsedTimeForInsert;
|
||||
} tSkipListState;
|
||||
|
||||
typedef enum {
|
||||
SSkipListPutSuccess = 0,
|
||||
SSkipListPutEarlyStop = 1,
|
||||
SSkipListPutSkipOne = 2
|
||||
} SSkipListPutStatus;
|
||||
|
||||
typedef struct SSkipList {
|
||||
unsigned int seed;
|
||||
__compar_fn_t comparFn;
|
||||
|
@ -111,6 +122,7 @@ typedef struct SSkipList {
|
|||
#if SKIP_LIST_RECORD_PERFORMANCE
|
||||
tSkipListState state; // skiplist state
|
||||
#endif
|
||||
tGenericSavedFunc* insertHandleFn;
|
||||
} SSkipList;
|
||||
|
||||
typedef struct SSkipListIterator {
|
||||
|
@ -118,7 +130,7 @@ typedef struct SSkipListIterator {
|
|||
SSkipListNode *cur;
|
||||
int32_t step; // the number of nodes that have been checked already
|
||||
int32_t order; // order of the iterator
|
||||
SSkipListNode *next; // next points to the true qualified node in skip list
|
||||
SSkipListNode *next; // next points to the true qualified node in skiplist
|
||||
} SSkipListIterator;
|
||||
|
||||
#define SL_IS_THREAD_SAFE(s) (((s)->flags) & SL_THREAD_SAFE)
|
||||
|
@ -132,7 +144,7 @@ SSkipList *tSkipListCreate(uint8_t maxLevel, uint8_t keyType, uint16_t keyLen, _
|
|||
__sl_key_fn_t fn);
|
||||
void tSkipListDestroy(SSkipList *pSkipList);
|
||||
SSkipListNode * tSkipListPut(SSkipList *pSkipList, void *pData);
|
||||
void tSkipListPutBatch(SSkipList *pSkipList, void **ppData, int ndata);
|
||||
void tSkipListPutBatchByIter(SSkipList *pSkipList, void *iter, iter_next_fn_t iterate);
|
||||
SArray * tSkipListGet(SSkipList *pSkipList, SSkipListKey pKey);
|
||||
void tSkipListPrint(SSkipList *pSkipList, int16_t nlevel);
|
||||
SSkipListIterator *tSkipListCreateIter(SSkipList *pSkipList);
|
||||
|
|
|
@ -294,10 +294,10 @@ int32_t taosHashPut(SHashObj *pHashObj, const void *key, size_t keyLen, void *da
|
|||
}
|
||||
|
||||
void *taosHashGet(SHashObj *pHashObj, const void *key, size_t keyLen) {
|
||||
return taosHashGetClone(pHashObj, key, keyLen, NULL, NULL, 0);
|
||||
return taosHashGetClone(pHashObj, key, keyLen, NULL, NULL);
|
||||
}
|
||||
|
||||
void* taosHashGetClone(SHashObj *pHashObj, const void *key, size_t keyLen, void (*fp)(void *), void* d, size_t dsize) {
|
||||
void* taosHashGetClone(SHashObj *pHashObj, const void *key, size_t keyLen, void (*fp)(void *), void* d) {
|
||||
if (taosHashTableEmpty(pHashObj) || keyLen == 0 || key == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -132,11 +132,11 @@ static FORCE_INLINE void taosCacheReleaseNode(SCacheObj *pCacheObj, SCacheDataNo
|
|||
return;
|
||||
}
|
||||
|
||||
pCacheObj->totalSize -= pNode->size;
|
||||
atomic_sub_fetch_64(&pCacheObj->totalSize, pNode->size);
|
||||
int32_t size = (int32_t)taosHashGetSize(pCacheObj->pHashTable);
|
||||
assert(size > 0);
|
||||
|
||||
uDebug("cache:%s, key:%p, %p is destroyed from cache, size:%dbytes, totalNum:%d size:%" PRId64 "bytes",
|
||||
uDebug("cache:%s, key:%p, %p is destroyed from cache, size:%dbytes, total num:%d size:%" PRId64 "bytes",
|
||||
pCacheObj->name, pNode->key, pNode->data, pNode->size, size - 1, pCacheObj->totalSize);
|
||||
|
||||
if (pCacheObj->freeFp) {
|
||||
|
@ -252,6 +252,7 @@ void *taosCachePut(SCacheObj *pCacheObj, const void *key, size_t keyLen, const v
|
|||
pCacheObj->freeFp(p->data);
|
||||
}
|
||||
|
||||
atomic_sub_fetch_64(&pCacheObj->totalSize, p->size);
|
||||
tfree(p);
|
||||
} else {
|
||||
taosAddToTrashcan(pCacheObj, p);
|
||||
|
@ -302,7 +303,7 @@ void *taosCacheAcquireByKey(SCacheObj *pCacheObj, const void *key, size_t keyLen
|
|||
}
|
||||
|
||||
SCacheDataNode* ptNode = NULL;
|
||||
taosHashGetClone(pCacheObj->pHashTable, key, keyLen, incRefFn, &ptNode, sizeof(void*));
|
||||
taosHashGetClone(pCacheObj->pHashTable, key, keyLen, incRefFn, &ptNode);
|
||||
|
||||
void* pData = (ptNode != NULL)? ptNode->data:NULL;
|
||||
|
||||
|
@ -679,7 +680,7 @@ void* taosCacheTimedRefresh(void *handle) {
|
|||
assert(pCacheArrayList != NULL);
|
||||
uDebug("cache refresh thread starts");
|
||||
|
||||
setThreadName("cacheTimedRefre");
|
||||
setThreadName("cacheRefresh");
|
||||
|
||||
const int32_t SLEEP_DURATION = 500; //500 ms
|
||||
int64_t count = 0;
|
||||
|
|
|
@ -159,7 +159,7 @@ int tsCompressINTImp(const char *const input, const int nelements, char *const o
|
|||
break;
|
||||
}
|
||||
// Get difference.
|
||||
if (!safeInt64Add(curr_value, -prev_value)) goto _copy_and_exit;
|
||||
if (!safeInt64Add(curr_value, -prev_value_tmp)) goto _copy_and_exit;
|
||||
|
||||
int64_t diff = curr_value - prev_value_tmp;
|
||||
// Zigzag encode the value.
|
||||
|
@ -997,4 +997,4 @@ int tsDecompressDoubleLossyImp(const char * input, int compressedSize, const int
|
|||
// decompressed with sz
|
||||
return tdszDecompress(SZ_DOUBLE, input + 1, compressedSize - 1, nelements, output);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "tfunctional.h"
|
||||
#include "tarray.h"
|
||||
|
||||
|
||||
tGenericSavedFunc* genericSavedFuncInit(GenericVaFunc func, int numOfArgs) {
|
||||
tGenericSavedFunc* pSavedFunc = malloc(sizeof(tGenericSavedFunc) + numOfArgs * (sizeof(void*)));
|
||||
pSavedFunc->func = func;
|
||||
return pSavedFunc;
|
||||
}
|
||||
|
||||
tI32SavedFunc* i32SavedFuncInit(I32VaFunc func, int numOfArgs) {
|
||||
tI32SavedFunc* pSavedFunc = malloc(sizeof(tI32SavedFunc) + numOfArgs * sizeof(void *));
|
||||
pSavedFunc->func = func;
|
||||
return pSavedFunc;
|
||||
}
|
||||
|
||||
tVoidSavedFunc* voidSavedFuncInit(VoidVaFunc func, int numOfArgs) {
|
||||
tVoidSavedFunc* pSavedFunc = malloc(sizeof(tVoidSavedFunc) + numOfArgs * sizeof(void*));
|
||||
pSavedFunc->func = func;
|
||||
return pSavedFunc;
|
||||
}
|
||||
|
||||
FORCE_INLINE void* genericInvoke(tGenericSavedFunc* const pSavedFunc) {
|
||||
return pSavedFunc->func(pSavedFunc->args);
|
||||
}
|
||||
|
||||
FORCE_INLINE int32_t i32Invoke(tI32SavedFunc* const pSavedFunc) {
|
||||
return pSavedFunc->func(pSavedFunc->args);
|
||||
}
|
||||
|
||||
FORCE_INLINE void voidInvoke(tVoidSavedFunc* const pSavedFunc) {
|
||||
if(pSavedFunc) pSavedFunc->func(pSavedFunc->args);
|
||||
}
|
|
@ -178,8 +178,6 @@ static void *taosThreadToOpenNewFile(void *param) {
|
|||
char keepName[LOG_FILE_NAME_LEN + 20];
|
||||
sprintf(keepName, "%s.%d", tsLogObj.logName, tsLogObj.flag);
|
||||
|
||||
setThreadName("openNewFile");
|
||||
|
||||
tsLogObj.flag ^= 1;
|
||||
tsLogObj.lines = 0;
|
||||
char name[LOG_FILE_NAME_LEN + 20];
|
||||
|
@ -689,12 +687,9 @@ static void taosWriteLog(SLogBuff *tLogBuff) {
|
|||
|
||||
static void *taosAsyncOutputLog(void *param) {
|
||||
SLogBuff *tLogBuff = (SLogBuff *)param;
|
||||
|
||||
setThreadName("asyncOutputLog");
|
||||
setThreadName("log");
|
||||
|
||||
while (1) {
|
||||
//tsem_wait(&(tLogBuff->buffNotEmpty));
|
||||
|
||||
taosMsleep(writeInterval);
|
||||
|
||||
// Polling the buffer
|
||||
|
|
|
@ -122,7 +122,9 @@ void *taosProcessSchedQueue(void *scheduler) {
|
|||
SSchedQueue *pSched = (SSchedQueue *)scheduler;
|
||||
int ret = 0;
|
||||
|
||||
setThreadName("schedQ");
|
||||
char name[16] = {0};
|
||||
snprintf(name, tListLen(name), "%s-taskQ", pSched->label);
|
||||
setThreadName(name);
|
||||
|
||||
while (1) {
|
||||
if ((ret = tsem_wait(&pSched->fullSem)) != 0) {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "tskiplist.h"
|
||||
#include "os.h"
|
||||
#include "tcompare.h"
|
||||
#include "tdataformat.h"
|
||||
#include "tulog.h"
|
||||
#include "tutil.h"
|
||||
|
||||
|
@ -31,6 +32,7 @@ static SSkipListNode *tSkipListNewNode(uint8_t level);
|
|||
static SSkipListNode *tSkipListPutImpl(SSkipList *pSkipList, void *pData, SSkipListNode **direction, bool isForward,
|
||||
bool hasDup);
|
||||
|
||||
|
||||
static FORCE_INLINE int tSkipListWLock(SSkipList *pSkipList);
|
||||
static FORCE_INLINE int tSkipListRLock(SSkipList *pSkipList);
|
||||
static FORCE_INLINE int tSkipListUnlock(SSkipList *pSkipList);
|
||||
|
@ -80,6 +82,7 @@ SSkipList *tSkipListCreate(uint8_t maxLevel, uint8_t keyType, uint16_t keyLen, _
|
|||
#if SKIP_LIST_RECORD_PERFORMANCE
|
||||
pSkipList->state.nTotalMemSize += sizeof(SSkipList);
|
||||
#endif
|
||||
pSkipList->insertHandleFn = NULL;
|
||||
|
||||
return pSkipList;
|
||||
}
|
||||
|
@ -97,6 +100,8 @@ void tSkipListDestroy(SSkipList *pSkipList) {
|
|||
tSkipListFreeNode(pTemp);
|
||||
}
|
||||
|
||||
tfree(pSkipList->insertHandleFn);
|
||||
|
||||
tSkipListUnlock(pSkipList);
|
||||
if (pSkipList->lock != NULL) {
|
||||
pthread_rwlock_destroy(pSkipList->lock);
|
||||
|
@ -124,8 +129,7 @@ SSkipListNode *tSkipListPut(SSkipList *pSkipList, void *pData) {
|
|||
return pNode;
|
||||
}
|
||||
|
||||
// Put a batch of data into skiplist. The batch of data must be in ascending order
|
||||
void tSkipListPutBatch(SSkipList *pSkipList, void **ppData, int ndata) {
|
||||
void tSkipListPutBatchByIter(SSkipList *pSkipList, void *iter, iter_next_fn_t iterate) {
|
||||
SSkipListNode *backward[MAX_SKIP_LIST_LEVEL] = {0};
|
||||
SSkipListNode *forward[MAX_SKIP_LIST_LEVEL] = {0};
|
||||
bool hasDup = false;
|
||||
|
@ -135,17 +139,21 @@ void tSkipListPutBatch(SSkipList *pSkipList, void **ppData, int ndata) {
|
|||
|
||||
tSkipListWLock(pSkipList);
|
||||
|
||||
void* pData = iterate(iter);
|
||||
if(pData == NULL) return;
|
||||
|
||||
// backward to put the first data
|
||||
hasDup = tSkipListGetPosToPut(pSkipList, backward, ppData[0]);
|
||||
tSkipListPutImpl(pSkipList, ppData[0], backward, false, hasDup);
|
||||
hasDup = tSkipListGetPosToPut(pSkipList, backward, pData);
|
||||
|
||||
tSkipListPutImpl(pSkipList, pData, backward, false, hasDup);
|
||||
|
||||
for (int level = 0; level < pSkipList->maxLevel; level++) {
|
||||
forward[level] = SL_NODE_GET_BACKWARD_POINTER(backward[level], level);
|
||||
}
|
||||
|
||||
// forward to put the rest of data
|
||||
for (int idata = 1; idata < ndata; idata++) {
|
||||
pDataKey = pSkipList->keyFn(ppData[idata]);
|
||||
while ((pData = iterate(iter)) != NULL) {
|
||||
pDataKey = pSkipList->keyFn(pData);
|
||||
hasDup = false;
|
||||
|
||||
// Compare max key
|
||||
|
@ -186,9 +194,8 @@ void tSkipListPutBatch(SSkipList *pSkipList, void **ppData, int ndata) {
|
|||
}
|
||||
}
|
||||
|
||||
tSkipListPutImpl(pSkipList, ppData[idata], forward, true, hasDup);
|
||||
tSkipListPutImpl(pSkipList, pData, forward, true, hasDup);
|
||||
}
|
||||
|
||||
tSkipListUnlock(pSkipList);
|
||||
}
|
||||
|
||||
|
@ -661,18 +668,40 @@ static SSkipListNode *tSkipListPutImpl(SSkipList *pSkipList, void *pData, SSkipL
|
|||
uint8_t dupMode = SL_DUP_MODE(pSkipList);
|
||||
SSkipListNode *pNode = NULL;
|
||||
|
||||
if (hasDup && (dupMode == SL_DISCARD_DUP_KEY || dupMode == SL_UPDATE_DUP_KEY)) {
|
||||
if (hasDup && (dupMode != SL_ALLOW_DUP_KEY)) {
|
||||
if (dupMode == SL_UPDATE_DUP_KEY) {
|
||||
if (isForward) {
|
||||
pNode = SL_NODE_GET_FORWARD_POINTER(direction[0], 0);
|
||||
} else {
|
||||
pNode = SL_NODE_GET_BACKWARD_POINTER(direction[0], 0);
|
||||
}
|
||||
atomic_store_ptr(&(pNode->pData), pData);
|
||||
if (pSkipList->insertHandleFn) {
|
||||
pSkipList->insertHandleFn->args[0] = pData;
|
||||
pSkipList->insertHandleFn->args[1] = pNode->pData;
|
||||
pData = genericInvoke(pSkipList->insertHandleFn);
|
||||
}
|
||||
if(pData) {
|
||||
atomic_store_ptr(&(pNode->pData), pData);
|
||||
}
|
||||
} else {
|
||||
//for compatiblity, duplicate key inserted when update=0 should be also calculated as affected rows!
|
||||
if(pSkipList->insertHandleFn) {
|
||||
pSkipList->insertHandleFn->args[0] = NULL;
|
||||
pSkipList->insertHandleFn->args[1] = NULL;
|
||||
genericInvoke(pSkipList->insertHandleFn);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pNode = tSkipListNewNode(getSkipListRandLevel(pSkipList));
|
||||
if (pNode != NULL) {
|
||||
// insertHandleFn will be assigned only for timeseries data,
|
||||
// in which case, pData is pointed to an memory to be freed later;
|
||||
// while for metadata, the mem alloc will not be called.
|
||||
if (pSkipList->insertHandleFn) {
|
||||
pSkipList->insertHandleFn->args[0] = pData;
|
||||
pSkipList->insertHandleFn->args[1] = NULL;
|
||||
pData = genericInvoke(pSkipList->insertHandleFn);
|
||||
}
|
||||
pNode->pData = pData;
|
||||
|
||||
tSkipListDoInsert(pSkipList, direction, pNode, isForward);
|
||||
|
|
|
@ -69,12 +69,12 @@ void taosStringBuilderAppendNull(SStringBuilder* sb) { taosStringBuilderAppendSt
|
|||
|
||||
void taosStringBuilderAppendInteger(SStringBuilder* sb, int64_t v) {
|
||||
char buf[64];
|
||||
size_t len = sprintf(buf, "%" PRId64, v);
|
||||
taosStringBuilderAppendStringLen(sb, buf, len);
|
||||
size_t len = snprintf(buf, sizeof(buf), "%" PRId64, v);
|
||||
taosStringBuilderAppendStringLen(sb, buf, MIN(len, sizeof(buf)));
|
||||
}
|
||||
|
||||
void taosStringBuilderAppendDouble(SStringBuilder* sb, double v) {
|
||||
char buf[64];
|
||||
size_t len = sprintf(buf, "%.9lf", v);
|
||||
taosStringBuilderAppendStringLen(sb, buf, len);
|
||||
char buf[512];
|
||||
size_t len = snprintf(buf, sizeof(buf), "%.9lf", v);
|
||||
taosStringBuilderAppendStringLen(sb, buf, MIN(len, sizeof(buf)));
|
||||
}
|
||||
|
|
|
@ -35,8 +35,6 @@ void *addRef(void *param) {
|
|||
SRefSpace *pSpace = (SRefSpace *)param;
|
||||
int id;
|
||||
|
||||
setThreadName("addRef");
|
||||
|
||||
for (int i=0; i < pSpace->steps; ++i) {
|
||||
printf("a");
|
||||
id = random() % pSpace->refNum;
|
||||
|
@ -54,8 +52,6 @@ void *removeRef(void *param) {
|
|||
SRefSpace *pSpace = (SRefSpace *)param;
|
||||
int id, code;
|
||||
|
||||
setThreadName("removeRef");
|
||||
|
||||
for (int i=0; i < pSpace->steps; ++i) {
|
||||
printf("d");
|
||||
id = random() % pSpace->refNum;
|
||||
|
@ -74,8 +70,6 @@ void *acquireRelease(void *param) {
|
|||
SRefSpace *pSpace = (SRefSpace *)param;
|
||||
int id;
|
||||
|
||||
setThreadName("acquireRelease");
|
||||
|
||||
for (int i=0; i < pSpace->steps; ++i) {
|
||||
printf("a");
|
||||
|
||||
|
@ -97,8 +91,6 @@ void myfree(void *p) {
|
|||
void *openRefSpace(void *param) {
|
||||
SRefSpace *pSpace = (SRefSpace *)param;
|
||||
|
||||
setThreadName("openRefSpace");
|
||||
|
||||
printf("c");
|
||||
pSpace->rsetId = taosOpenRef(50, myfree);
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ static void vnodeIncRef(void *ptNode) {
|
|||
void *vnodeAcquire(int32_t vgId) {
|
||||
SVnodeObj *pVnode = NULL;
|
||||
if (tsVnodesHash != NULL) {
|
||||
taosHashGetClone(tsVnodesHash, &vgId, sizeof(int32_t), vnodeIncRef, &pVnode, sizeof(void *));
|
||||
taosHashGetClone(tsVnodesHash, &vgId, sizeof(int32_t), vnodeIncRef, &pVnode);
|
||||
}
|
||||
|
||||
if (pVnode == NULL) {
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
typedef enum {
|
||||
VNODE_WORKER_ACTION_CLEANUP,
|
||||
VNODE_WORKER_ACTION_DESTROUY
|
||||
VNODE_WORKER_ACTION_DESTROY
|
||||
} EVMWorkerAction;
|
||||
|
||||
typedef struct {
|
||||
|
@ -155,7 +155,7 @@ int32_t vnodeCleanupInMWorker(SVnodeObj *pVnode) {
|
|||
|
||||
int32_t vnodeDestroyInMWorker(SVnodeObj *pVnode) {
|
||||
vTrace("vgId:%d, will destroy in vmworker", pVnode->vgId);
|
||||
return vnodeWriteIntoMWorker(pVnode, VNODE_WORKER_ACTION_DESTROUY, NULL);
|
||||
return vnodeWriteIntoMWorker(pVnode, VNODE_WORKER_ACTION_DESTROY, NULL);
|
||||
}
|
||||
|
||||
static void vnodeFreeMWorkerMsg(SVMWorkerMsg *pMsg) {
|
||||
|
@ -179,7 +179,7 @@ static void vnodeProcessMWorkerMsg(SVMWorkerMsg *pMsg) {
|
|||
case VNODE_WORKER_ACTION_CLEANUP:
|
||||
vnodeCleanUp(pMsg->pVnode);
|
||||
break;
|
||||
case VNODE_WORKER_ACTION_DESTROUY:
|
||||
case VNODE_WORKER_ACTION_DESTROY:
|
||||
vnodeDestroy(pMsg->pVnode);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -192,7 +192,7 @@ static void walFsyncAll() {
|
|||
|
||||
static void *walThreadFunc(void *param) {
|
||||
int stop = 0;
|
||||
setThreadName("walThrd");
|
||||
setThreadName("wal");
|
||||
while (1) {
|
||||
walUpdateSeq();
|
||||
walFsyncAll();
|
||||
|
|
|
@ -1,5 +1,32 @@
|
|||
def pre_test(){
|
||||
|
||||
sh '''
|
||||
sudo rmtaos||echo 'no taosd installed'
|
||||
'''
|
||||
sh '''
|
||||
cd ${WKC}
|
||||
git reset --hard
|
||||
git checkout $BRANCH_NAME
|
||||
git pull
|
||||
git submodule update
|
||||
cd ${WK}
|
||||
git reset --hard
|
||||
git checkout $BRANCH_NAME
|
||||
git pull
|
||||
export TZ=Asia/Harbin
|
||||
date
|
||||
rm -rf ${WK}/debug
|
||||
mkdir debug
|
||||
cd debug
|
||||
cmake -DMEMORY_SANITIZER=true .. > /dev/null
|
||||
make > /dev/null
|
||||
make install > /dev/null
|
||||
pip3 install ${WKC}/src/connector/python
|
||||
'''
|
||||
return 1
|
||||
}
|
||||
def pre_test_p(){
|
||||
|
||||
sh '''
|
||||
sudo rmtaos||echo 'no taosd installed'
|
||||
'''
|
||||
|
@ -39,7 +66,7 @@ pipeline {
|
|||
stage('pytest') {
|
||||
agent{label 'slad1'}
|
||||
steps {
|
||||
pre_test()
|
||||
pre_test_p()
|
||||
sh '''
|
||||
cd ${WKC}/tests
|
||||
find pytest -name '*'sql|xargs rm -rf
|
||||
|
@ -48,7 +75,7 @@ pipeline {
|
|||
}
|
||||
}
|
||||
stage('test_b1') {
|
||||
agent{label 'master'}
|
||||
agent{label 'slad2'}
|
||||
steps {
|
||||
pre_test()
|
||||
|
||||
|
@ -62,7 +89,7 @@ pipeline {
|
|||
}
|
||||
|
||||
stage('test_crash_gen') {
|
||||
agent{label "slad2"}
|
||||
agent{label "slad3"}
|
||||
steps {
|
||||
pre_test()
|
||||
sh '''
|
||||
|
@ -92,7 +119,7 @@ pipeline {
|
|||
}
|
||||
|
||||
sh'''
|
||||
systemctl start taosd
|
||||
nohup taosd >/dev/null &
|
||||
sleep 10
|
||||
'''
|
||||
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
|
||||
|
@ -128,7 +155,7 @@ pipeline {
|
|||
'''
|
||||
}
|
||||
sh '''
|
||||
systemctl stop taosd
|
||||
pkill -9 taosd
|
||||
cd ${WKC}/tests
|
||||
./test-all.sh b2
|
||||
date
|
||||
|
@ -141,7 +168,7 @@ pipeline {
|
|||
}
|
||||
|
||||
stage('test_valgrind') {
|
||||
agent{label "slad3"}
|
||||
agent{label "slad4"}
|
||||
|
||||
steps {
|
||||
pre_test()
|
||||
|
|
|
@ -359,7 +359,7 @@ void verify_prepare(TAOS* taos) {
|
|||
v.v8 = (int64_t)(i * 8);
|
||||
v.f4 = (float)(i * 40);
|
||||
v.f8 = (double)(i * 80);
|
||||
for (int j = 0; j < sizeof(v.bin) - 1; ++j) {
|
||||
for (int j = 0; j < sizeof(v.bin); ++j) {
|
||||
v.bin[j] = (char)(i + '0');
|
||||
}
|
||||
|
||||
|
@ -556,7 +556,7 @@ void verify_prepare2(TAOS* taos) {
|
|||
v.v8[i] = (int64_t)(i * 8);
|
||||
v.f4[i] = (float)(i * 40);
|
||||
v.f8[i] = (double)(i * 80);
|
||||
for (int j = 0; j < sizeof(v.bin[0]) - 1; ++j) {
|
||||
for (int j = 0; j < sizeof(v.bin[0]); ++j) {
|
||||
v.bin[i][j] = (char)(i + '0');
|
||||
}
|
||||
strcpy(v.blob[i], "一二三四五六七八九十");
|
||||
|
@ -808,7 +808,7 @@ void verify_prepare3(TAOS* taos) {
|
|||
v.v8[i] = (int64_t)(i * 8);
|
||||
v.f4[i] = (float)(i * 40);
|
||||
v.f8[i] = (double)(i * 80);
|
||||
for (int j = 0; j < sizeof(v.bin[0]) - 1; ++j) {
|
||||
for (int j = 0; j < sizeof(v.bin[0]); ++j) {
|
||||
v.bin[i][j] = (char)(i + '0');
|
||||
}
|
||||
strcpy(v.blob[i], "一二三四五六七八九十");
|
||||
|
@ -1031,7 +1031,7 @@ int main(int argc, char *argv[]) {
|
|||
info = taos_get_client_info(taos);
|
||||
printf("client info: %s\n", info);
|
||||
|
||||
printf("************ verify shemaless *************\n");
|
||||
printf("************ verify schema-less *************\n");
|
||||
verify_schema_less(taos);
|
||||
|
||||
|
||||
|
@ -1049,14 +1049,12 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
printf("************ verify prepare2 *************\n");
|
||||
verify_prepare2(taos);
|
||||
|
||||
printf("************ verify prepare3 *************\n");
|
||||
verify_prepare3(taos);
|
||||
|
||||
|
||||
printf("************ verify stream *************\n");
|
||||
verify_stream(taos);
|
||||
printf("done\n");
|
||||
|
||||
taos_close(taos);
|
||||
taos_cleanup();
|
||||
}
|
||||
|
|
|
@ -157,5 +157,45 @@ int main(int argc, char* argv[]) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
//Duplicate key check;
|
||||
char* lines_003_1[] = {
|
||||
"std,id=\"std_3_1\",t1=4i64,Id=\"std\",t2=true c1=true 1626006834s"
|
||||
};
|
||||
|
||||
code = taos_insert_lines(taos, lines_003_1 , sizeof(lines_003_1)/sizeof(char*));
|
||||
if (0 == code) {
|
||||
printf("taos_insert_lines() lines_003_1 return code:%d (%s)\n", code, (char*)tstrerror(code));
|
||||
return -1;
|
||||
}
|
||||
|
||||
char* lines_003_2[] = {
|
||||
"std,id=\"std_3_2\",tag1=4i64,Tag2=true,tAg3=2,TaG2=\"dup!\" c1=true 1626006834s"
|
||||
};
|
||||
|
||||
code = taos_insert_lines(taos, lines_003_2 , sizeof(lines_003_2)/sizeof(char*));
|
||||
if (0 == code) {
|
||||
printf("taos_insert_lines() lines_003_2 return code:%d (%s)\n", code, (char*)tstrerror(code));
|
||||
return -1;
|
||||
}
|
||||
|
||||
char* lines_003_3[] = {
|
||||
"std,id=\"std_3_3\",tag1=4i64 field1=true,Field2=2,FIElD1=\"dup!\",fIeLd4=true 1626006834s"
|
||||
};
|
||||
|
||||
code = taos_insert_lines(taos, lines_003_3 , sizeof(lines_003_3)/sizeof(char*));
|
||||
if (0 == code) {
|
||||
printf("taos_insert_lines() lines_003_3 return code:%d (%s)\n", code, (char*)tstrerror(code));
|
||||
return -1;
|
||||
}
|
||||
|
||||
char* lines_003_4[] = {
|
||||
"std,id=\"std_3_4\",tag1=4i64,dupkey=4i16,tag2=T field1=true,dUpkEy=1e3f32,field2=\"1234\" 1626006834s"
|
||||
};
|
||||
|
||||
code = taos_insert_lines(taos, lines_003_4 , sizeof(lines_003_4)/sizeof(char*));
|
||||
if (0 == code) {
|
||||
printf("taos_insert_lines() lines_003_4 return code:%d (%s)\n", code, (char*)tstrerror(code));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,32 @@
|
|||
def pre_test(){
|
||||
|
||||
sh '''
|
||||
sudo rmtaos||echo 'no taosd installed'
|
||||
'''
|
||||
sh '''
|
||||
cd ${WKC}
|
||||
git reset --hard
|
||||
git checkout $BRANCH_NAME
|
||||
git pull
|
||||
git submodule update
|
||||
cd ${WK}
|
||||
git reset --hard
|
||||
git checkout $BRANCH_NAME
|
||||
git pull
|
||||
export TZ=Asia/Harbin
|
||||
date
|
||||
rm -rf ${WK}/debug
|
||||
mkdir debug
|
||||
cd debug
|
||||
cmake -DMEMORY_SANITIZER=true .. > /dev/null
|
||||
make > /dev/null
|
||||
make install > /dev/null
|
||||
pip3 install ${WKC}/src/connector/python/ || echo 0
|
||||
'''
|
||||
return 1
|
||||
}
|
||||
def pre_test_p(){
|
||||
|
||||
sh '''
|
||||
sudo rmtaos||echo 'no taosd installed'
|
||||
'''
|
||||
|
@ -39,7 +66,7 @@ pipeline {
|
|||
stage('pytest') {
|
||||
agent{label 'slam1'}
|
||||
steps {
|
||||
pre_test()
|
||||
pre_test_p()
|
||||
sh '''
|
||||
cd ${WKC}/tests
|
||||
find pytest -name '*'sql|xargs rm -rf
|
||||
|
@ -92,7 +119,7 @@ pipeline {
|
|||
}
|
||||
|
||||
sh'''
|
||||
systemctl start taosd
|
||||
nohup taosd >/dev/null &
|
||||
sleep 10
|
||||
'''
|
||||
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
|
||||
|
@ -136,7 +163,7 @@ pipeline {
|
|||
'''
|
||||
}
|
||||
sh '''
|
||||
systemctl stop taosd
|
||||
pkill -9 taosd
|
||||
cd ${WKC}/tests
|
||||
./test-all.sh b2
|
||||
date
|
||||
|
|
|
@ -163,7 +163,12 @@ python3 test.py -f tools/taosdemoTestSampleData.py
|
|||
python3 test.py -f tools/taosdemoTestInterlace.py
|
||||
python3 test.py -f tools/taosdemoTestQuery.py
|
||||
|
||||
|
||||
# nano support
|
||||
python3 test.py -f tools/taosdemoAllTest/taosdemoTestSupportNanoInsert.py
|
||||
python3 test.py -f tools/taosdemoAllTest/taosdemoTestSupportNanoQuery.py
|
||||
python3 test.py -f tools/taosdemoAllTest/taosdemoTestSupportNanosubscribe.py
|
||||
python3 test.py -f tools/taosdemoAllTest/taosdemoTestInsertTime_step.py
|
||||
python3 test.py -f tools/taosdumpTestNanoSupport.py
|
||||
|
||||
# update
|
||||
python3 ./test.py -f update/allow_update.py
|
||||
|
@ -247,6 +252,7 @@ python3 ./test.py -f query/queryStateWindow.py
|
|||
python3 ./test.py -f query/nestedQuery/queryWithOrderLimit.py
|
||||
python3 ./test.py -f query/nestquery_last_row.py
|
||||
python3 ./test.py -f query/queryCnameDisplay.py
|
||||
python3 ./test.py -f query/operator_cost.py
|
||||
python3 test.py -f query/nestedQuery/queryWithSpread.py
|
||||
|
||||
#stream
|
||||
|
@ -360,12 +366,23 @@ python3 ./test.py -f tag_lite/alter_tag.py
|
|||
|
||||
|
||||
python3 test.py -f tools/taosdemoAllTest/TD-4985/query-limit-offset.py
|
||||
python3 test.py -f tools/taosdemoAllTest/TD-5213/insert4096columns_not_use_taosdemo.py
|
||||
python3 test.py -f tools/taosdemoAllTest/TD-5213/insertSigcolumnsNum4096.py
|
||||
python3 ./test.py -f tag_lite/drop_auto_create.py
|
||||
python3 test.py -f insert/insert_before_use_db.py
|
||||
python3 test.py -f alter/alter_keep.py
|
||||
python3 test.py -f alter/alter_cacheLastRow.py
|
||||
python3 ./test.py -f query/querySession.py
|
||||
python3 test.py -f alter/alter_create_exception.py
|
||||
|
||||
python3 ./test.py -f insert/flushwhiledrop.py
|
||||
|
||||
#======================p4-end===============
|
||||
python3 test.py -f tools/taosdemoAllTest/pytest.py
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -77,6 +77,8 @@ class TDTestCase:
|
|||
"sth,t1=4i64,t2=5f64,t4=5f64,ID=\"childtable\" c1=3i64,c3=L\"passitagin_stf\",c2=false,c5=5f64,c6=7u64 1626006933641ms",
|
||||
"sth,t1=4i64,t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin_stf\",c2=false,c5=5f64,c6=7u64 1626006933654ms"
|
||||
])
|
||||
tdSql.execute('reset query cache')
|
||||
|
||||
tdSql.query('select tbname, * from sth')
|
||||
tdSql.checkRows(2)
|
||||
|
||||
|
|
|
@ -70,6 +70,14 @@ class TDTestCase:
|
|||
tdSql.query("select * from (select avg(value), sum(value) from st group by tbname slimit 5 soffset 7)")
|
||||
tdSql.checkRows(3)
|
||||
|
||||
# https://jira.taosdata.com:18080/browse/TD-5497
|
||||
tdSql.execute("create table tt(ts timestamp ,i int)")
|
||||
tdSql.execute("insert into tt values(now, 11)(now + 1s, -12)")
|
||||
tdSql.query("select * from (select max(i),0-min(i) from tt)")
|
||||
tdSql.checkRows(1);
|
||||
tdSql.checkData(0, 0, 11);
|
||||
tdSql.checkData(0, 1, 12.0);
|
||||
|
||||
def stop(self):
|
||||
tdSql.close()
|
||||
tdLog.success("%s successfully executed" % __file__)
|
||||
|
|
|
@ -0,0 +1,536 @@
|
|||
###################################################################
|
||||
# Copyright (c) 2016 by TAOS Technologies, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This file is proprietary and confidential to TAOS Technologies.
|
||||
# No part of this file may be reproduced, stored, transmitted,
|
||||
# disclosed or used in any form or by any means other than as
|
||||
# expressly provided by the written permission from Jianhui Tao
|
||||
#
|
||||
###################################################################
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
import taos
|
||||
from util.log import tdLog
|
||||
from util.cases import tdCases
|
||||
from util.sql import tdSql
|
||||
import random
|
||||
import time
|
||||
|
||||
|
||||
class TDTestCase:
|
||||
def init(self, conn, logSql):
|
||||
tdLog.debug("start to execute %s" % __file__)
|
||||
tdSql.init(conn.cursor(), logSql)
|
||||
|
||||
self.ts = 1600000000000
|
||||
self.num = 10
|
||||
|
||||
def run(self):
|
||||
tdSql.prepare()
|
||||
# test case for https://jira.taosdata.com:18080/browse/TD-5074
|
||||
|
||||
startTime = time.time()
|
||||
|
||||
tdSql.execute('''create stable stable_1
|
||||
(ts timestamp , q_int int , q_bigint bigint , q_smallint smallint , q_tinyint tinyint,
|
||||
q_bool bool , q_binary binary(20) , q_nchar nchar(20) ,
|
||||
q_float float , q_double double , q_ts timestamp)
|
||||
tags(loc nchar(20) , t_int int , t_bigint bigint , t_smallint smallint , t_tinyint tinyint,
|
||||
t_bool bool , t_binary binary(20) , t_nchar nchar(20) ,
|
||||
t_float float , t_double double , t_ts timestamp);''')
|
||||
tdSql.execute('''create stable stable_2
|
||||
(ts timestamp , q_int int , q_bigint bigint , q_smallint smallint , q_tinyint tinyint,
|
||||
q_bool bool , q_binary binary(20) , q_nchar nchar(20) ,
|
||||
q_float float , q_double double , q_ts timestamp)
|
||||
tags(loc nchar(20) , t_int int , t_bigint bigint , t_smallint smallint , t_tinyint tinyint,
|
||||
t_bool bool , t_binary binary(20) , t_nchar nchar(20) ,
|
||||
t_float float , t_double double , t_ts timestamp);''')
|
||||
tdSql.execute('''create table table_0 using stable_1
|
||||
tags('table_0' , '0' , '0' , '0' , '0' , 0 , '0' , '0' , '0' , '0' ,'0')''')
|
||||
tdSql.execute('''create table table_1 using stable_1
|
||||
tags('table_1' , '2147483647' , '9223372036854775807' , '32767' , '127' , 1 ,
|
||||
'binary1' , 'nchar1' , '1' , '11' , \'1999-09-09 09:09:09.090\')''')
|
||||
tdSql.execute('''create table table_2 using stable_1
|
||||
tags('table_2' , '-2147483647' , '-9223372036854775807' , '-32767' , '-127' , false ,
|
||||
'binary2' , 'nchar2nchar2' , '-2.2' , '-22.22' , \'2099-09-09 09:09:09.090\')''')
|
||||
tdSql.execute('''create table table_3 using stable_1
|
||||
tags('table_3' , '3' , '3' , '3' , '3' , true , 'binary3' , 'nchar3' , '33.33' , '3333.3333' , '0')''')
|
||||
tdSql.execute('''create table table_4 using stable_1
|
||||
tags('table_4' , '4' , '4' , '4' , '4' , false , 'binary4' , 'nchar4' , '-444.444' , '-444444.444444' , '0')''')
|
||||
tdSql.execute('''create table table_5 using stable_1
|
||||
tags('table_5' , '5' , '5' , '5' , '5' , true , 'binary5' , 'nchar5' , '5555.5555' , '55555555.55555555' , '0')''')
|
||||
tdSql.execute('''create table table_21 using stable_2
|
||||
tags('table_5' , '5' , '5' , '5' , '5' , true , 'binary5' , 'nchar5' , '5555.5555' , '55555555.55555555' , '0')''')
|
||||
#regular table
|
||||
tdSql.execute('''create table regular_table_1
|
||||
(ts timestamp , q_int int , q_bigint bigint , q_smallint smallint , q_tinyint tinyint,
|
||||
q_bool bool , q_binary binary(20) , q_nchar nchar(20) ,
|
||||
q_float float , q_double double , q_ts timestamp) ;''')
|
||||
|
||||
for i in range(self.num):
|
||||
tdSql.execute('''insert into table_0 values(%d, %d, %d, %d, %d, 0, 'binary.%s', 'nchar.%s', %f, %f, %d)'''
|
||||
% (self.ts + i, i, i, i, i, i, i, i, i, self.ts + i))
|
||||
tdSql.execute('''insert into table_1 values(%d, %d, %d, %d, %d, 1, 'binary1.%s', 'nchar1.%s', %f, %f, %d)'''
|
||||
% (self.ts + i, 2147483647-i, 9223372036854775807-i, 32767-i, 127-i,
|
||||
i, i, random.random(), random.random(), 1262304000001 + i))
|
||||
tdSql.execute('''insert into table_2 values(%d, %d, %d, %d, %d, true, 'binary2.%s', 'nchar2nchar2.%s', %f, %f, %d)'''
|
||||
% (self.ts + i, -2147483647+i, -9223372036854775807+i, -32767+i, -127+i,
|
||||
i, i, random.uniform(-1,0), random.uniform(-1,0), 1577836800001 + i))
|
||||
tdSql.execute('''insert into table_3 values(%d, %d, %d, %d, %d, false, 'binary3.%s', 'nchar3.%s', %f, %f, %d)'''
|
||||
% (self.ts + i, random.randint(-2147483647, 2147483647),
|
||||
random.randint(-9223372036854775807, 9223372036854775807), random.randint(-32767, 32767),
|
||||
random.randint(-127, 127), random.randint(-100, 100), random.randint(-10000, 10000),
|
||||
random.uniform(-100000,100000), random.uniform(-1000000000,1000000000), self.ts + i))
|
||||
tdSql.execute('''insert into table_4 values(%d, %d, %d, %d, %d, true, 'binary4.%s', 'nchar4.%s', %f, %f, %d)'''
|
||||
% (self.ts + i, i, i, i, i, i, i, i, i, self.ts + i))
|
||||
tdSql.execute('''insert into table_5 values(%d, %d, %d, %d, %d, false, 'binary5.%s', 'nchar5.%s', %f, %f, %d)'''
|
||||
% (self.ts + i, i, i, i, i, i, i, i, i, self.ts + i))
|
||||
tdSql.execute('''insert into table_21 values(%d, %d, %d, %d, %d, false, 'binary5.%s', 'nchar5.%s', %f, %f, %d)'''
|
||||
% (self.ts + i, i, i, i, i, i, i, i, i, self.ts + i))
|
||||
|
||||
tdSql.execute('''insert into regular_table_1 values(%d, %d, %d, %d, %d, 0, 'binary.%s', 'nchar.%s', %f, %f, %d)'''
|
||||
% (self.ts + i, i, i, i, i, i, i, i, i, self.ts + i))
|
||||
tdSql.execute('''insert into regular_table_1 values(%d, %d, %d, %d, %d, 1, 'binary1.%s', 'nchar1.%s', %f, %f, %d)'''
|
||||
% (self.ts + 100 + i, 2147483647-i, 9223372036854775807-i, 32767-i, 127-i,
|
||||
i, i, random.random(), random.random(), 1262304000001 + i))
|
||||
tdSql.execute('''insert into regular_table_1 values(%d, %d, %d, %d, %d, true, 'binary2.%s', 'nchar2nchar2.%s', %f, %f, %d)'''
|
||||
% (self.ts + 200 + i, -2147483647+i, -9223372036854775807+i, -32767+i, -127+i,
|
||||
i, i, random.uniform(-1,0), random.uniform(-1,0), 1577836800001 + i))
|
||||
tdSql.execute('''insert into regular_table_1 values(%d, %d, %d, %d, %d, false, 'binary3.%s', 'nchar3.%s', %f, %f, %d)'''
|
||||
% (self.ts + 300 + i, random.randint(-2147483647, 2147483647),
|
||||
random.randint(-9223372036854775807, 9223372036854775807), random.randint(-32767, 32767),
|
||||
random.randint(-127, 127), random.randint(-100, 100), random.randint(-10000, 10000),
|
||||
random.uniform(-100000,100000), random.uniform(-1000000000,1000000000), self.ts + i))
|
||||
tdSql.execute('''insert into regular_table_1 values(%d, %d, %d, %d, %d, true, 'binary4.%s', 'nchar4.%s', %f, %f, %d)'''
|
||||
% (self.ts + 400 + i, i, i, i, i, i, i, i, i, self.ts + i))
|
||||
tdSql.execute('''insert into regular_table_1 values(%d, %d, %d, %d, %d, false, 'binary5.%s', 'nchar5.%s', %f, %f, %d)'''
|
||||
% (self.ts + 500 + i, i, i, i, i, i, i, i, i, self.ts + i))
|
||||
|
||||
tdLog.info("========== operator=1(OP_TableScan) ==========")
|
||||
tdLog.info("========== operator=7(OP_Project) ==========")
|
||||
sql = '''select * from stable_1'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(6*self.num)
|
||||
sql = '''select * from regular_table_1'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(6*self.num)
|
||||
|
||||
tdLog.info("========== operator=14(OP_MultiTableAggregate ) ==========")
|
||||
sql = '''select last_row(*) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkData(0,1,self.num-1)
|
||||
|
||||
tdLog.info("========== operator=6(OP_Aggregate) ==========")
|
||||
sql = '''select last_row(*) from regular_table_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkData(0,1,self.num-1)
|
||||
|
||||
tdLog.info("========== operator=9(OP_Limit) ==========")
|
||||
sql = '''select * from stable_1 where loc = 'table_0' limit 5;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(5)
|
||||
sql = '''select last_row(*) from (select * from stable_1 where loc = 'table_0');'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
|
||||
sql = '''select * from regular_table_1 ;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(6*self.num)
|
||||
sql = '''select last_row(*) from (select * from regular_table_1);'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkData(0,1,self.num-1)
|
||||
|
||||
|
||||
sql = '''select last_row(*) from
|
||||
((select * from table_0) union all
|
||||
(select * from table_1) union all
|
||||
(select * from table_2));'''
|
||||
tdSql.error(sql)
|
||||
|
||||
tdLog.info("========== operator=16(OP_DummyInput) ==========")
|
||||
sql = '''select last_row(*) from
|
||||
((select last_row(*) from table_0) union all
|
||||
(select last_row(*) from table_1) union all
|
||||
(select last_row(*) from table_2));'''
|
||||
tdSql.error(sql)
|
||||
|
||||
sql = '''select last_row(*) from
|
||||
((select * from table_0 limit 5 offset 5) union all
|
||||
(select * from table_1 limit 5 offset 5) union all
|
||||
(select * from regular_table_1 limit 5 offset 5));'''
|
||||
tdSql.error(sql)
|
||||
|
||||
tdLog.info("========== operator=10(OP_SLimit) ==========")
|
||||
sql = '''select count(*) from stable_1 group by loc slimit 3 soffset 2 ;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(3)
|
||||
|
||||
sql = '''select last_row(*) from
|
||||
((select * from table_0) union all
|
||||
(select * from table_1) union all
|
||||
(select * from table_2));'''
|
||||
tdSql.error(sql)
|
||||
|
||||
tdLog.info("========== operator=20(OP_Distinct) ==========")
|
||||
tdLog.info("========== operator=4(OP_TagScan) ==========")
|
||||
sql = '''select distinct(t_bool) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(2)
|
||||
sql = '''select distinct(loc) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(6)
|
||||
sql = '''select distinct(t_int) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(6)
|
||||
sql = '''select distinct(t_bigint) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(6)
|
||||
sql = '''select distinct(t_smallint) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(6)
|
||||
sql = '''select distinct(t_tinyint) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(6)
|
||||
sql = '''select distinct(t_nchar) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(6)
|
||||
sql = '''select distinct(t_float) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(6)
|
||||
sql = '''select distinct(t_double) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(6)
|
||||
sql = '''select distinct(t_ts) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(3)
|
||||
sql = '''select distinct(tbname) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(6)
|
||||
|
||||
tdLog.info("========== operator=2(OP_DataBlocksOptScan) ==========")
|
||||
sql = '''select last(q_int),first(q_int) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
sql = '''select last(q_bigint),first(q_bigint) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
sql = '''select last(q_smallint),first(q_smallint) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
sql = '''select last(q_tinyint),first(q_tinyint) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
sql = '''select last(q_bool),first(q_bool) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
sql = '''select last(q_binary),first(q_binary) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
sql = '''select last(q_nchar),first(q_nchar) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
sql = '''select last(q_float),first(q_float) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
sql = '''select last(q_double),first(q_double) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
sql = '''select last(q_ts),first(q_ts) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
sql = '''select last(q_int),last(q_bigint), last(q_smallint),last(q_tinyint),last(q_bool),last(q_binary),last(q_nchar),
|
||||
last(q_float),last(q_double),last(q_ts),first(q_int),first(q_bigint),first(q_smallint),first(q_tinyint),
|
||||
first(q_bool),first(q_binary),first(q_nchar),first(q_float),first(q_float),first(q_double),first(q_ts) from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
sql = '''select last(q_int),last(q_bigint), last(q_smallint),last(q_tinyint),last(q_bool),last(q_binary),last(q_nchar),
|
||||
last(q_float),last(q_double),last(q_ts),first(q_int),first(q_bigint),first(q_smallint),first(q_tinyint),first(q_bool),
|
||||
first(q_binary),first(q_nchar),first(q_float),first(q_float),first(q_double),first(q_ts) from regular_table_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
|
||||
tdLog.info("========== operator=8(OP_Groupby) ==========")
|
||||
sql = '''select stddev(q_int) from table_0 group by q_int;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(self.num)
|
||||
sql = '''select stddev(q_int),stddev(q_bigint),stddev(q_smallint),stddev(q_tinyint),stddev(q_float),stddev(q_double) from stable_1 group by q_int;'''
|
||||
tdSql.query(sql)
|
||||
sql = '''select stddev(q_int),stddev(q_bigint),stddev(q_smallint),stddev(q_tinyint),stddev(q_float),stddev(q_double) from table_1 group by q_bigint;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(self.num)
|
||||
sql = '''select stddev(q_int),stddev(q_bigint),stddev(q_smallint),stddev(q_tinyint),stddev(q_float),stddev(q_double) from regular_table_1 group by q_smallint;'''
|
||||
tdSql.query(sql)
|
||||
|
||||
tdLog.info("========== operator=11(OP_TimeWindow) ==========")
|
||||
sql = '''select last(q_int) from table_0 interval(1m);'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
sql = '''select last(q_int),last(q_bigint), last(q_smallint),last(q_tinyint),
|
||||
first(q_int),first(q_bigint),first(q_smallint),first(q_tinyint) from table_1 interval(1m);'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
sql = '''select last(q_int),last(q_bigint), last(q_smallint),last(q_tinyint),
|
||||
first(q_int),first(q_bigint),first(q_smallint),first(q_tinyint) from stable_1 interval(1m);'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
sql = '''select last(q_int),last(q_bigint), last(q_smallint),last(q_tinyint),
|
||||
first(q_int),first(q_bigint),first(q_smallint),first(q_tinyint) from regular_table_1 interval(1m);'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
|
||||
tdLog.info("========== operator=12(OP_SessionWindow) ==========")
|
||||
sql = '''select count(*) from table_1 session(ts,1s);'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
sql = '''select count(*) from regular_table_1 session(ts,1s);'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
sql = '''select count(*),sum(q_int), avg(q_int), min(q_int), max(q_int), first(q_int), last(q_int),
|
||||
sum(q_bigint), avg(q_bigint), min(q_bigint), max(q_bigint), first(q_bigint), last(q_bigint),
|
||||
sum(q_smallint), avg(q_smallint), min(q_smallint), max(q_smallint), first(q_smallint), last(q_smallint),
|
||||
sum(q_tinyint), avg(q_tinyint), min(q_tinyint), max(q_tinyint), first(q_tinyint), last(q_tinyint),
|
||||
sum(q_float), avg(q_float), min(q_float), max(q_float), first(q_float), last(q_float),
|
||||
sum(q_double), avg(q_double), min(q_double), max(q_double), first(q_double), last(q_double)
|
||||
from table_1 session(ts,1s);'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
sql = '''select count(*),sum(q_int), avg(q_int), min(q_int), max(q_int), first(q_int), last(q_int),
|
||||
sum(q_bigint), avg(q_bigint), min(q_bigint), max(q_bigint), first(q_bigint), last(q_bigint),
|
||||
sum(q_smallint), avg(q_smallint), min(q_smallint), max(q_smallint), first(q_smallint), last(q_smallint),
|
||||
sum(q_tinyint), avg(q_tinyint), min(q_tinyint), max(q_tinyint), first(q_tinyint), last(q_tinyint),
|
||||
sum(q_float), avg(q_float), min(q_float), max(q_float), first(q_float), last(q_float),
|
||||
sum(q_double), avg(q_double), min(q_double), max(q_double), first(q_double), last(q_double)
|
||||
from regular_table_1 session(ts,1s);'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
|
||||
tdLog.info("========== operator=13(OP_Fill) ==========")
|
||||
sql = '''select sum(q_int) from table_0
|
||||
where ts >='1970-10-01 00:00:00' and ts <=now interval(1n) fill(NULL);'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkData(0,1,'None')
|
||||
sql = '''select sum(q_int), avg(q_int), min(q_int), max(q_int), first(q_int), last(q_int),
|
||||
sum(q_bigint), avg(q_bigint), min(q_bigint), max(q_bigint), first(q_bigint), last(q_bigint),
|
||||
sum(q_smallint), avg(q_smallint), min(q_smallint), max(q_smallint), first(q_smallint), last(q_smallint),
|
||||
sum(q_tinyint), avg(q_tinyint), min(q_tinyint), max(q_tinyint), first(q_tinyint), last(q_tinyint),
|
||||
sum(q_float), avg(q_float), min(q_float), max(q_float), first(q_float), last(q_float),
|
||||
sum(q_double), avg(q_double), min(q_double), max(q_double), first(q_double), last(q_double)
|
||||
from stable_1 where ts >='1970-10-01 00:00:00' and ts <=now interval(1n) fill(NULL);'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkData(0,1,'None')
|
||||
sql = '''select sum(q_int), avg(q_int), min(q_int), max(q_int), first(q_int), last(q_int),
|
||||
sum(q_bigint), avg(q_bigint), min(q_bigint), max(q_bigint), first(q_bigint), last(q_bigint),
|
||||
sum(q_smallint), avg(q_smallint), min(q_smallint), max(q_smallint), first(q_smallint), last(q_smallint),
|
||||
sum(q_tinyint), avg(q_tinyint), min(q_tinyint), max(q_tinyint), first(q_tinyint), last(q_tinyint),
|
||||
sum(q_float), avg(q_float), min(q_float), max(q_float), first(q_float), last(q_float),
|
||||
sum(q_double), avg(q_double), min(q_double), max(q_double), first(q_double), last(q_double)
|
||||
from regular_table_1 where ts >='1970-10-01 00:00:00' and ts <=now interval(1n) fill(NULL);'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkData(0,1,'None')
|
||||
sql = '''select sum(q_int), avg(q_int), min(q_int), max(q_int), first(q_int), last(q_int),
|
||||
sum(q_bigint), avg(q_bigint), min(q_bigint), max(q_bigint), first(q_bigint), last(q_bigint),
|
||||
sum(q_smallint), avg(q_smallint), min(q_smallint), max(q_smallint), first(q_smallint), last(q_smallint),
|
||||
sum(q_tinyint), avg(q_tinyint), min(q_tinyint), max(q_tinyint), first(q_tinyint), last(q_tinyint),
|
||||
sum(q_float), avg(q_float), min(q_float), max(q_float), first(q_float), last(q_float),
|
||||
sum(q_double), avg(q_double), min(q_double), max(q_double), first(q_double), last(q_double)
|
||||
from table_0 where ts >='1970-10-01 00:00:00' and ts <=now interval(1n) fill(NULL);'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkData(0,1,'None')
|
||||
#TD-5190
|
||||
sql = '''select sum(q_tinyint),stddev(q_float) from stable_1
|
||||
where ts >='1970-10-01 00:00:00' and ts <=now interval(1n) fill(NULL);'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkData(0,1,'None')
|
||||
|
||||
tdLog.info("========== operator=15(OP_MultiTableTimeInterval) ==========")
|
||||
sql = '''select avg(q_int) from stable_1 where ts<now interval(10m);'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
sql = '''select sum(q_int), avg(q_int), min(q_int), max(q_int), first(q_int), last(q_int),
|
||||
sum(q_bigint), avg(q_bigint), min(q_bigint), max(q_bigint), first(q_bigint), last(q_bigint),
|
||||
sum(q_smallint), avg(q_smallint), min(q_smallint), max(q_smallint), first(q_smallint), last(q_smallint),
|
||||
sum(q_tinyint), avg(q_tinyint), min(q_tinyint), max(q_tinyint), first(q_tinyint), last(q_tinyint),
|
||||
sum(q_float), avg(q_float), min(q_float), max(q_float), first(q_float), last(q_float),
|
||||
sum(q_double), avg(q_double), min(q_double), max(q_double), first(q_double), last(q_double)
|
||||
from table_1 where ts<now interval(10m);'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
sql = '''select sum(q_int), avg(q_int), min(q_int), max(q_int), first(q_int), last(q_int),
|
||||
sum(q_bigint), avg(q_bigint), min(q_bigint), max(q_bigint), first(q_bigint), last(q_bigint),
|
||||
sum(q_smallint), avg(q_smallint), min(q_smallint), max(q_smallint), first(q_smallint), last(q_smallint),
|
||||
sum(q_tinyint), avg(q_tinyint), min(q_tinyint), max(q_tinyint), first(q_tinyint), last(q_tinyint),
|
||||
sum(q_float), avg(q_float), min(q_float), max(q_float), first(q_float), last(q_float),
|
||||
sum(q_double), avg(q_double), min(q_double), max(q_double), first(q_double), last(q_double)
|
||||
from stable_1 where ts<now interval(10m);'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
sql = '''select sum(q_int), avg(q_int), min(q_int), max(q_int), first(q_int), last(q_int),
|
||||
sum(q_bigint), avg(q_bigint), min(q_bigint), max(q_bigint), first(q_bigint), last(q_bigint),
|
||||
sum(q_smallint), avg(q_smallint), min(q_smallint), max(q_smallint), first(q_smallint), last(q_smallint),
|
||||
sum(q_tinyint), avg(q_tinyint), min(q_tinyint), max(q_tinyint), first(q_tinyint), last(q_tinyint),
|
||||
sum(q_float), avg(q_float), min(q_float), max(q_float), first(q_float), last(q_float),
|
||||
sum(q_double), avg(q_double), min(q_double), max(q_double), first(q_double), last(q_double)
|
||||
from regular_table_1 where ts<now interval(10m);'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
|
||||
tdLog.info("========== operator=3(OP_TableSeqScan) ==========")
|
||||
tdLog.info("========== operator=6(OP_Aggregate) ==========")
|
||||
sql = '''select * from table_1,table_2
|
||||
where table_1.ts = table_2.ts;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(self.num)
|
||||
#TD-5206
|
||||
sql = '''select * from stable_1,stable_2
|
||||
where stable_1.t_nchar = stable_2.t_nchar and stable_1.ts = stable_2.ts;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(self.num)
|
||||
#TD-5139
|
||||
sql = '''select * from table_1,regular_table_1
|
||||
where table_1.ts = regular_table_1.ts;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(self.num)
|
||||
|
||||
tdLog.info("========== operator=5(OP_TableBlockInfoScan) ==========")
|
||||
sql = '''select _block_dist() from stable_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
sql = '''select _block_dist() from table_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
sql = '''select _block_dist() from regular_table_1;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(1)
|
||||
|
||||
tdLog.info("========== operator=17(OP_MultiwayMergeSort) ==========")
|
||||
tdLog.info("========== operator=18(OP_GlobalAggregate) ==========")
|
||||
tdLog.info("========== operator=19(OP_Filter) ==========")
|
||||
sql = '''select loc,sum(q_int) from stable_1
|
||||
group by loc having sum(q_int)>=0;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkData(0,0,'table_0')
|
||||
sql = '''select loc, sum(q_int), avg(q_int), min(q_int), max(q_int), first(q_int), last(q_int),
|
||||
sum(q_bigint), avg(q_bigint), min(q_bigint), max(q_bigint), first(q_bigint), last(q_bigint),
|
||||
sum(q_smallint), avg(q_smallint), min(q_smallint), max(q_smallint), first(q_smallint), last(q_smallint),
|
||||
sum(q_tinyint), avg(q_tinyint), min(q_tinyint), max(q_tinyint), first(q_tinyint), last(q_tinyint),
|
||||
sum(q_float), avg(q_float), min(q_float), max(q_float), first(q_float), last(q_float),
|
||||
sum(q_double), avg(q_double), min(q_double), max(q_double), first(q_double), last(q_double)
|
||||
from stable_1 group by loc having sum(q_int)>=0;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkData(0,0,'table_0')
|
||||
sql = '''select loc, sum(q_int), avg(q_int), min(q_int), max(q_int), first(q_int), last(q_int),
|
||||
sum(q_bigint), avg(q_bigint), min(q_bigint), max(q_bigint), first(q_bigint), last(q_bigint),
|
||||
sum(q_smallint), avg(q_smallint), min(q_smallint), max(q_smallint), first(q_smallint), last(q_smallint),
|
||||
sum(q_tinyint), avg(q_tinyint), min(q_tinyint), max(q_tinyint), first(q_tinyint), last(q_tinyint),
|
||||
sum(q_float), avg(q_float), min(q_float), max(q_float), first(q_float), last(q_float),
|
||||
sum(q_double), avg(q_double), min(q_double), max(q_double), first(q_double), last(q_double)
|
||||
from stable_1 group by loc having avg(q_int)>=0;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkData(0,0,'table_0')
|
||||
sql = '''select loc, sum(q_int), avg(q_int), min(q_int), max(q_int), first(q_int), last(q_int),
|
||||
sum(q_bigint), avg(q_bigint), min(q_bigint), max(q_bigint), first(q_bigint), last(q_bigint),
|
||||
sum(q_smallint), avg(q_smallint), min(q_smallint), max(q_smallint), first(q_smallint), last(q_smallint),
|
||||
sum(q_tinyint), avg(q_tinyint), min(q_tinyint), max(q_tinyint), first(q_tinyint), last(q_tinyint),
|
||||
sum(q_float), avg(q_float), min(q_float), max(q_float), first(q_float), last(q_float),
|
||||
sum(q_double), avg(q_double), min(q_double), max(q_double), first(q_double), last(q_double)
|
||||
from stable_1 group by loc having min(q_int)>=0;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkData(0,0,'table_0')
|
||||
sql = '''select loc, sum(q_int), avg(q_int), min(q_int), max(q_int), first(q_int), last(q_int),
|
||||
sum(q_bigint), avg(q_bigint), min(q_bigint), max(q_bigint), first(q_bigint), last(q_bigint),
|
||||
sum(q_smallint), avg(q_smallint), min(q_smallint), max(q_smallint), first(q_smallint), last(q_smallint),
|
||||
sum(q_tinyint), avg(q_tinyint), min(q_tinyint), max(q_tinyint), first(q_tinyint), last(q_tinyint),
|
||||
sum(q_float), avg(q_float), min(q_float), max(q_float), first(q_float), last(q_float),
|
||||
sum(q_double), avg(q_double), min(q_double), max(q_double), first(q_double), last(q_double)
|
||||
from stable_1 group by loc having max(q_int)>=0;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkData(0,0,'table_0')
|
||||
sql = '''select loc, sum(q_int), avg(q_int), min(q_int), max(q_int), first(q_int), last(q_int),
|
||||
sum(q_bigint), avg(q_bigint), min(q_bigint), max(q_bigint), first(q_bigint), last(q_bigint),
|
||||
sum(q_smallint), avg(q_smallint), min(q_smallint), max(q_smallint), first(q_smallint), last(q_smallint),
|
||||
sum(q_tinyint), avg(q_tinyint), min(q_tinyint), max(q_tinyint), first(q_tinyint), last(q_tinyint),
|
||||
sum(q_float), avg(q_float), min(q_float), max(q_float), first(q_float), last(q_float),
|
||||
sum(q_double), avg(q_double), min(q_double), max(q_double), first(q_double), last(q_double)
|
||||
from stable_1 group by loc having first(q_int)>=0;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkData(0,0,'table_0')
|
||||
sql = '''select loc, sum(q_int), avg(q_int), min(q_int), max(q_int), first(q_int), last(q_int),
|
||||
sum(q_bigint), avg(q_bigint), min(q_bigint), max(q_bigint), first(q_bigint), last(q_bigint),
|
||||
sum(q_smallint), avg(q_smallint), min(q_smallint), max(q_smallint), first(q_smallint), last(q_smallint),
|
||||
sum(q_tinyint), avg(q_tinyint), min(q_tinyint), max(q_tinyint), first(q_tinyint), last(q_tinyint),
|
||||
sum(q_float), avg(q_float), min(q_float), max(q_float), first(q_float), last(q_float),
|
||||
sum(q_double), avg(q_double), min(q_double), max(q_double), first(q_double), last(q_double)
|
||||
from stable_1 group by loc having last(q_int)>=0;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkData(0,0,'table_0')
|
||||
|
||||
tdLog.info("========== operator=21(OP_Join) ==========")
|
||||
sql = '''select t1.q_int,t2.q_int from
|
||||
(select ts,q_int from table_1) t1 , (select ts,q_int from table_2) t2
|
||||
where t2.ts = t1.ts;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(self.num)
|
||||
sql = '''select t1.*,t2.* from
|
||||
(select * from table_1) t1 , (select * from table_2) t2
|
||||
where t2.ts = t1.ts;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(self.num)
|
||||
sql = '''select t1.*,t2.* from
|
||||
(select * from regular_table_1) t1 , (select * from table_0) t2
|
||||
where t2.ts = t1.ts;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(self.num)
|
||||
sql = '''select t1.*,t2.* from
|
||||
(select * from stable_1) t1 , (select * from table_2) t2
|
||||
where t2.ts = t1.ts;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(self.num)
|
||||
sql = '''select t1.*,t2.* from
|
||||
(select * from regular_table_1) t1 , (select * from stable_1) t2
|
||||
where t2.ts = t1.ts;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(self.num)
|
||||
sql = '''select t1.*,t2.*,t3.* from
|
||||
(select * from regular_table_1) t1 , (select * from stable_1) t2, (select * from table_0) t3
|
||||
where t2.ts = t1.ts and t3.ts = t1.ts and t2.ts = t3.ts;'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(self.num)
|
||||
|
||||
tdLog.info("========== operator=22(OP_StateWindow) ==========")
|
||||
sql = '''select avg(q_int),sum(q_smallint) from table_1 state_window(q_int);'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(self.num)
|
||||
sql = '''select sum(q_int), avg(q_int), min(q_int), max(q_int), first(q_int), last(q_int),
|
||||
sum(q_bigint), avg(q_bigint), min(q_bigint), max(q_bigint), first(q_bigint), last(q_bigint),
|
||||
sum(q_smallint), avg(q_smallint), min(q_smallint), max(q_smallint), first(q_smallint), last(q_smallint),
|
||||
sum(q_tinyint), avg(q_tinyint), min(q_tinyint), max(q_tinyint), first(q_tinyint), last(q_tinyint),
|
||||
sum(q_float), avg(q_float), min(q_float), max(q_float), first(q_float), last(q_float),
|
||||
sum(q_double), avg(q_double), min(q_double), max(q_double), first(q_double), last(q_double)
|
||||
from table_1 state_window(q_bigint);'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(self.num)
|
||||
sql = '''select sum(q_int), avg(q_int), min(q_int), max(q_int), first(q_int), last(q_int),
|
||||
sum(q_bigint), avg(q_bigint), min(q_bigint), max(q_bigint), first(q_bigint), last(q_bigint),
|
||||
sum(q_smallint), avg(q_smallint), min(q_smallint), max(q_smallint), first(q_smallint), last(q_smallint),
|
||||
sum(q_tinyint), avg(q_tinyint), min(q_tinyint), max(q_tinyint), first(q_tinyint), last(q_tinyint),
|
||||
sum(q_float), avg(q_float), min(q_float), max(q_float), first(q_float), last(q_float),
|
||||
sum(q_double), avg(q_double), min(q_double), max(q_double), first(q_double), last(q_double)
|
||||
from regular_table_1 state_window(q_smallint);'''
|
||||
tdSql.query(sql)
|
||||
tdSql.checkRows(6*self.num)
|
||||
|
||||
endTime = time.time()
|
||||
print("total time %ds" % (endTime - startTime))
|
||||
|
||||
|
||||
def stop(self):
|
||||
tdSql.close()
|
||||
tdLog.success("%s successfully executed" % __file__)
|
||||
|
||||
|
||||
tdCases.addWindows(__file__, TDTestCase())
|
||||
tdCases.addLinux(__file__, TDTestCase())
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue