Merge branch '3.0' into 3.0test/jcy
This commit is contained in:
commit
01e670d3db
|
@ -54,14 +54,14 @@ Database changed.
|
|||
taos> show vgroups;
|
||||
vgId | tables | status | onlines | v1_dnode | v1_status | compacting |
|
||||
==========================================================================================
|
||||
14 | 38000 | ready | 1 | 1 | master | 0 |
|
||||
15 | 38000 | ready | 1 | 1 | master | 0 |
|
||||
16 | 38000 | ready | 1 | 1 | master | 0 |
|
||||
17 | 38000 | ready | 1 | 1 | master | 0 |
|
||||
18 | 37001 | ready | 1 | 1 | master | 0 |
|
||||
19 | 37000 | ready | 1 | 1 | master | 0 |
|
||||
20 | 37000 | ready | 1 | 1 | master | 0 |
|
||||
21 | 37000 | ready | 1 | 1 | master | 0 |
|
||||
14 | 38000 | ready | 1 | 1 | leader | 0 |
|
||||
15 | 38000 | ready | 1 | 1 | leader | 0 |
|
||||
16 | 38000 | ready | 1 | 1 | leader | 0 |
|
||||
17 | 38000 | ready | 1 | 1 | leader | 0 |
|
||||
18 | 37001 | ready | 1 | 1 | leader | 0 |
|
||||
19 | 37000 | ready | 1 | 1 | leader | 0 |
|
||||
20 | 37000 | ready | 1 | 1 | leader | 0 |
|
||||
21 | 37000 | ready | 1 | 1 | leader | 0 |
|
||||
Query OK, 8 row(s) in set (0.001154s)
|
||||
```
|
||||
|
||||
|
@ -161,14 +161,14 @@ First `show vgroups` is executed to show the vgroup distribution.
|
|||
taos> show vgroups;
|
||||
vgId | tables | status | onlines | v1_dnode | v1_status | compacting |
|
||||
==========================================================================================
|
||||
14 | 38000 | ready | 1 | 3 | master | 0 |
|
||||
15 | 38000 | ready | 1 | 3 | master | 0 |
|
||||
16 | 38000 | ready | 1 | 3 | master | 0 |
|
||||
17 | 38000 | ready | 1 | 3 | master | 0 |
|
||||
18 | 37001 | ready | 1 | 3 | master | 0 |
|
||||
19 | 37000 | ready | 1 | 1 | master | 0 |
|
||||
20 | 37000 | ready | 1 | 1 | master | 0 |
|
||||
21 | 37000 | ready | 1 | 1 | master | 0 |
|
||||
14 | 38000 | ready | 1 | 3 | leader | 0 |
|
||||
15 | 38000 | ready | 1 | 3 | leader | 0 |
|
||||
16 | 38000 | ready | 1 | 3 | leader | 0 |
|
||||
17 | 38000 | ready | 1 | 3 | leader | 0 |
|
||||
18 | 37001 | ready | 1 | 3 | leader | 0 |
|
||||
19 | 37000 | ready | 1 | 1 | leader | 0 |
|
||||
20 | 37000 | ready | 1 | 1 | leader | 0 |
|
||||
21 | 37000 | ready | 1 | 1 | leader | 0 |
|
||||
Query OK, 8 row(s) in set (0.001314s)
|
||||
```
|
||||
|
||||
|
@ -191,14 +191,14 @@ Query OK, 0 row(s) in set (0.000575s)
|
|||
taos> show vgroups;
|
||||
vgId | tables | status | onlines | v1_dnode | v1_status | v2_dnode | v2_status | compacting |
|
||||
=================================================================================================================
|
||||
14 | 38000 | ready | 1 | 3 | master | 0 | NULL | 0 |
|
||||
15 | 38000 | ready | 1 | 3 | master | 0 | NULL | 0 |
|
||||
16 | 38000 | ready | 1 | 3 | master | 0 | NULL | 0 |
|
||||
17 | 38000 | ready | 1 | 3 | master | 0 | NULL | 0 |
|
||||
18 | 37001 | ready | 2 | 1 | slave | 3 | master | 0 |
|
||||
19 | 37000 | ready | 1 | 1 | master | 0 | NULL | 0 |
|
||||
20 | 37000 | ready | 1 | 1 | master | 0 | NULL | 0 |
|
||||
21 | 37000 | ready | 1 | 1 | master | 0 | NULL | 0 |
|
||||
14 | 38000 | ready | 1 | 3 | leader | 0 | NULL | 0 |
|
||||
15 | 38000 | ready | 1 | 3 | leader | 0 | NULL | 0 |
|
||||
16 | 38000 | ready | 1 | 3 | leader | 0 | NULL | 0 |
|
||||
17 | 38000 | ready | 1 | 3 | leader | 0 | NULL | 0 |
|
||||
18 | 37001 | ready | 2 | 1 | follower | 3 | leader | 0 |
|
||||
19 | 37000 | ready | 1 | 1 | leader | 0 | NULL | 0 |
|
||||
20 | 37000 | ready | 1 | 1 | leader | 0 | NULL | 0 |
|
||||
21 | 37000 | ready | 1 | 1 | leader | 0 | NULL | 0 |
|
||||
Query OK, 8 row(s) in set (0.001242s)
|
||||
```
|
||||
|
||||
|
@ -207,7 +207,7 @@ It can be seen from above output that vgId 18 has been moved from dnode 3 to dno
|
|||
:::note
|
||||
|
||||
- Manual load balancing can only be performed when the automatic load balancing is disabled, i.e. `balance` is set to 0.
|
||||
- Only a vnode in normal state, i.e. master or slave, can be moved. vnode can't be moved when its in status offline, unsynced or syncing.
|
||||
- Only a vnode in normal state, i.e. leader or follower, can be moved. vnode can't be moved when its in status offline, unsynced or syncing.
|
||||
- Before moving a vnode, it's necessary to make sure the target dnode has enough resources: CPU, memory and disk.
|
||||
|
||||
:::
|
||||
|
|
|
@ -27,7 +27,7 @@ There may be multiple dnodes in a cluster, but only one mnode can be started in
|
|||
SHOW MNODES;
|
||||
```
|
||||
|
||||
The end point and role/status (master, slave, unsynced, or offline) of all mnodes can be shown by the above command. When the first dnode is started in a cluster, there must be one mnode in this dnode. Without at least one mnode, the cluster cannot work. If `numOfMNodes` is configured to 2, another mnode will be started when the second dnode is launched.
|
||||
The end point and role/status (leader, follower, unsynced, or offline) of all mnodes can be shown by the above command. When the first dnode is started in a cluster, there must be one mnode in this dnode. Without at least one mnode, the cluster cannot work. If `numOfMNodes` is configured to 2, another mnode will be started when the second dnode is launched.
|
||||
|
||||
For the high availability of mnode, `numOfMnodes` needs to be configured to 2 or a higher value. Because the data consistency between mnodes must be guaranteed, the replica confirmation parameter `quorum` is set to 2 automatically if `numOfMNodes` is set to 2 or higher.
|
||||
|
||||
|
@ -58,13 +58,13 @@ When a dnode is offline, it can be detected by the TDengine cluster. There are t
|
|||
- If the dnode has been offline over the threshold configured in `offlineThreshold` in `taos.cfg`, the dnode will be removed from the cluster automatically. A system alert will be generated and automatic load balancing will be triggered if `balance` is set to 1. When the removed dnode is restarted and becomes online, it will not join the cluster automatically. The system administrator has to manually join the dnode to the cluster.
|
||||
|
||||
:::note
|
||||
If all the vnodes in a vgroup (or mnodes in mnode group) are in offline or unsynced status, the master node can only be voted on, after all the vnodes or mnodes in the group become online and can exchange status. Following this, the vgroup (or mnode group) is able to provide service.
|
||||
If all the vnodes in a vgroup (or mnodes in mnode group) are in offline or unsynced status, the leader node can only be voted on, after all the vnodes or mnodes in the group become online and can exchange status. Following this, the vgroup (or mnode group) is able to provide service.
|
||||
|
||||
:::
|
||||
|
||||
## Arbitrator
|
||||
|
||||
The "arbitrator" component is used to address the special case when the number of replicas is set to an even number like 2,4 etc. If half of the vnodes in a vgroup don't work, it is impossible to vote and select a master node. This situation also applies to mnodes if the number of mnodes is set to an even number like 2,4 etc.
|
||||
The "arbitrator" component is used to address the special case when the number of replicas is set to an even number like 2,4 etc. If half of the vnodes in a vgroup don't work, it is impossible to vote and select a leader node. This situation also applies to mnodes if the number of mnodes is set to an even number like 2,4 etc.
|
||||
|
||||
To resolve this problem, a new arbitrator component named `tarbitrator`, an abbreviation of TDengine Arbitrator, was introduced. The `tarbitrator` simulates a vnode or mnode but it's only responsible for network communication and doesn't handle any actual data access. As long as more than half of the vnode or mnode, including Arbitrator, are available the vnode group or mnode group can provide data insertion or query services normally.
|
||||
|
||||
|
|
|
@ -211,7 +211,7 @@
|
|||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Master MNode",
|
||||
"title": "Leader MNode",
|
||||
"transformations": [
|
||||
{
|
||||
"id": "filterByValue",
|
||||
|
@ -221,7 +221,7 @@
|
|||
"config": {
|
||||
"id": "regex",
|
||||
"options": {
|
||||
"value": "master"
|
||||
"value": "leader"
|
||||
}
|
||||
},
|
||||
"fieldName": "role"
|
||||
|
@ -300,7 +300,7 @@
|
|||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Master MNode Create Time",
|
||||
"title": "Leader MNode Create Time",
|
||||
"transformations": [
|
||||
{
|
||||
"id": "filterByValue",
|
||||
|
@ -310,7 +310,7 @@
|
|||
"config": {
|
||||
"id": "regex",
|
||||
"options": {
|
||||
"value": "master"
|
||||
"value": "leader"
|
||||
}
|
||||
},
|
||||
"fieldName": "role"
|
||||
|
|
|
@ -153,7 +153,7 @@
|
|||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Master MNode",
|
||||
"title": "Leader MNode",
|
||||
"transformations": [
|
||||
{
|
||||
"id": "filterByValue",
|
||||
|
@ -163,7 +163,7 @@
|
|||
"config": {
|
||||
"id": "regex",
|
||||
"options": {
|
||||
"value": "master"
|
||||
"value": "leader"
|
||||
}
|
||||
},
|
||||
"fieldName": "role"
|
||||
|
@ -246,7 +246,7 @@
|
|||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Master MNode Create Time",
|
||||
"title": "Leader MNode Create Time",
|
||||
"transformations": [
|
||||
{
|
||||
"id": "filterByValue",
|
||||
|
@ -256,7 +256,7 @@
|
|||
"config": {
|
||||
"id": "regex",
|
||||
"options": {
|
||||
"value": "master"
|
||||
"value": "leader"
|
||||
}
|
||||
},
|
||||
"fieldName": "role"
|
||||
|
|
|
@ -274,8 +274,8 @@ Details of the metrics are as follows.
|
|||
This section contains the current information and status of the cluster, the alert information is also here (from left to right, top to bottom).
|
||||
|
||||
- **First EP**: the `firstEp` setting in the current TDengine cluster.
|
||||
- **Version**: TDengine server version (master mnode).
|
||||
- **Master Uptime**: The time elapsed since the current Master MNode was elected as Master.
|
||||
- **Version**: TDengine server version (leader mnode).
|
||||
- **Leader Uptime**: The time elapsed since the current Leader MNode was elected as Leader.
|
||||
- **Expire Time** - Enterprise version expiration time.
|
||||
- **Used Measuring Points** - The number of measuring points used by the Enterprise Edition.
|
||||
- **Databases** - The number of databases.
|
||||
|
@ -333,7 +333,7 @@ Data node resource usage display with repeated multiple rows for the variable `$
|
|||
2. **Has MNodes?**: whether the current dnode is a mnode.
|
||||
3. **CPU Cores**: the number of CPU cores.
|
||||
4. **VNodes Number**: the number of VNodes in the current dnode.
|
||||
5. **VNodes Masters**: the number of vnodes in the master role.
|
||||
5. **VNodes Masters**: the number of vnodes in the leader role.
|
||||
6. **Current CPU Usage of taosd**: CPU usage rate of taosd processes.
|
||||
7. **Current Memory Usage of taosd**: memory usage of taosd processes.
|
||||
8. **Disk Used**: The total disk usage percentage of the taosd data directory.
|
||||
|
|
|
@ -22,9 +22,9 @@ A complete TDengine system runs on one or more physical nodes. Logically, it inc
|
|||
|
||||
**Virtual node (vnode)**: To better support data sharding, load balancing and prevent data from overheating or skewing, data nodes are virtualized into multiple virtual nodes (vnode, V2, V3, V4, etc. in the figure). Each vnode is a relatively independent work unit, which is the basic unit of time-series data storage and has independent running threads, memory space and persistent storage path. A vnode contains a certain number of tables (data collection points). When a new table is created, the system checks whether a new vnode needs to be created. The number of vnodes that can be created on a data node depends on the capacity of the hardware of the physical node where the data node is located. A vnode belongs to only one DB, but a DB can have multiple vnodes. In addition to the stored time-series data, a vnode also stores the schema and tag values of the included tables. A virtual node is uniquely identified in the system by the EP of the data node and the VGroup ID to which it belongs and is created and managed by the management node.
|
||||
|
||||
**Management node (mnode)**: A virtual logical unit responsible for monitoring and maintaining the running status of all data nodes and load balancing among nodes (M in the figure). At the same time, the management node is also responsible for the storage and management of metadata (including users, databases, tables, static tags, etc.), so it is also called Meta Node. Multiple (up to 5) mnodes can be configured in a TDengine cluster, and they are automatically constructed into a virtual management node group (M0, M1, M2 in the figure). The master/slave mechanism is adopted for the mnode group and the data synchronization is carried out in a strongly consistent way. Any data update operation can only be executed on the master. The creation of mnode cluster is completed automatically by the system without manual intervention. There is at most one mnode on each dnode, which is uniquely identified by the EP of the data node to which it belongs. Each dnode automatically obtains the EP of the dnode where all mnodes in the whole cluster are located, through internal messaging interaction.
|
||||
**Management node (mnode)**: A virtual logical unit responsible for monitoring and maintaining the running status of all data nodes and load balancing among nodes (M in the figure). At the same time, the management node is also responsible for the storage and management of metadata (including users, databases, tables, static tags, etc.), so it is also called Meta Node. Multiple (up to 5) mnodes can be configured in a TDengine cluster, and they are automatically constructed into a virtual management node group (M0, M1, M2 in the figure). The leader/follower mechanism is adopted for the mnode group and the data synchronization is carried out in a strongly consistent way. Any data update operation can only be executed on the leader. The creation of mnode cluster is completed automatically by the system without manual intervention. There is at most one mnode on each dnode, which is uniquely identified by the EP of the data node to which it belongs. Each dnode automatically obtains the EP of the dnode where all mnodes in the whole cluster are located, through internal messaging interaction.
|
||||
|
||||
**Virtual node group (VGroup)**: Vnodes on different data nodes can form a virtual node group to ensure the high availability of the system. The virtual node group is managed in a master/slave mechanism. Write operations can only be performed on the master vnode, and then replicated to slave vnodes, 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 a DB, and the default is 1. Using the multi-replication feature of TDengine, the same high data reliability can be achieved without the need for expensive storage devices such as disk arrays. Virtual node groups are created and managed by the management node, and the management node assigns a system unique ID, aka VGroup ID. If two virtual nodes have the same vnode group ID, it 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.
|
||||
**Virtual node group (VGroup)**: Vnodes on different data nodes can form a virtual node group to ensure the high availability of the system. The virtual node group is managed in a leader/follower mechanism. Write operations can only be performed on the leader vnode, and then replicated to follower vnodes, 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 a DB, and the default is 1. Using the multi-replication feature of TDengine, the same high data reliability can be achieved without the need for expensive storage devices such as disk arrays. Virtual node groups are created and managed by the management node, and the management node assigns a system unique ID, aka VGroup ID. If two virtual nodes have the same vnode group ID, it 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. It is responsible for dealing with the interaction between application and cluster, and provides the native interface for the C/C++ language. It is also embedded in the 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 needs 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.
|
||||
|
||||
|
@ -62,13 +62,13 @@ To explain the relationship between vnode, mnode, TAOSC and application and thei
|
|||
1. Application initiates a request to insert data through JDBC, ODBC, or other APIs.
|
||||
2. TAOSC checks the cache to see if meta data exists for the table. If it does, it goes straight to Step 4. If not, TAOSC sends a get meta-data request to mnode.
|
||||
3. Mnode returns the meta-data of the table to TAOSC. Meta-data contains the schema of the table, and also the vgroup information to which the table belongs (the vnode ID and the End Point of the dnode where the table belongs. If the number of replicas is N, there will be N groups of End Points). If TAOSC does not receive a response from the mnode for a long time, and there are multiple mnodes, TAOSC will send a request to the next mnode.
|
||||
4. TAOSC initiates an insert request to master vnode.
|
||||
4. TAOSC initiates an insert request to leader vnode.
|
||||
5. After vnode inserts the data, it gives a reply to TAOSC, indicating that the insertion is successful. If TAOSC doesn't get a response from vnode for a long time, TAOSC will treat this node as offline. In this case, if there are multiple replicas of the inserted database, TAOSC will issue an insert request to the next vnode in vgroup.
|
||||
6. TAOSC notifies APP that writing is successful.
|
||||
|
||||
For Step 2 and 3, when TAOSC starts, it does not know the End Point of mnode, so it will directly initiate a request to the configured serving End Point of the cluster. If the dnode that receives the request does not have a mnode configured, it will reply with the mnode EP list, so that TAOSC will re-issue a request to obtain meta-data to the EP of another mnode.
|
||||
|
||||
For Step 4 and 5, without caching, TAOSC can't recognize the master in the virtual node group, so assumes that the first vnode is the master and sends a request to it. If this vnode is not the master, it will reply to the actual master as a new target to which TAOSC shall send a request. Once a response of successful insertion is obtained, TAOSC will cache the information of master node.
|
||||
For Step 4 and 5, without caching, TAOSC can't recognize the leader in the virtual node group, so assumes that the first vnode is the leader and sends a request to it. If this vnode is not the leader, it will reply to the actual leader as a new target to which TAOSC shall send a request. Once a response of successful insertion is obtained, TAOSC will cache the information of leader node.
|
||||
|
||||
The above describes the process of inserting data. The processes of querying and computing are the same. TAOSC encapsulates and hides all these complicated processes, and it is transparent to applications.
|
||||
|
||||
|
@ -119,65 +119,65 @@ The load balancing process does not require any manual intervention, and it is t
|
|||
|
||||
## Data Writing and Replication Process
|
||||
|
||||
If a database has N replicas, a virtual node group has N virtual nodes. But only one is the Master and all others are slaves. When the application writes a new record to system, only the Master vnode can accept the writing request. If a slave vnode receives a writing request, the system will notifies TAOSC to redirect.
|
||||
If a database has N replicas, a virtual node group has N virtual nodes. But only one is the Leader and all others are slaves. When the application writes a new record to system, only the Leader vnode can accept the writing request. If a follower vnode receives a writing request, the system will notifies TAOSC to redirect.
|
||||
|
||||
### Master vnode Writing Process
|
||||
### Leader vnode Writing Process
|
||||
|
||||
Master Vnode uses a writing process as follows:
|
||||
Leader Vnode uses a writing process as follows:
|
||||
|
||||

|
||||
<center> Figure 3: TDengine Master writing process </center>
|
||||

|
||||
<center> Figure 3: TDengine Leader writing process </center>
|
||||
|
||||
1. Master vnode receives the application data insertion request, verifies, and moves to next step;
|
||||
1. Leader vnode receives the application data insertion request, verifies, and moves to next step;
|
||||
2. If the system configuration parameter `“walLevel”` is greater than 0, vnode will write the original request packet into database log file WAL. If walLevel is set to 2 and fsync is set to 0, TDengine will make WAL data written immediately to ensure that even system goes down, all data can be recovered from database log file;
|
||||
3. If there are multiple replicas, vnode will forward data packet to slave vnodes in the same virtual node group, and the forwarded packet has a version number with data;
|
||||
3. If there are multiple replicas, vnode will forward data packet to follower vnodes in the same virtual node group, and the forwarded packet has a version number with data;
|
||||
4. Write into memory and add the record to “skip list”;
|
||||
5. Master vnode returns a confirmation message to the application, indicating a successful write.
|
||||
5. Leader vnode returns a confirmation message to the application, indicating a successful write.
|
||||
6. If any of Step 2, 3 or 4 fails, the error will directly return to the application.
|
||||
|
||||
### Slave vnode Writing Process
|
||||
### Follower vnode Writing Process
|
||||
|
||||
For a slave vnode, the write process as follows:
|
||||
For a follower vnode, the write process as follows:
|
||||
|
||||

|
||||
<center> Figure 4: TDengine Slave Writing Process </center>
|
||||

|
||||
<center> Figure 4: TDengine Follower Writing Process </center>
|
||||
|
||||
1. Slave vnode receives a data insertion request forwarded by Master vnode;
|
||||
1. Follower vnode receives a data insertion request forwarded by Leader vnode;
|
||||
2. If the system configuration parameter `“walLevel”` is greater than 0, vnode will write the original request packet into database log file WAL. If walLevel is set to 2 and fsync is set to 0, TDengine will make WAL data written immediately to ensure that even system goes down, all data can be recovered from database log file;
|
||||
3. Write into memory and add the record to “skip list”.
|
||||
|
||||
Compared with Master vnode, slave vnode has no forwarding or reply confirmation step, means two steps less. But writing into memory and WAL is exactly the same.
|
||||
Compared with Leader vnode, follower vnode has no forwarding or reply confirmation step, means two steps less. But writing into memory and WAL is exactly the same.
|
||||
|
||||
### Remote Disaster Recovery and IDC (Internet Data Center) Migration
|
||||
|
||||
As discussed above, TDengine writes using Master and Slave processes. TDengine adopts asynchronous replication for data synchronization. This method can greatly improve write performance, with no obvious impact from network delay. By configuring IDC and rack number for each physical node, it can be ensured that for a virtual node group, virtual nodes are composed of physical nodes from different IDC and different racks, thus implementing remote disaster recovery without other tools.
|
||||
As discussed above, TDengine writes using Leader and Follower processes. TDengine adopts asynchronous replication for data synchronization. This method can greatly improve write performance, with no obvious impact from network delay. By configuring IDC and rack number for each physical node, it can be ensured that for a virtual node group, virtual nodes are composed of physical nodes from different IDC and different racks, thus implementing remote disaster recovery without other tools.
|
||||
|
||||
On the other hand, TDengine supports dynamic modification of the replica number. Once the number of replicas increases, the newly added virtual nodes will immediately enter the data synchronization process. After synchronization is complete, added virtual nodes can provide services. In the synchronization process, master and other synchronized virtual nodes keep serving. With this feature, TDengine can provide IDC migration without service interruption. It is only necessary to add new physical nodes to the existing IDC cluster, and then remove old physical nodes after the data synchronization is completed.
|
||||
On the other hand, TDengine supports dynamic modification of the replica number. Once the number of replicas increases, the newly added virtual nodes will immediately enter the data synchronization process. After synchronization is complete, added virtual nodes can provide services. In the synchronization process, leader and other synchronized virtual nodes keep serving. With this feature, TDengine can provide IDC migration without service interruption. It is only necessary to add new physical nodes to the existing IDC cluster, and then remove old physical nodes after the data synchronization is completed.
|
||||
|
||||
However, the asynchronous replication has a very low probability scenario where data may be lost. The specific scenario is as follows:
|
||||
|
||||
1. Master vnode has finished its 5-step operations, confirmed the success of writing to APP, and then goes down;
|
||||
2. Slave vnode receives the write request, then processing fails before writing to the log in Step 2;
|
||||
3. Slave vnode will become the new master, thus losing one record.
|
||||
1. Leader vnode has finished its 5-step operations, confirmed the success of writing to APP, and then goes down;
|
||||
2. Follower vnode receives the write request, then processing fails before writing to the log in Step 2;
|
||||
3. Follower vnode will become the new leader, thus losing one record.
|
||||
|
||||
In theory, for asynchronous replication, there is no guarantee to prevent data loss. However, this is an extremely low probability scenario as described above.
|
||||
|
||||
Note: Remote disaster recovery and no-downtime IDC migration are only supported by Enterprise Edition. **Hint: This function is not available yet**
|
||||
|
||||
### Master/slave Selection
|
||||
### Leader/follower Selection
|
||||
|
||||
Vnode maintains a version number. When memory data is persisted, the version number will also be persisted. For each data update operation, whether it is time-series data or metadata, this version number will be increased by one.
|
||||
|
||||
When a vnode starts, the roles (master, slave) are uncertain, and the data is in an unsynchronized state. It’s necessary to establish TCP connections with other nodes in the virtual node group and exchange status, including version and its own roles. Through the exchange, the system implements a master-selection process. The rules are as follows:
|
||||
When a vnode starts, the roles (leader, follower) are uncertain, and the data is in an unsynchronized state. It’s necessary to establish TCP connections with other nodes in the virtual node group and exchange status, including version and its own roles. Through the exchange, the system implements a leader-selection process. The rules are as follows:
|
||||
|
||||
1. If there’s only one replica, it’s always master
|
||||
2. When all replicas are online, the one with latest version is master
|
||||
3. Over half of online nodes are virtual nodes, and some virtual node is slave, it will automatically become master
|
||||
4. For 2 and 3, if multiple virtual nodes meet the requirement, the first vnode in virtual node group list will be selected as master.
|
||||
1. If there’s only one replica, it’s always leader
|
||||
2. When all replicas are online, the one with latest version is leader
|
||||
3. Over half of online nodes are virtual nodes, and some virtual node is follower, it will automatically become leader
|
||||
4. For 2 and 3, if multiple virtual nodes meet the requirement, the first vnode in virtual node group list will be selected as leader.
|
||||
|
||||
### Synchronous Replication
|
||||
|
||||
For scenarios with strong data consistency requirements, asynchronous data replication is not applicable, because there is a small probability of data loss. So, TDengine provides a synchronous replication mechanism for users. When creating a database, in addition to specifying the number of replicas, user also needs to specify a new parameter “quorum”. If quorum is greater than one, it means that every time the Master forwards a message to the replica, it needs to wait for “quorum-1” reply confirms before informing the application that data has been successfully written in slave. If “quorum-1” reply confirms are not received within a certain period of time, the master vnode will return an error to the application.
|
||||
For scenarios with strong data consistency requirements, asynchronous data replication is not applicable, because there is a small probability of data loss. So, TDengine provides a synchronous replication mechanism for users. When creating a database, in addition to specifying the number of replicas, user also needs to specify a new parameter “quorum”. If quorum is greater than one, it means that every time the Leader forwards a message to the replica, it needs to wait for “quorum-1” reply confirms before informing the application that data has been successfully written in follower. If “quorum-1” reply confirms are not received within a certain period of time, the leader vnode will return an error to the application.
|
||||
|
||||
With synchronous replication, performance of system will decrease and latency will increase. Because metadata needs strong consistency, the default for data synchronization between mnodes is synchronous replication.
|
||||
|
||||
|
|
|
@ -190,6 +190,7 @@ bool fmIsForbidWindowFunc(int32_t funcId);
|
|||
bool fmIsForbidGroupByFunc(int32_t funcId);
|
||||
bool fmIsIntervalInterpoFunc(int32_t funcId);
|
||||
bool fmIsInterpFunc(int32_t funcId);
|
||||
bool fmIsLastRowFunc(int32_t funcId);
|
||||
|
||||
int32_t fmGetDistMethod(const SFunctionNode* pFunc, SFunctionNode** pPartialFunc, SFunctionNode** pMergeFunc);
|
||||
|
||||
|
|
|
@ -59,10 +59,10 @@ extern "C" {
|
|||
for (SListCell* cell = (NULL != (list) ? (list)->pHead : NULL); \
|
||||
(NULL != cell ? (node = &(cell->pNode), true) : (node = NULL, false)); cell = cell->pNext)
|
||||
|
||||
#define DESTORY_LIST(list) \
|
||||
do { \
|
||||
nodesDestroyList((list)); \
|
||||
(list) = NULL; \
|
||||
#define NODES_DESTORY_LIST(list) \
|
||||
do { \
|
||||
nodesDestroyList((list)); \
|
||||
(list) = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define NODES_CLEAR_LIST(list) \
|
||||
|
@ -219,6 +219,7 @@ typedef enum ENodeType {
|
|||
QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN,
|
||||
QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN,
|
||||
QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN,
|
||||
QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN,
|
||||
QUERY_NODE_PHYSICAL_PLAN_PROJECT,
|
||||
QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN,
|
||||
QUERY_NODE_PHYSICAL_PLAN_HASH_AGG,
|
||||
|
@ -227,6 +228,7 @@ typedef enum ENodeType {
|
|||
QUERY_NODE_PHYSICAL_PLAN_SORT,
|
||||
QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL,
|
||||
QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL,
|
||||
QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL,
|
||||
QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL,
|
||||
QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL,
|
||||
QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL,
|
||||
|
|
|
@ -40,7 +40,8 @@ typedef enum EScanType {
|
|||
SCAN_TYPE_SYSTEM_TABLE,
|
||||
SCAN_TYPE_STREAM,
|
||||
SCAN_TYPE_TABLE_MERGE,
|
||||
SCAN_TYPE_BLOCK_INFO
|
||||
SCAN_TYPE_BLOCK_INFO,
|
||||
SCAN_TYPE_LAST_ROW
|
||||
} EScanType;
|
||||
|
||||
typedef struct SScanLogicNode {
|
||||
|
@ -260,6 +261,7 @@ typedef struct SScanPhysiNode {
|
|||
|
||||
typedef SScanPhysiNode STagScanPhysiNode;
|
||||
typedef SScanPhysiNode SBlockDistScanPhysiNode;
|
||||
typedef SScanPhysiNode SLastRowScanPhysiNode;
|
||||
|
||||
typedef struct SSystemTableScanPhysiNode {
|
||||
SScanPhysiNode scan;
|
||||
|
@ -375,7 +377,8 @@ typedef struct SIntervalPhysiNode {
|
|||
int8_t slidingUnit;
|
||||
} SIntervalPhysiNode;
|
||||
|
||||
typedef SIntervalPhysiNode SMergeIntervalPhysiNode;
|
||||
typedef SIntervalPhysiNode SMergeIntervalPhysiNode;
|
||||
typedef SIntervalPhysiNode SMergeAlignedIntervalPhysiNode;
|
||||
typedef SIntervalPhysiNode SStreamIntervalPhysiNode;
|
||||
typedef SIntervalPhysiNode SStreamFinalIntervalPhysiNode;
|
||||
typedef SIntervalPhysiNode SStreamSemiIntervalPhysiNode;
|
||||
|
|
|
@ -258,6 +258,7 @@ typedef struct SSelectStmt {
|
|||
bool hasUniqueFunc;
|
||||
bool hasTailFunc;
|
||||
bool hasInterpFunc;
|
||||
bool hasLastRowFunc;
|
||||
} SSelectStmt;
|
||||
|
||||
typedef enum ESetOperatorType { SET_OP_TYPE_UNION_ALL = 1, SET_OP_TYPE_UNION } ESetOperatorType;
|
||||
|
|
|
@ -263,6 +263,7 @@ int32_t colDataMergeCol(SColumnInfoData* pColumnInfoData, uint32_t numOfRow1, in
|
|||
pColumnInfoData->varmeta.length = len + oldLen;
|
||||
} else {
|
||||
if (finalNumOfRows > *capacity) {
|
||||
ASSERT(finalNumOfRows*pColumnInfoData->info.bytes);
|
||||
char* tmp = taosMemoryRealloc(pColumnInfoData->pData, finalNumOfRows * pColumnInfoData->info.bytes);
|
||||
if (tmp == NULL) {
|
||||
return TSDB_CODE_VND_OUT_OF_MEMORY;
|
||||
|
@ -1126,6 +1127,7 @@ void blockDataCleanup(SSDataBlock* pDataBlock) {
|
|||
}
|
||||
|
||||
int32_t colInfoDataEnsureCapacity(SColumnInfoData* pColumn, size_t existRows, uint32_t numOfRows) {
|
||||
ASSERT(numOfRows);
|
||||
if (0 == numOfRows || numOfRows <= existRows) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
@ -1178,6 +1180,8 @@ void colInfoDataCleanup(SColumnInfoData* pColumn, uint32_t numOfRows) {
|
|||
|
||||
int32_t blockDataEnsureCapacity(SSDataBlock* pDataBlock, uint32_t numOfRows) {
|
||||
int32_t code = 0;
|
||||
ASSERT(numOfRows > 0);
|
||||
|
||||
if (numOfRows == 0) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -28,10 +28,10 @@ static inline void vmSendRsp(SRpcMsg *pMsg, int32_t code) {
|
|||
}
|
||||
|
||||
static void vmProcessMgmtQueue(SQueueInfo *pInfo, SRpcMsg *pMsg) {
|
||||
SVnodeMgmt *pMgmt = pInfo->ahandle;
|
||||
int32_t code = -1;
|
||||
SVnodeMgmt *pMgmt = pInfo->ahandle;
|
||||
int32_t code = -1;
|
||||
const STraceId *trace = &pMsg->info.traceId;
|
||||
|
||||
STraceId *trace = &pMsg->info.traceId;
|
||||
dGTrace("msg:%p, get from vnode-mgmt queue", pMsg);
|
||||
switch (pMsg->msgType) {
|
||||
case TDMT_MON_VM_INFO:
|
||||
|
@ -48,50 +48,52 @@ static void vmProcessMgmtQueue(SQueueInfo *pInfo, SRpcMsg *pMsg) {
|
|||
break;
|
||||
default:
|
||||
terrno = TSDB_CODE_MSG_NOT_PROCESSED;
|
||||
dError("msg:%p, not processed in vnode-mgmt queue", pMsg);
|
||||
dGError("msg:%p, not processed in vnode-mgmt queue", pMsg);
|
||||
}
|
||||
|
||||
if (IsReq(pMsg)) {
|
||||
if (code != 0) {
|
||||
if (terrno != 0) code = terrno;
|
||||
dError("msg:%p, failed to process since %s", pMsg, terrstr());
|
||||
dGError("msg:%p, failed to process since %s", pMsg, terrstr());
|
||||
}
|
||||
vmSendRsp(pMsg, code);
|
||||
}
|
||||
|
||||
dTrace("msg:%p, is freed, code:0x%x", pMsg, code);
|
||||
dGTrace("msg:%p, is freed, code:0x%x", pMsg, code);
|
||||
rpcFreeCont(pMsg->pCont);
|
||||
taosFreeQitem(pMsg);
|
||||
}
|
||||
|
||||
static void vmProcessQueryQueue(SQueueInfo *pInfo, SRpcMsg *pMsg) {
|
||||
SVnodeObj *pVnode = pInfo->ahandle;
|
||||
SVnodeObj *pVnode = pInfo->ahandle;
|
||||
const STraceId *trace = &pMsg->info.traceId;
|
||||
|
||||
dTrace("vgId:%d, msg:%p get from vnode-query queue", pVnode->vgId, pMsg);
|
||||
dGTrace("vgId:%d, msg:%p get from vnode-query queue", pVnode->vgId, pMsg);
|
||||
int32_t code = vnodeProcessQueryMsg(pVnode->pImpl, pMsg);
|
||||
if (code != 0) {
|
||||
if (terrno != 0) code = terrno;
|
||||
dError("vgId:%d, msg:%p failed to query since %s", pVnode->vgId, pMsg, terrstr());
|
||||
dGError("vgId:%d, msg:%p failed to query since %s", pVnode->vgId, pMsg, terrstr());
|
||||
vmSendRsp(pMsg, code);
|
||||
}
|
||||
|
||||
dTrace("vgId:%d, msg:%p is freed, code:0x%x", pVnode->vgId, pMsg, code);
|
||||
dGTrace("vgId:%d, msg:%p is freed, code:0x%x", pVnode->vgId, pMsg, code);
|
||||
rpcFreeCont(pMsg->pCont);
|
||||
taosFreeQitem(pMsg);
|
||||
}
|
||||
|
||||
static void vmProcessFetchQueue(SQueueInfo *pInfo, SRpcMsg *pMsg) {
|
||||
SVnodeObj *pVnode = pInfo->ahandle;
|
||||
SVnodeObj *pVnode = pInfo->ahandle;
|
||||
const STraceId *trace = &pMsg->info.traceId;
|
||||
|
||||
dTrace("vgId:%d, msg:%p get from vnode-fetch queue", pVnode->vgId, pMsg);
|
||||
dGTrace("vgId:%d, msg:%p get from vnode-fetch queue", pVnode->vgId, pMsg);
|
||||
int32_t code = vnodeProcessFetchMsg(pVnode->pImpl, pMsg, pInfo);
|
||||
if (code != 0) {
|
||||
if (terrno != 0) code = terrno;
|
||||
dError("vgId:%d, msg:%p failed to fetch since %s", pVnode->vgId, pMsg, terrstr());
|
||||
dGError("vgId:%d, msg:%p failed to fetch since %s", pVnode->vgId, pMsg, terrstr());
|
||||
vmSendRsp(pMsg, code);
|
||||
}
|
||||
|
||||
dTrace("vgId:%d, msg:%p is freed, code:0x%x", pVnode->vgId, pMsg, code);
|
||||
dGTrace("vgId:%d, msg:%p is freed, code:0x%x", pVnode->vgId, pMsg, code);
|
||||
rpcFreeCont(pMsg->pCont);
|
||||
taosFreeQitem(pMsg);
|
||||
}
|
||||
|
@ -102,16 +104,17 @@ static void vmProcessSyncQueue(SQueueInfo *pInfo, STaosQall *qall, int32_t numOf
|
|||
|
||||
for (int32_t i = 0; i < numOfMsgs; ++i) {
|
||||
if (taosGetQitem(qall, (void **)&pMsg) == 0) continue;
|
||||
dTrace("vgId:%d, msg:%p get from vnode-sync queue", pVnode->vgId, pMsg);
|
||||
const STraceId *trace = &pMsg->info.traceId;
|
||||
dGTrace("vgId:%d, msg:%p get from vnode-sync queue", pVnode->vgId, pMsg);
|
||||
|
||||
int32_t code = vnodeProcessSyncReq(pVnode->pImpl, pMsg, NULL);
|
||||
if (code != 0) {
|
||||
if (terrno != 0) code = terrno;
|
||||
dError("vgId:%d, msg:%p failed to sync since %s", pVnode->vgId, pMsg, terrstr());
|
||||
dGError("vgId:%d, msg:%p failed to sync since %s", pVnode->vgId, pMsg, terrstr());
|
||||
vmSendRsp(pMsg, code);
|
||||
}
|
||||
|
||||
dTrace("vgId:%d, msg:%p is freed, code:0x%x", pVnode->vgId, pMsg, code);
|
||||
dGTrace("vgId:%d, msg:%p is freed, code:0x%x", pVnode->vgId, pMsg, code);
|
||||
rpcFreeCont(pMsg->pCont);
|
||||
taosFreeQitem(pMsg);
|
||||
}
|
||||
|
@ -123,55 +126,57 @@ static void vmProcessMergeQueue(SQueueInfo *pInfo, STaosQall *qall, int32_t numO
|
|||
|
||||
for (int32_t i = 0; i < numOfMsgs; ++i) {
|
||||
if (taosGetQitem(qall, (void **)&pMsg) == 0) continue;
|
||||
dTrace("vgId:%d, msg:%p get from vnode-merge queue", pVnode->vgId, pMsg);
|
||||
const STraceId *trace = &pMsg->info.traceId;
|
||||
dGTrace("vgId:%d, msg:%p get from vnode-merge queue", pVnode->vgId, pMsg);
|
||||
|
||||
int32_t code = vnodeProcessFetchMsg(pVnode->pImpl, pMsg, pInfo);
|
||||
if (code != 0) {
|
||||
if (terrno != 0) code = terrno;
|
||||
dError("vgId:%d, msg:%p failed to merge since %s", pVnode->vgId, pMsg, terrstr());
|
||||
dGError("vgId:%d, msg:%p failed to merge since %s", pVnode->vgId, pMsg, terrstr());
|
||||
vmSendRsp(pMsg, code);
|
||||
}
|
||||
|
||||
dTrace("msg:%p, is freed, code:0x%x", pMsg, code);
|
||||
dGTrace("msg:%p, is freed, code:0x%x", pMsg, code);
|
||||
rpcFreeCont(pMsg->pCont);
|
||||
taosFreeQitem(pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t vmPutMsgToQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg, EQueueType qtype) {
|
||||
SMsgHead *pHead = pMsg->pCont;
|
||||
int32_t code = 0;
|
||||
const STraceId *trace = &pMsg->info.traceId;
|
||||
SMsgHead *pHead = pMsg->pCont;
|
||||
int32_t code = 0;
|
||||
|
||||
pHead->contLen = ntohl(pHead->contLen);
|
||||
pHead->vgId = ntohl(pHead->vgId);
|
||||
|
||||
SVnodeObj *pVnode = vmAcquireVnode(pMgmt, pHead->vgId);
|
||||
if (pVnode == NULL) {
|
||||
dError("vgId:%d, msg:%p failed to put into vnode queue since %s, type:%s", pHead->vgId, pMsg, terrstr(),
|
||||
TMSG_INFO(pMsg->msgType));
|
||||
dGError("vgId:%d, msg:%p failed to put into vnode queue since %s, type:%s", pHead->vgId, pMsg, terrstr(),
|
||||
TMSG_INFO(pMsg->msgType));
|
||||
return terrno != 0 ? terrno : -1;
|
||||
}
|
||||
|
||||
switch (qtype) {
|
||||
case QUERY_QUEUE:
|
||||
vnodePreprocessQueryMsg(pVnode->pImpl, pMsg);
|
||||
dTrace("vgId:%d, msg:%p put into vnode-query queue", pVnode->vgId, pMsg);
|
||||
dGTrace("vgId:%d, msg:%p put into vnode-query queue", pVnode->vgId, pMsg);
|
||||
taosWriteQitem(pVnode->pQueryQ, pMsg);
|
||||
break;
|
||||
case FETCH_QUEUE:
|
||||
dTrace("vgId:%d, msg:%p put into vnode-fetch queue", pVnode->vgId, pMsg);
|
||||
dGTrace("vgId:%d, msg:%p put into vnode-fetch queue", pVnode->vgId, pMsg);
|
||||
taosWriteQitem(pVnode->pFetchQ, pMsg);
|
||||
break;
|
||||
case WRITE_QUEUE:
|
||||
dTrace("vgId:%d, msg:%p put into vnode-write queue", pVnode->vgId, pMsg);
|
||||
dGTrace("vgId:%d, msg:%p put into vnode-write queue", pVnode->vgId, pMsg);
|
||||
taosWriteQitem(pVnode->pWriteQ, pMsg);
|
||||
break;
|
||||
case SYNC_QUEUE:
|
||||
dTrace("vgId:%d, msg:%p put into vnode-sync queue", pVnode->vgId, pMsg);
|
||||
dGTrace("vgId:%d, msg:%p put into vnode-sync queue", pVnode->vgId, pMsg);
|
||||
taosWriteQitem(pVnode->pSyncQ, pMsg);
|
||||
break;
|
||||
case APPLY_QUEUE:
|
||||
dTrace("vgId:%d, msg:%p put into vnode-apply queue", pVnode->vgId, pMsg);
|
||||
dGTrace("vgId:%d, msg:%p put into vnode-apply queue", pVnode->vgId, pMsg);
|
||||
taosWriteQitem(pVnode->pApplyQ, pMsg);
|
||||
break;
|
||||
default:
|
||||
|
@ -193,13 +198,15 @@ int32_t vmPutMsgToQueryQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) { return vmPutMsg
|
|||
int32_t vmPutMsgToFetchQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) { return vmPutMsgToQueue(pMgmt, pMsg, FETCH_QUEUE); }
|
||||
|
||||
int32_t vmPutMsgToMgmtQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
|
||||
dTrace("msg:%p, put into vnode-mgmt queue", pMsg);
|
||||
const STraceId *trace = &pMsg->info.traceId;
|
||||
dGTrace("msg:%p, put into vnode-mgmt queue", pMsg);
|
||||
taosWriteQitem(pMgmt->mgmtWorker.queue, pMsg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t vmPutMsgToMonitorQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
|
||||
dTrace("msg:%p, put into vnode-monitor queue", pMsg);
|
||||
const STraceId *trace = &pMsg->info.traceId;
|
||||
dGTrace("msg:%p, put into vnode-monitor queue", pMsg);
|
||||
taosWriteQitem(pMgmt->monitorWorker.queue, pMsg);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// clang-format off
|
||||
|
||||
#define dFatal(...) { if (dDebugFlag & DEBUG_FATAL) { taosPrintLog("DND FATAL ", DEBUG_FATAL, 255, __VA_ARGS__); }}
|
||||
|
|
|
@ -35,6 +35,7 @@ extern "C" {
|
|||
|
||||
// clang-format off
|
||||
|
||||
|
||||
#define mFatal(...) { if (mDebugFlag & DEBUG_FATAL) { taosPrintLog("MND FATAL ", DEBUG_FATAL, 255, __VA_ARGS__); }}
|
||||
#define mError(...) { if (mDebugFlag & DEBUG_ERROR) { taosPrintLog("MND ERROR ", DEBUG_ERROR, 255, __VA_ARGS__); }}
|
||||
#define mWarn(...) { if (mDebugFlag & DEBUG_WARN) { taosPrintLog("MND WARN ", DEBUG_WARN, 255, __VA_ARGS__); }}
|
||||
|
@ -77,7 +78,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
SCacheObj *connCache;
|
||||
SCacheObj *appCache;
|
||||
SCacheObj *appCache;
|
||||
} SProfileMgmt;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -24,12 +24,12 @@ extern "C" {
|
|||
|
||||
#define QNODE_LOAD_VALUE(pQnode) (pQnode ? (pQnode->load.numOfQueryInQueue + pQnode->load.numOfFetchInQueue) : 0)
|
||||
|
||||
int32_t mndInitQnode(SMnode *pMnode);
|
||||
void mndCleanupQnode(SMnode *pMnode);
|
||||
|
||||
int32_t mndInitQnode(SMnode *pMnode);
|
||||
void mndCleanupQnode(SMnode *pMnode);
|
||||
SQnodeObj *mndAcquireQnode(SMnode *pMnode, int32_t qnodeId);
|
||||
void mndReleaseQnode(SMnode *pMnode, SQnodeObj *pObj);
|
||||
int32_t mndCreateQnodeList(SMnode *pMnode, SArray** pList, int32_t limit);
|
||||
void mndReleaseQnode(SMnode *pMnode, SQnodeObj *pObj);
|
||||
int32_t mndCreateQnodeList(SMnode *pMnode, SArray **pList, int32_t limit);
|
||||
int32_t mndSetDropQnodeInfoToTrans(SMnode *pMnode, STrans *pTrans, SQnodeObj *pObj);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -22,9 +22,12 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
int32_t mndInitSnode(SMnode *pMnode);
|
||||
void mndCleanupSnode(SMnode *pMnode);
|
||||
SEpSet mndAcquireEpFromSnode(SMnode *pMnode, const SSnodeObj *pSnode);
|
||||
int32_t mndInitSnode(SMnode *pMnode);
|
||||
void mndCleanupSnode(SMnode *pMnode);
|
||||
SSnodeObj *mndAcquireSnode(SMnode *pMnode, int32_t qnodeId);
|
||||
void mndReleaseSnode(SMnode *pMnode, SSnodeObj *pObj);
|
||||
SEpSet mndAcquireEpFromSnode(SMnode *pMnode, const SSnodeObj *pSnode);
|
||||
int32_t mndSetDropSnodeInfoToTrans(SMnode *pMnode, STrans *pTrans, SSnodeObj *pObj);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "mndMnode.h"
|
||||
#include "mndQnode.h"
|
||||
#include "mndShow.h"
|
||||
#include "mndSnode.h"
|
||||
#include "mndTrans.h"
|
||||
#include "mndUser.h"
|
||||
#include "mndVgroup.h"
|
||||
|
@ -370,7 +371,8 @@ static int32_t mndProcessStatusReq(SRpcMsg *pReq) {
|
|||
SMnodeObj *pObj = mndAcquireMnode(pMnode, pDnode->id);
|
||||
if (pObj != NULL) {
|
||||
if (pObj->state != statusReq.mload.syncState) {
|
||||
mInfo("dnode:%d, mnode syncstate from %s to %s", pObj->id, syncStr(pObj->state), syncStr(statusReq.mload.syncState));
|
||||
mInfo("dnode:%d, mnode syncstate from %s to %s", pObj->id, syncStr(pObj->state),
|
||||
syncStr(statusReq.mload.syncState));
|
||||
pObj->state = statusReq.mload.syncState;
|
||||
pObj->stateStartTime = taosGetTimestampMs();
|
||||
}
|
||||
|
@ -508,7 +510,7 @@ static int32_t mndProcessCreateDnodeReq(SRpcMsg *pReq) {
|
|||
goto _OVER;
|
||||
}
|
||||
|
||||
mDebug("dnode:%s:%d, start to create", createReq.fqdn, createReq.port);
|
||||
mInfo("dnode:%s:%d, start to create", createReq.fqdn, createReq.port);
|
||||
|
||||
if (createReq.fqdn[0] == 0 || createReq.port <= 0 || createReq.port > UINT16_MAX) {
|
||||
terrno = TSDB_CODE_MND_INVALID_DNODE_EP;
|
||||
|
@ -538,7 +540,8 @@ _OVER:
|
|||
return code;
|
||||
}
|
||||
|
||||
static int32_t mndDropDnode(SMnode *pMnode, SRpcMsg *pReq, SDnodeObj *pDnode, SMnodeObj *pMObj, int32_t numOfVnodes) {
|
||||
static int32_t mndDropDnode(SMnode *pMnode, SRpcMsg *pReq, SDnodeObj *pDnode, SMnodeObj *pMObj, SQnodeObj *pQObj,
|
||||
SSnodeObj *pSObj, int32_t numOfVnodes) {
|
||||
int32_t code = -1;
|
||||
SSdbRaw *pRaw = NULL;
|
||||
STrans *pTrans = NULL;
|
||||
|
@ -546,7 +549,7 @@ static int32_t mndDropDnode(SMnode *pMnode, SRpcMsg *pReq, SDnodeObj *pDnode, SM
|
|||
pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_GLOBAL, pReq);
|
||||
if (pTrans == NULL) goto _OVER;
|
||||
mndTransSetSerial(pTrans);
|
||||
mDebug("trans:%d, used to drop dnode:%d", pTrans->id, pDnode->id);
|
||||
mInfo("trans:%d, used to drop dnode:%d", pTrans->id, pDnode->id);
|
||||
|
||||
pRaw = mndDnodeActionEncode(pDnode);
|
||||
if (pRaw == NULL || mndTransAppendRedolog(pTrans, pRaw) != 0) goto _OVER;
|
||||
|
@ -559,11 +562,22 @@ static int32_t mndDropDnode(SMnode *pMnode, SRpcMsg *pReq, SDnodeObj *pDnode, SM
|
|||
pRaw = NULL;
|
||||
|
||||
if (pMObj != NULL) {
|
||||
mDebug("trans:%d, mnode on dnode:%d will be dropped", pTrans->id, pDnode->id);
|
||||
mInfo("trans:%d, mnode on dnode:%d will be dropped", pTrans->id, pDnode->id);
|
||||
if (mndSetDropMnodeInfoToTrans(pMnode, pTrans, pMObj) != 0) goto _OVER;
|
||||
}
|
||||
|
||||
if (pQObj != NULL) {
|
||||
mInfo("trans:%d, qnode on dnode:%d will be dropped", pTrans->id, pDnode->id);
|
||||
if (mndSetDropQnodeInfoToTrans(pMnode, pTrans, pQObj) != 0) goto _OVER;
|
||||
}
|
||||
|
||||
if (pSObj != NULL) {
|
||||
mInfo("trans:%d, snode on dnode:%d will be dropped", pTrans->id, pDnode->id);
|
||||
if (mndSetDropSnodeInfoToTrans(pMnode, pTrans, pSObj) != 0) goto _OVER;
|
||||
}
|
||||
|
||||
if (numOfVnodes > 0) {
|
||||
mDebug("trans:%d, %d vnodes on dnode:%d will be dropped", pTrans->id, numOfVnodes, pDnode->id);
|
||||
mInfo("trans:%d, %d vnodes on dnode:%d will be dropped", pTrans->id, numOfVnodes, pDnode->id);
|
||||
if (mndSetMoveVgroupsInfoToTrans(pMnode, pTrans, pDnode->id) != 0) goto _OVER;
|
||||
}
|
||||
if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER;
|
||||
|
@ -581,6 +595,8 @@ static int32_t mndProcessDropDnodeReq(SRpcMsg *pReq) {
|
|||
int32_t code = -1;
|
||||
SDnodeObj *pDnode = NULL;
|
||||
SMnodeObj *pMObj = NULL;
|
||||
SQnodeObj *pQObj = NULL;
|
||||
SSnodeObj *pSObj = NULL;
|
||||
SMDropMnodeReq dropReq = {0};
|
||||
|
||||
if (tDeserializeSCreateDropMQSBNodeReq(pReq->pCont, pReq->contLen, &dropReq) != 0) {
|
||||
|
@ -588,7 +604,7 @@ static int32_t mndProcessDropDnodeReq(SRpcMsg *pReq) {
|
|||
goto _OVER;
|
||||
}
|
||||
|
||||
mDebug("dnode:%d, start to drop", dropReq.dnodeId);
|
||||
mInfo("dnode:%d, start to drop", dropReq.dnodeId);
|
||||
|
||||
if (dropReq.dnodeId <= 0) {
|
||||
terrno = TSDB_CODE_MND_INVALID_DNODE_ID;
|
||||
|
@ -601,6 +617,8 @@ static int32_t mndProcessDropDnodeReq(SRpcMsg *pReq) {
|
|||
goto _OVER;
|
||||
}
|
||||
|
||||
pQObj = mndAcquireQnode(pMnode, dropReq.dnodeId);
|
||||
pSObj = mndAcquireSnode(pMnode, dropReq.dnodeId);
|
||||
pMObj = mndAcquireMnode(pMnode, dropReq.dnodeId);
|
||||
if (pMObj != NULL) {
|
||||
if (sdbGetSize(pMnode->pSdb, SDB_MNODE) <= 1) {
|
||||
|
@ -627,7 +645,7 @@ static int32_t mndProcessDropDnodeReq(SRpcMsg *pReq) {
|
|||
goto _OVER;
|
||||
}
|
||||
|
||||
code = mndDropDnode(pMnode, pReq, pDnode, pMObj, numOfVnodes);
|
||||
code = mndDropDnode(pMnode, pReq, pDnode, pMObj, pQObj, pSObj, numOfVnodes);
|
||||
if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
|
||||
|
||||
_OVER:
|
||||
|
@ -637,6 +655,8 @@ _OVER:
|
|||
|
||||
mndReleaseDnode(pMnode, pDnode);
|
||||
mndReleaseMnode(pMnode, pMObj);
|
||||
mndReleaseQnode(pMnode, pQObj);
|
||||
mndReleaseSnode(pMnode, pSObj);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
|
|
@ -447,7 +447,7 @@ static int32_t mndUpdateAppInfo(SMnode *pMnode, SClientHbReq *pHbReq, SRpcConnIn
|
|||
mError("failed to create new app %" PRIx64 " since %s", pReq->appId, terrstr());
|
||||
return -1;
|
||||
} else {
|
||||
mDebug("a new app %" PRIx64 "created", pReq->appId);
|
||||
mDebug("a new app %" PRIx64 " is created", pReq->appId);
|
||||
mndReleaseApp(pMnode, pApp);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -354,6 +354,14 @@ static int32_t mndSetDropQnodeRedoActions(STrans *pTrans, SDnodeObj *pDnode, SQn
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t mndSetDropQnodeInfoToTrans(SMnode *pMnode, STrans *pTrans, SQnodeObj *pObj) {
|
||||
if (pObj == NULL) return 0;
|
||||
if (mndSetDropQnodeRedoLogs(pTrans, pObj) != 0) return -1;
|
||||
if (mndSetDropQnodeCommitLogs(pTrans, pObj) != 0) return -1;
|
||||
if (mndSetDropQnodeRedoActions(pTrans, pObj->pDnode, pObj) != 0) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t mndDropQnode(SMnode *pMnode, SRpcMsg *pReq, SQnodeObj *pObj) {
|
||||
int32_t code = -1;
|
||||
|
||||
|
@ -361,9 +369,7 @@ static int32_t mndDropQnode(SMnode *pMnode, SRpcMsg *pReq, SQnodeObj *pObj) {
|
|||
if (pTrans == NULL) goto _OVER;
|
||||
|
||||
mDebug("trans:%d, used to drop qnode:%d", pTrans->id, pObj->id);
|
||||
if (mndSetDropQnodeRedoLogs(pTrans, pObj) != 0) goto _OVER;
|
||||
if (mndSetDropQnodeCommitLogs(pTrans, pObj) != 0) goto _OVER;
|
||||
if (mndSetDropQnodeRedoActions(pTrans, pObj->pDnode, pObj) != 0) goto _OVER;
|
||||
if (mndSetDropQnodeInfoToTrans(pMnode, pTrans, pObj) != 0) goto _OVER;
|
||||
if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER;
|
||||
|
||||
code = 0;
|
||||
|
|
|
@ -65,7 +65,7 @@ SEpSet mndAcquireEpFromSnode(SMnode *pMnode, const SSnodeObj *pSnode) {
|
|||
return epSet;
|
||||
}
|
||||
|
||||
static SSnodeObj *mndAcquireSnode(SMnode *pMnode, int32_t snodeId) {
|
||||
SSnodeObj *mndAcquireSnode(SMnode *pMnode, int32_t snodeId) {
|
||||
SSnodeObj *pObj = sdbAcquire(pMnode->pSdb, SDB_SNODE, &snodeId);
|
||||
if (pObj == NULL && terrno == TSDB_CODE_SDB_OBJ_NOT_THERE) {
|
||||
terrno = TSDB_CODE_MND_SNODE_NOT_EXIST;
|
||||
|
@ -73,7 +73,7 @@ static SSnodeObj *mndAcquireSnode(SMnode *pMnode, int32_t snodeId) {
|
|||
return pObj;
|
||||
}
|
||||
|
||||
static void mndReleaseSnode(SMnode *pMnode, SSnodeObj *pObj) {
|
||||
void mndReleaseSnode(SMnode *pMnode, SSnodeObj *pObj) {
|
||||
SSdb *pSdb = pMnode->pSdb;
|
||||
sdbRelease(pSdb, pObj);
|
||||
}
|
||||
|
@ -361,6 +361,14 @@ static int32_t mndSetDropSnodeRedoActions(STrans *pTrans, SDnodeObj *pDnode, SSn
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t mndSetDropSnodeInfoToTrans(SMnode *pMnode, STrans *pTrans, SSnodeObj *pObj) {
|
||||
if (pObj == NULL) return 0;
|
||||
if (mndSetDropSnodeRedoLogs(pTrans, pObj) != 0) return -1;
|
||||
if (mndSetDropSnodeCommitLogs(pTrans, pObj) != 0) return -1;
|
||||
if (mndSetDropSnodeRedoActions(pTrans, pObj->pDnode, pObj) != 0) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t mndDropSnode(SMnode *pMnode, SRpcMsg *pReq, SSnodeObj *pObj) {
|
||||
int32_t code = -1;
|
||||
|
||||
|
@ -368,10 +376,7 @@ static int32_t mndDropSnode(SMnode *pMnode, SRpcMsg *pReq, SSnodeObj *pObj) {
|
|||
if (pTrans == NULL) goto _OVER;
|
||||
|
||||
mDebug("trans:%d, used to drop snode:%d", pTrans->id, pObj->id);
|
||||
|
||||
if (mndSetDropSnodeRedoLogs(pTrans, pObj) != 0) goto _OVER;
|
||||
if (mndSetDropSnodeCommitLogs(pTrans, pObj) != 0) goto _OVER;
|
||||
if (mndSetDropSnodeRedoActions(pTrans, pObj->pDnode, pObj) != 0) goto _OVER;
|
||||
if (mndSetDropSnodeInfoToTrans(pMnode, pTrans, pObj) != 0) goto _OVER;
|
||||
if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER;
|
||||
|
||||
code = 0;
|
||||
|
|
|
@ -75,7 +75,7 @@ void mndSyncCommitMsg(struct SSyncFSM *pFsm, const SRpcMsg *pMsg, SFsmCbMeta cbM
|
|||
}
|
||||
|
||||
int32_t mndSyncGetSnapshot(struct SSyncFSM *pFsm, SSnapshot *pSnapshot, void *pReaderParam, void **ppReader) {
|
||||
mInfo("start to read snapshot from sdb in atomic way");
|
||||
mDebug("start to read snapshot from sdb in atomic way");
|
||||
SMnode *pMnode = pFsm->data;
|
||||
return sdbStartRead(pMnode->pSdb, (SSdbIter **)ppReader, &pSnapshot->lastApplyIndex, &pSnapshot->lastApplyTerm,
|
||||
&pSnapshot->lastConfigIndex);
|
||||
|
@ -96,7 +96,7 @@ void mndRestoreFinish(struct SSyncFSM *pFsm) {
|
|||
mndTransPullup(pMnode);
|
||||
mndSetRestore(pMnode, true);
|
||||
} else {
|
||||
mInfo("mnode sync restore finished, and will set ready after first deploy");
|
||||
mInfo("mnode sync restore finished");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,13 +118,13 @@ void mndReConfig(struct SSyncFSM *pFsm, const SRpcMsg *pMsg, SReConfigCbMeta cbM
|
|||
}
|
||||
|
||||
int32_t mndSnapshotStartRead(struct SSyncFSM *pFsm, void **ppReader) {
|
||||
mInfo("start to read snapshot from sdb");
|
||||
mDebug("start to read snapshot from sdb");
|
||||
SMnode *pMnode = pFsm->data;
|
||||
return sdbStartRead(pMnode->pSdb, (SSdbIter **)ppReader, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
int32_t mndSnapshotStopRead(struct SSyncFSM *pFsm, void *pReader) {
|
||||
mInfo("stop to read snapshot from sdb");
|
||||
mDebug("stop to read snapshot from sdb");
|
||||
SMnode *pMnode = pFsm->data;
|
||||
return sdbStopRead(pMnode->pSdb, pReader);
|
||||
}
|
||||
|
|
|
@ -432,11 +432,11 @@ static const char *mndTransStr(ETrnStage stage) {
|
|||
}
|
||||
|
||||
static void mndTransTestStartFunc(SMnode *pMnode, void *param, int32_t paramLen) {
|
||||
mInfo("test trans start, param:%s, len:%d", (char *)param, paramLen);
|
||||
mDebug("test trans start, param:%s, len:%d", (char *)param, paramLen);
|
||||
}
|
||||
|
||||
static void mndTransTestStopFunc(SMnode *pMnode, void *param, int32_t paramLen) {
|
||||
mInfo("test trans stop, param:%s, len:%d", (char *)param, paramLen);
|
||||
mDebug("test trans stop, param:%s, len:%d", (char *)param, paramLen);
|
||||
}
|
||||
|
||||
static TransCbFp mndTransGetCbFp(ETrnFunc ftype) {
|
||||
|
|
|
@ -1017,6 +1017,11 @@ int32_t mndSetMoveVgroupInfoToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb,
|
|||
if (mndAddDropVnodeAction(pMnode, pTrans, pDb, &newVg, &del, true) != 0) return -1;
|
||||
if (mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg) != 0) return -1;
|
||||
|
||||
SSdbRaw *pRaw = mndVgroupActionEncode(&newVg);
|
||||
if (pRaw == NULL || mndTransAppendCommitlog(pTrans, pRaw) != 0) return -1;
|
||||
sdbSetRawStatus(pRaw, SDB_STATUS_READY);
|
||||
pRaw = NULL;
|
||||
|
||||
mInfo("vgId:%d, vgroup info after move, replica:%d", newVg.vgId, newVg.replica);
|
||||
for (int32_t i = 0; i < newVg.replica; ++i) {
|
||||
mInfo("vgId:%d, vnode:%d dnode:%d", newVg.vgId, i, newVg.vnodeGid[i].dnodeId);
|
||||
|
@ -1025,6 +1030,7 @@ int32_t mndSetMoveVgroupInfoToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb,
|
|||
}
|
||||
|
||||
int32_t mndSetMoveVgroupsInfoToTrans(SMnode *pMnode, STrans *pTrans, int32_t delDnodeId) {
|
||||
int32_t code = 0;
|
||||
SArray *pArray = mndBuildDnodesArray(pMnode, delDnodeId);
|
||||
if (pArray == NULL) return -1;
|
||||
|
||||
|
@ -1042,18 +1048,24 @@ int32_t mndSetMoveVgroupsInfoToTrans(SMnode *pMnode, STrans *pTrans, int32_t del
|
|||
}
|
||||
}
|
||||
|
||||
code = 0;
|
||||
if (vnIndex != -1) {
|
||||
mInfo("vgId:%d, vnode:%d will be removed from dnode:%d", pVgroup->vgId, vnIndex, delDnodeId);
|
||||
SDbObj *pDb = mndAcquireDb(pMnode, pVgroup->dbName);
|
||||
mndSetMoveVgroupInfoToTrans(pMnode, pTrans, pDb, pVgroup, vnIndex, pArray);
|
||||
code = mndSetMoveVgroupInfoToTrans(pMnode, pTrans, pDb, pVgroup, vnIndex, pArray);
|
||||
mndReleaseDb(pMnode, pDb);
|
||||
}
|
||||
|
||||
sdbRelease(pMnode->pSdb, pVgroup);
|
||||
|
||||
if (code != 0) {
|
||||
sdbCancelFetch(pMnode->pSdb, pIter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
taosArrayDestroy(pArray);
|
||||
return 0;
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t mndAddIncVgroupReplicaToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup,
|
||||
|
|
|
@ -519,7 +519,7 @@ static void sdbCloseIter(SSdbIter *pIter) {
|
|||
pIter->name = NULL;
|
||||
}
|
||||
|
||||
mInfo("sdbiter:%p, is closed, total:%" PRId64, pIter, pIter->total);
|
||||
mDebug("sdbiter:%p, is closed, total:%" PRId64, pIter, pIter->total);
|
||||
taosMemoryFree(pIter);
|
||||
}
|
||||
|
||||
|
@ -556,7 +556,7 @@ int32_t sdbStartRead(SSdb *pSdb, SSdbIter **ppIter, int64_t *index, int64_t *ter
|
|||
if (term != NULL) *term = commitTerm;
|
||||
if (config != NULL) *config = commitConfig;
|
||||
|
||||
mInfo("sdbiter:%p, is created to read snapshot, commit index:%" PRId64 " term:%" PRId64 " config:%" PRId64 " file:%s",
|
||||
mDebug("sdbiter:%p, is created to read snapshot, commit index:%" PRId64 " term:%" PRId64 " config:%" PRId64 " file:%s",
|
||||
pIter, commitIndex, commitTerm, commitConfig, pIter->name);
|
||||
return 0;
|
||||
}
|
||||
|
@ -583,14 +583,14 @@ int32_t sdbDoRead(SSdb *pSdb, SSdbIter *pIter, void **ppBuf, int32_t *len) {
|
|||
taosMemoryFree(pBuf);
|
||||
return -1;
|
||||
} else if (readlen == 0) {
|
||||
mInfo("sdbiter:%p, read snapshot to the end, total:%" PRId64, pIter, pIter->total);
|
||||
mDebug("sdbiter:%p, read snapshot to the end, total:%" PRId64, pIter, pIter->total);
|
||||
*ppBuf = NULL;
|
||||
*len = 0;
|
||||
taosMemoryFree(pBuf);
|
||||
return 0;
|
||||
} else { // (readlen <= maxlen)
|
||||
pIter->total += readlen;
|
||||
mInfo("sdbiter:%p, read:%d bytes from snapshot, total:%" PRId64, pIter, readlen, pIter->total);
|
||||
mDebug("sdbiter:%p, read:%d bytes from snapshot, total:%" PRId64, pIter, readlen, pIter->total);
|
||||
*ppBuf = pBuf;
|
||||
*len = readlen;
|
||||
return 0;
|
||||
|
@ -609,7 +609,7 @@ int32_t sdbStartWrite(SSdb *pSdb, SSdbIter **ppIter) {
|
|||
}
|
||||
|
||||
*ppIter = pIter;
|
||||
mInfo("sdbiter:%p, is created to write snapshot, file:%s", pIter, pIter->name);
|
||||
mDebug("sdbiter:%p, is created to write snapshot, file:%s", pIter, pIter->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -618,7 +618,7 @@ int32_t sdbStopWrite(SSdb *pSdb, SSdbIter *pIter, bool isApply) {
|
|||
|
||||
if (!isApply) {
|
||||
sdbCloseIter(pIter);
|
||||
mInfo("sdbiter:%p, not apply to sdb", pIter);
|
||||
mDebug("sdbiter:%p, not apply to sdb", pIter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -641,7 +641,7 @@ int32_t sdbStopWrite(SSdb *pSdb, SSdbIter *pIter, bool isApply) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
mInfo("sdbiter:%p, successfully applyed to sdb", pIter);
|
||||
mDebug("sdbiter:%p, successfully applyed to sdb", pIter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -654,6 +654,6 @@ int32_t sdbDoWrite(SSdb *pSdb, SSdbIter *pIter, void *pBuf, int32_t len) {
|
|||
}
|
||||
|
||||
pIter->total += writelen;
|
||||
mInfo("sdbiter:%p, write:%d bytes to snapshot, total:%" PRId64, pIter, writelen, pIter->total);
|
||||
mDebug("sdbiter:%p, write:%d bytes to snapshot, total:%" PRId64, pIter, writelen, pIter->total);
|
||||
return 0;
|
||||
}
|
|
@ -26,20 +26,19 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
// clang-format off
|
||||
#define vFatal(...) do { if (vDebugFlag & DEBUG_FATAL) { taosPrintLog("VND FATAL ", DEBUG_FATAL, 255, __VA_ARGS__); }} while(0)
|
||||
#define vError(...) do { if (vDebugFlag & DEBUG_ERROR) { taosPrintLog("VND ERROR ", DEBUG_ERROR, 255, __VA_ARGS__); }} while(0)
|
||||
#define vWarn(...) do { if (vDebugFlag & DEBUG_WARN) { taosPrintLog("VND WARN ", DEBUG_WARN, 255, __VA_ARGS__); }} while(0)
|
||||
#define vInfo(...) do { if (vDebugFlag & DEBUG_INFO) { taosPrintLog("VND ", DEBUG_INFO, 255, __VA_ARGS__); }} while(0)
|
||||
#define vDebug(...) do { if (vDebugFlag & DEBUG_DEBUG) { taosPrintLog("VND ", DEBUG_DEBUG, vDebugFlag, __VA_ARGS__); }} while(0)
|
||||
#define vTrace(...) do { if (vDebugFlag & DEBUG_TRACE) { taosPrintLog("VND ", DEBUG_TRACE, vDebugFlag, __VA_ARGS__); }} while(0)
|
||||
|
||||
#define vFatal(...) { if (vDebugFlag & DEBUG_FATAL) { taosPrintLog("VND FATAL ", DEBUG_FATAL, 255, __VA_ARGS__); }}
|
||||
#define vError(...) { if (vDebugFlag & DEBUG_ERROR) { taosPrintLog("VND ERROR ", DEBUG_ERROR, 255, __VA_ARGS__); }}
|
||||
#define vWarn(...) { if (vDebugFlag & DEBUG_WARN) { taosPrintLog("VND WARN ", DEBUG_WARN, 255, __VA_ARGS__); }}
|
||||
#define vInfo(...) { if (vDebugFlag & DEBUG_INFO) { taosPrintLog("VND ", DEBUG_INFO, 255, __VA_ARGS__); }}
|
||||
#define vDebug(...) { if (vDebugFlag & DEBUG_DEBUG) { taosPrintLog("VND ", DEBUG_DEBUG, vDebugFlag, __VA_ARGS__); }}
|
||||
#define vTrace(...) { if (vDebugFlag & DEBUG_TRACE) { taosPrintLog("VND ", DEBUG_TRACE, vDebugFlag, __VA_ARGS__); }}
|
||||
|
||||
#define vGFatal(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); vFatal(param ", gtid:%s", __VA_ARGS__, buf);}
|
||||
#define vGError(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); vError(param ", gtid:%s", __VA_ARGS__, buf);}
|
||||
#define vGWarn(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); vWarn (param ", gtid:%s", __VA_ARGS__, buf);}
|
||||
#define vGInfo(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); vInfo (param ", gtid:%s", __VA_ARGS__, buf);}
|
||||
#define vGDebug(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); vDebug(param ", gtid:%s", __VA_ARGS__, buf);}
|
||||
#define vGTrace(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); vTrace(param ", gtid:%s", __VA_ARGS__, buf);}
|
||||
#define vGTrace(param, ...) do { if (vDebugFlag & DEBUG_TRACE) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); vTrace(param ", gtid:%s", __VA_ARGS__, buf);}} while(0)
|
||||
#define vGFatal(param, ...) do { if (vDebugFlag & DEBUG_FATAL) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); vFatal(param ", gtid:%s", __VA_ARGS__, buf);}} while(0)
|
||||
#define vGError(param, ...) do { if (vDebugFlag & DEBUG_ERROR) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); vError(param ", gtid:%s", __VA_ARGS__, buf);}} while(0)
|
||||
#define vGWarn(param, ...) do { if (vDebugFlag & DEBUG_WARN) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); vWarn(param ", gtid:%s", __VA_ARGS__, buf);}} while(0)
|
||||
#define vGInfo(param, ...) do { if (vDebugFlag & DEBUG_INFO) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); vInfo(param ", gtid:%s", __VA_ARGS__, buf);}} while(0)
|
||||
#define vGDebug(param, ...) do { if (vDebugFlag & DEBUG_DEBUG) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); vDebug(param ", gtid:%s", __VA_ARGS__, buf);}} while(0)
|
||||
|
||||
// clang-format on
|
||||
|
||||
|
|
|
@ -92,9 +92,8 @@ SSubmitReq* tdBlockToSubmit(const SArray* pBlocks, const STSchema* pTSchema, boo
|
|||
blkHead->uid = 0;
|
||||
|
||||
int32_t rows = pDataBlock->info.rows;
|
||||
/*int32_t maxLen = TD_ROW_MAX_BYTES_FROM_SCHEMA(pTSchema);*/
|
||||
/*blkHead->dataLen = htonl(rows * maxLen);*/
|
||||
blkHead->dataLen = 0;
|
||||
|
||||
int32_t dataLen = 0;
|
||||
|
||||
void* blkSchema = POINTER_SHIFT(blkHead, sizeof(SSubmitBlk));
|
||||
|
||||
|
@ -167,9 +166,8 @@ SSubmitReq* tdBlockToSubmit(const SArray* pBlocks, const STSchema* pTSchema, boo
|
|||
}
|
||||
int32_t rowLen = TD_ROW_LEN(rowData);
|
||||
rowData = POINTER_SHIFT(rowData, rowLen);
|
||||
blkHead->dataLen += rowLen;
|
||||
dataLen += rowLen;
|
||||
}
|
||||
int32_t dataLen = blkHead->dataLen;
|
||||
blkHead->dataLen = htonl(dataLen);
|
||||
|
||||
ret->length += sizeof(SSubmitBlk) + schemaLen + dataLen;
|
||||
|
|
|
@ -184,8 +184,8 @@ int32_t qExplainGenerateResChildren(SPhysiNode *pNode, SExplainGroup *group, SNo
|
|||
pPhysiChildren = indefPhysiNode->node.pChildren;
|
||||
break;
|
||||
}
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL: {
|
||||
SMergeIntervalPhysiNode *intPhysiNode = (SMergeIntervalPhysiNode *)pNode;
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL: {
|
||||
SMergeAlignedIntervalPhysiNode *intPhysiNode = (SMergeAlignedIntervalPhysiNode *)pNode;
|
||||
pPhysiChildren = intPhysiNode->window.node.pChildren;
|
||||
break;
|
||||
}
|
||||
|
@ -841,8 +841,8 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
|
|||
}
|
||||
break;
|
||||
}
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL: {
|
||||
SMergeIntervalPhysiNode *pIntNode = (SMergeIntervalPhysiNode *)pNode;
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL: {
|
||||
SMergeAlignedIntervalPhysiNode *pIntNode = (SMergeAlignedIntervalPhysiNode *)pNode;
|
||||
EXPLAIN_ROW_NEW(level, EXPLAIN_INTERVAL_FORMAT, nodesGetNameFromColumnNode(pIntNode->window.pTspk));
|
||||
EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
|
||||
if (pResNode->pExecInfo) {
|
||||
|
|
|
@ -234,6 +234,7 @@ typedef struct SColMatchInfo {
|
|||
int32_t colId;
|
||||
int32_t targetSlotId;
|
||||
bool output;
|
||||
bool reserved;
|
||||
int32_t matchType; // determinate the source according to col id or slot id
|
||||
} SColMatchInfo;
|
||||
|
||||
|
@ -253,7 +254,6 @@ typedef struct STableScanInfo {
|
|||
|
||||
SFileBlockLoadRecorder readRecorder;
|
||||
int64_t numOfRows;
|
||||
// int32_t prevGroupId; // previous table group id
|
||||
SScanInfo scanInfo;
|
||||
int32_t scanTimes;
|
||||
SNode* pFilterNode; // filter info, which is push down by optimizer
|
||||
|
@ -733,6 +733,10 @@ SOperatorInfo* createMergeIntervalOperatorInfo(SOperatorInfo* downstream, SExprI
|
|||
SSDataBlock* pResBlock, SInterval* pInterval, int32_t primaryTsSlotId,
|
||||
SExecTaskInfo* pTaskInfo);
|
||||
|
||||
SOperatorInfo* createMergeAlignedIntervalOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExprInfo, int32_t numOfCols,
|
||||
SSDataBlock* pResBlock, SInterval* pInterval, int32_t primaryTsSlotId,
|
||||
SExecTaskInfo* pTaskInfo);
|
||||
|
||||
SOperatorInfo* createStreamFinalIntervalOperatorInfo(SOperatorInfo* downstream,
|
||||
SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo, int32_t numOfChild);
|
||||
SOperatorInfo* createStreamIntervalOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExprInfo, int32_t numOfCols,
|
||||
|
|
|
@ -50,6 +50,7 @@ typedef struct SMsortComparParam {
|
|||
void **pSources;
|
||||
int32_t numOfSources;
|
||||
SArray *orderInfo; // SArray<SBlockOrderInfo>
|
||||
bool cmpGroupId;
|
||||
} SMsortComparParam;
|
||||
|
||||
typedef struct SSortHandle SSortHandle;
|
||||
|
@ -99,6 +100,11 @@ int32_t tsortSetFetchRawDataFp(SSortHandle* pHandle, _sort_fetch_block_fn_t fetc
|
|||
*/
|
||||
int32_t tsortSetComparFp(SSortHandle* pHandle, _sort_merge_compar_fn_t fp);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
int32_t tsortSetCompareGroupId(SSortHandle* pHandle, bool compareGroupId);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param pHandle
|
||||
|
|
|
@ -300,7 +300,7 @@ SArray* extractColMatchInfo(SNodeList* pNodeList, SDataBlockDescNode* pOutputNod
|
|||
|
||||
SColMatchInfo c = {0};
|
||||
c.output = true;
|
||||
c.colId = pColNode->colId;
|
||||
c.colId = pColNode->colId;
|
||||
c.srcSlotId = pColNode->slotId;
|
||||
c.matchType = type;
|
||||
c.targetSlotId = pNode->slotId;
|
||||
|
|
|
@ -609,7 +609,7 @@ int32_t projectApplyFunctions(SExprInfo* pExpr, SSDataBlock* pResult, SSDataBloc
|
|||
}
|
||||
|
||||
int32_t startOffset = createNewColModel ? 0 : pResult->info.rows;
|
||||
colInfoDataEnsureCapacity(pResColData, startOffset, pResult->info.capacity);
|
||||
ASSERT(pResult->info.capacity > 0);
|
||||
colDataMergeCol(pResColData, startOffset, &pResult->info.capacity, &idata, dest.numOfRows);
|
||||
|
||||
numOfRows = dest.numOfRows;
|
||||
|
@ -649,7 +649,7 @@ int32_t projectApplyFunctions(SExprInfo* pExpr, SSDataBlock* pResult, SSDataBloc
|
|||
}
|
||||
|
||||
int32_t startOffset = createNewColModel ? 0 : pResult->info.rows;
|
||||
colInfoDataEnsureCapacity(pResColData, startOffset, pResult->info.capacity);
|
||||
ASSERT(pResult->info.capacity > 0);
|
||||
colDataMergeCol(pResColData, startOffset, &pResult->info.capacity, &idata, dest.numOfRows);
|
||||
|
||||
numOfRows = dest.numOfRows;
|
||||
|
@ -1340,9 +1340,9 @@ void extractQualifiedTupleByFilterResult(SSDataBlock* pBlock, const int8_t* rowR
|
|||
}
|
||||
|
||||
if (rowRes != NULL) {
|
||||
int32_t totalRows = pBlock->info.rows;
|
||||
SSDataBlock* px = createOneDataBlock(pBlock, true);
|
||||
|
||||
int32_t totalRows = pBlock->info.rows;
|
||||
for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
|
||||
SColumnInfoData* pSrc = taosArrayGet(px->pDataBlock, i);
|
||||
SColumnInfoData* pDst = taosArrayGet(pBlock->pDataBlock, i);
|
||||
|
@ -2765,7 +2765,7 @@ SOperatorInfo* createSortedMergeOperatorInfo(SOperatorInfo** downstream, int32_t
|
|||
goto _error;
|
||||
}
|
||||
|
||||
size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
|
||||
size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
|
||||
code = doInitAggInfoSup(&pInfo->aggSup, pOperator->exprSupp.pCtx, num, keyBufSize, pTaskInfo->id.str);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _error;
|
||||
|
@ -2787,9 +2787,9 @@ SOperatorInfo* createSortedMergeOperatorInfo(SOperatorInfo** downstream, int32_t
|
|||
|
||||
pOperator->name = "SortedMerge";
|
||||
// pOperator->operatorType = OP_SortedMerge;
|
||||
pOperator->blocking = true;
|
||||
pOperator->status = OP_NOT_OPENED;
|
||||
pOperator->info = pInfo;
|
||||
pOperator->blocking = true;
|
||||
pOperator->status = OP_NOT_OPENED;
|
||||
pOperator->info = pInfo;
|
||||
pOperator->pTaskInfo = pTaskInfo;
|
||||
|
||||
pOperator->fpSet = createOperatorFpSet(operatorDummyOpenFn, doSortedMerge, NULL, NULL, destroySortedMergeOperatorInfo,
|
||||
|
@ -2844,8 +2844,8 @@ static int32_t doOpenAggregateOptr(SOperatorInfo* pOperator) {
|
|||
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
|
||||
SAggOperatorInfo* pAggInfo = pOperator->info;
|
||||
|
||||
SExprSupp* pSup = &pOperator->exprSupp;
|
||||
SOperatorInfo* downstream = pOperator->pDownstream[0];
|
||||
SExprSupp* pSup = &pOperator->exprSupp;
|
||||
SOperatorInfo* downstream = pOperator->pDownstream[0];
|
||||
|
||||
int64_t st = taosGetTimestampUs();
|
||||
|
||||
|
@ -3736,9 +3736,9 @@ SOperatorInfo* createIndefinitOutputOperatorInfo(SOperatorInfo* downstream, SPhy
|
|||
SExprInfo* pExprInfo = createExprInfo(pPhyNode->pFuncs, NULL, &numOfExpr);
|
||||
|
||||
if (pPhyNode->pExprs != NULL) {
|
||||
int32_t num = 0;
|
||||
int32_t num = 0;
|
||||
SExprInfo* pSExpr = createExprInfo(pPhyNode->pExprs, NULL, &num);
|
||||
int32_t code = initExprSupp(&pInfo->scalarSup, pSExpr, num);
|
||||
int32_t code = initExprSupp(&pInfo->scalarSup, pSExpr, num);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _error;
|
||||
}
|
||||
|
@ -3761,14 +3761,14 @@ SOperatorInfo* createIndefinitOutputOperatorInfo(SOperatorInfo* downstream, SPhy
|
|||
|
||||
setFunctionResultOutput(pOperator, &pInfo->binfo, &pInfo->aggSup, MAIN_SCAN, numOfExpr);
|
||||
|
||||
pInfo->binfo.pRes = pResBlock;
|
||||
pInfo->pPseudoColInfo = setRowTsColumnOutputInfo(pSup->pCtx, numOfExpr);
|
||||
pInfo->binfo.pRes = pResBlock;
|
||||
pInfo->pPseudoColInfo = setRowTsColumnOutputInfo(pSup->pCtx, numOfExpr);
|
||||
|
||||
pOperator->name = "IndefinitOperator";
|
||||
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_PROJECT;
|
||||
pOperator->blocking = false;
|
||||
pOperator->status = OP_NOT_OPENED;
|
||||
pOperator->info = pInfo;
|
||||
pOperator->blocking = false;
|
||||
pOperator->status = OP_NOT_OPENED;
|
||||
pOperator->info = pInfo;
|
||||
pOperator->exprSupp.numOfExprs = numOfExpr;
|
||||
pOperator->pTaskInfo = pTaskInfo;
|
||||
|
||||
|
@ -3838,10 +3838,10 @@ SOperatorInfo* createFillOperatorInfo(SOperatorInfo* downstream, SFillPhysiNode*
|
|||
pOperator->blocking = false;
|
||||
pOperator->status = OP_NOT_OPENED;
|
||||
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_FILL;
|
||||
pOperator->exprSupp.pExprInfo = pExprInfo;
|
||||
pOperator->exprSupp.numOfExprs = num;
|
||||
pOperator->info = pInfo;
|
||||
pOperator->pTaskInfo = pTaskInfo;
|
||||
pOperator->exprSupp.pExprInfo = pExprInfo;
|
||||
pOperator->exprSupp.numOfExprs = num;
|
||||
pOperator->info = pInfo;
|
||||
pOperator->pTaskInfo = pTaskInfo;
|
||||
|
||||
pOperator->fpSet =
|
||||
createOperatorFpSet(operatorDummyOpenFn, doFill, NULL, NULL, destroySFillOperatorInfo, NULL, NULL, NULL);
|
||||
|
@ -4087,7 +4087,7 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo
|
|||
|
||||
return createTagScanOperatorInfo(pHandle, pScanPhyNode, pTableListInfo, pTaskInfo);
|
||||
} else if (QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN == type) {
|
||||
SBlockDistScanPhysiNode* pBlockNode = (SBlockDistScanPhysiNode*) pPhyNode;
|
||||
SBlockDistScanPhysiNode* pBlockNode = (SBlockDistScanPhysiNode*)pPhyNode;
|
||||
pTableListInfo->pTableList = taosArrayInit(4, sizeof(STableKeyInfo));
|
||||
|
||||
if (pBlockNode->tableType == TSDB_SUPER_TABLE) {
|
||||
|
@ -4190,6 +4190,21 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo
|
|||
pOptr =
|
||||
createIntervalOperatorInfo(ops[0], pExprInfo, num, pResBlock, &interval, tsSlotId, &as, pTaskInfo, isStream);
|
||||
|
||||
} else if (QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL == type) {
|
||||
SMergeAlignedIntervalPhysiNode* pIntervalPhyNode = (SMergeAlignedIntervalPhysiNode*)pPhyNode;
|
||||
|
||||
SExprInfo* pExprInfo = createExprInfo(pIntervalPhyNode->window.pFuncs, NULL, &num);
|
||||
SSDataBlock* pResBlock = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
|
||||
|
||||
SInterval interval = {.interval = pIntervalPhyNode->interval,
|
||||
.sliding = pIntervalPhyNode->sliding,
|
||||
.intervalUnit = pIntervalPhyNode->intervalUnit,
|
||||
.slidingUnit = pIntervalPhyNode->slidingUnit,
|
||||
.offset = pIntervalPhyNode->offset,
|
||||
.precision = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->node.resType.precision};
|
||||
|
||||
int32_t tsSlotId = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
|
||||
pOptr = createMergeAlignedIntervalOperatorInfo(ops[0], pExprInfo, num, pResBlock, &interval, tsSlotId, pTaskInfo);
|
||||
} else if (QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL == type) {
|
||||
SMergeIntervalPhysiNode* pIntervalPhyNode = (SMergeIntervalPhysiNode*)pPhyNode;
|
||||
|
||||
|
|
|
@ -224,7 +224,7 @@ static int32_t loadDataBlock(SOperatorInfo* pOperator, STableScanInfo* pTableSca
|
|||
pBlock->pBlockAgg = taosMemoryCalloc(numOfCols, POINTER_BYTES);
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < numOfCols; ++i) {
|
||||
for (int32_t i = 0; i < taosArrayGetSize(pTableScanInfo->pColMatchInfo); ++i) {
|
||||
SColMatchInfo* pColMatchInfo = taosArrayGet(pTableScanInfo->pColMatchInfo, i);
|
||||
if (!pColMatchInfo->output) {
|
||||
continue;
|
||||
|
@ -384,7 +384,14 @@ static SSDataBlock* doTableScanImpl(SOperatorInfo* pOperator) {
|
|||
continue;
|
||||
}
|
||||
|
||||
tsdbRetrieveDataBlockInfo(pTableScanInfo->dataReader, &pBlock->info);
|
||||
blockDataCleanup(pBlock);
|
||||
|
||||
SDataBlockInfo binfo = pBlock->info;
|
||||
tsdbRetrieveDataBlockInfo(pTableScanInfo->dataReader, &binfo);
|
||||
|
||||
binfo.capacity = binfo.rows;
|
||||
blockDataEnsureCapacity(pBlock, binfo.rows);
|
||||
pBlock->info = binfo;
|
||||
|
||||
uint32_t status = 0;
|
||||
int32_t code = loadDataBlock(pOperator, pTableScanInfo, pBlock, &status);
|
||||
|
@ -530,7 +537,6 @@ SOperatorInfo* createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode,
|
|||
// taosSsleep(20);
|
||||
|
||||
SDataBlockDescNode* pDescNode = pTableScanNode->scan.node.pOutputDataBlockDesc;
|
||||
|
||||
int32_t numOfCols = 0;
|
||||
SArray* pColList = extractColMatchInfo(pTableScanNode->scan.pScanCols, pDescNode, &numOfCols, COL_MATCH_FROM_COL_ID);
|
||||
|
||||
|
|
|
@ -22,10 +22,11 @@ static int32_t getExplainExecInfo(SOperatorInfo* pOptr, void** pOptrExplain
|
|||
|
||||
static void destroyOrderOperatorInfo(void* param, int32_t numOfOutput);
|
||||
|
||||
SOperatorInfo* createSortOperatorInfo(SOperatorInfo* downstream, SSortPhysiNode* pSortPhyNode, SExecTaskInfo* pTaskInfo) {
|
||||
SOperatorInfo* createSortOperatorInfo(SOperatorInfo* downstream, SSortPhysiNode* pSortPhyNode,
|
||||
SExecTaskInfo* pTaskInfo) {
|
||||
SSortOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SSortOperatorInfo));
|
||||
SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
|
||||
if (pInfo == NULL || pOperator == NULL/* || rowSize > 100 * 1024 * 1024*/) {
|
||||
if (pInfo == NULL || pOperator == NULL /* || rowSize > 100 * 1024 * 1024*/) {
|
||||
goto _error;
|
||||
}
|
||||
|
||||
|
@ -44,16 +45,17 @@ SOperatorInfo* createSortOperatorInfo(SOperatorInfo* downstream, SSortPhysiNode*
|
|||
|
||||
initResultSizeInfo(pOperator, 1024);
|
||||
|
||||
pInfo->pSortInfo = createSortInfo(pSortPhyNode->pSortKeys);;
|
||||
pInfo->pColMatchInfo = pColMatchColInfo;
|
||||
pOperator->name = "SortOperator";
|
||||
pInfo->pSortInfo = createSortInfo(pSortPhyNode->pSortKeys);
|
||||
;
|
||||
pInfo->pColMatchInfo = pColMatchColInfo;
|
||||
pOperator->name = "SortOperator";
|
||||
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_SORT;
|
||||
pOperator->blocking = true;
|
||||
pOperator->status = OP_NOT_OPENED;
|
||||
pOperator->info = pInfo;
|
||||
pOperator->exprSupp.pExprInfo = pExprInfo;
|
||||
pOperator->exprSupp.numOfExprs = numOfCols;
|
||||
pOperator->pTaskInfo = pTaskInfo;
|
||||
pOperator->blocking = true;
|
||||
pOperator->status = OP_NOT_OPENED;
|
||||
pOperator->info = pInfo;
|
||||
pOperator->exprSupp.pExprInfo = pExprInfo;
|
||||
pOperator->exprSupp.numOfExprs = numOfCols;
|
||||
pOperator->pTaskInfo = pTaskInfo;
|
||||
|
||||
// lazy evaluation for the following parameter since the input datablock is not known till now.
|
||||
// pInfo->bufPageSize = rowSize < 1024 ? 1024 * 2 : rowSize * 2;
|
||||
|
@ -146,8 +148,8 @@ void applyScalarFunction(SSDataBlock* pBlock, void* param) {
|
|||
SOperatorInfo* pOperator = param;
|
||||
SSortOperatorInfo* pSort = pOperator->info;
|
||||
if (pOperator->exprSupp.pExprInfo != NULL) {
|
||||
int32_t code =
|
||||
projectApplyFunctions(pOperator->exprSupp.pExprInfo, pBlock, pBlock, pOperator->exprSupp.pCtx, pOperator->exprSupp.numOfExprs, NULL);
|
||||
int32_t code = projectApplyFunctions(pOperator->exprSupp.pExprInfo, pBlock, pBlock, pOperator->exprSupp.pCtx,
|
||||
pOperator->exprSupp.numOfExprs, NULL);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
longjmp(pOperator->pTaskInfo->env, code);
|
||||
}
|
||||
|
@ -165,8 +167,7 @@ int32_t doOpenSortOperator(SOperatorInfo* pOperator) {
|
|||
pInfo->startTs = taosGetTimestampUs();
|
||||
|
||||
// pInfo->binfo.pRes is not equalled to the input datablock.
|
||||
pInfo->pSortHandle = tsortCreateSortHandle(pInfo->pSortInfo, SORT_SINGLESOURCE_SORT, -1, -1,
|
||||
NULL, pTaskInfo->id.str);
|
||||
pInfo->pSortHandle = tsortCreateSortHandle(pInfo->pSortInfo, SORT_SINGLESOURCE_SORT, -1, -1, NULL, pTaskInfo->id.str);
|
||||
|
||||
tsortSetFetchRawDataFp(pInfo->pSortHandle, loadNextDataBlock, applyScalarFunction, pOperator);
|
||||
|
||||
|
@ -232,6 +233,265 @@ int32_t getExplainExecInfo(SOperatorInfo* pOptr, void** pOptrExplain, uint32_t*
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// Group Sort Operator
|
||||
typedef enum EChildOperatorStatus { CHILD_OP_NEW_GROUP, CHILD_OP_SAME_GROUP, CHILD_OP_FINISHED } EChildOperatorStatus;
|
||||
|
||||
typedef struct SGroupSortOperatorInfo {
|
||||
SOptrBasicInfo binfo;
|
||||
SArray* pSortInfo;
|
||||
SArray* pColMatchInfo;
|
||||
|
||||
int64_t startTs;
|
||||
uint64_t sortElapsed;
|
||||
bool hasGroupId;
|
||||
uint64_t currGroupId;
|
||||
|
||||
SSDataBlock* prefetchedSortInput;
|
||||
SSortHandle* pCurrSortHandle;
|
||||
EChildOperatorStatus childOpStatus;
|
||||
|
||||
SSortExecInfo sortExecInfo;
|
||||
} SGroupSortOperatorInfo;
|
||||
|
||||
SSDataBlock* getGroupSortedBlockData(SSortHandle* pHandle, SSDataBlock* pDataBlock, int32_t capacity,
|
||||
SArray* pColMatchInfo, SGroupSortOperatorInfo* pInfo) {
|
||||
blockDataCleanup(pDataBlock);
|
||||
|
||||
SSDataBlock* p = tsortGetSortedDataBlock(pHandle);
|
||||
if (p == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
blockDataEnsureCapacity(p, capacity);
|
||||
|
||||
while (1) {
|
||||
STupleHandle* pTupleHandle = tsortNextTuple(pHandle);
|
||||
if (pTupleHandle == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
appendOneRowToDataBlock(p, pTupleHandle);
|
||||
if (p->info.rows >= capacity) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (p->info.rows > 0) {
|
||||
int32_t numOfCols = taosArrayGetSize(pColMatchInfo);
|
||||
for (int32_t i = 0; i < numOfCols; ++i) {
|
||||
SColMatchInfo* pmInfo = taosArrayGet(pColMatchInfo, i);
|
||||
ASSERT(pmInfo->matchType == COL_MATCH_FROM_SLOT_ID);
|
||||
|
||||
SColumnInfoData* pSrc = taosArrayGet(p->pDataBlock, pmInfo->srcSlotId);
|
||||
SColumnInfoData* pDst = taosArrayGet(pDataBlock->pDataBlock, pmInfo->targetSlotId);
|
||||
colDataAssign(pDst, pSrc, p->info.rows);
|
||||
}
|
||||
|
||||
pDataBlock->info.rows = p->info.rows;
|
||||
pDataBlock->info.capacity = p->info.rows;
|
||||
}
|
||||
|
||||
blockDataDestroy(p);
|
||||
return (pDataBlock->info.rows > 0) ? pDataBlock : NULL;
|
||||
}
|
||||
|
||||
typedef struct SGroupSortSourceParam {
|
||||
SOperatorInfo* childOpInfo;
|
||||
SGroupSortOperatorInfo* grpSortOpInfo;
|
||||
} SGroupSortSourceParam;
|
||||
|
||||
SSDataBlock* fetchNextGroupSortDataBlock(void* param) {
|
||||
SGroupSortSourceParam* source = param;
|
||||
SGroupSortOperatorInfo* grpSortOpInfo = source->grpSortOpInfo;
|
||||
if (grpSortOpInfo->prefetchedSortInput) {
|
||||
SSDataBlock* block = grpSortOpInfo->prefetchedSortInput;
|
||||
grpSortOpInfo->prefetchedSortInput = NULL;
|
||||
return block;
|
||||
} else {
|
||||
SOperatorInfo* childOp = source->childOpInfo;
|
||||
SSDataBlock* block = childOp->fpSet.getNextFn(childOp);
|
||||
if (block != NULL) {
|
||||
if (block->info.groupId == grpSortOpInfo->currGroupId) {
|
||||
grpSortOpInfo->childOpStatus = CHILD_OP_SAME_GROUP;
|
||||
return block;
|
||||
} else {
|
||||
grpSortOpInfo->childOpStatus = CHILD_OP_NEW_GROUP;
|
||||
grpSortOpInfo->prefetchedSortInput = block;
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
grpSortOpInfo->childOpStatus = CHILD_OP_FINISHED;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t beginSortGroup(SOperatorInfo* pOperator) {
|
||||
SGroupSortOperatorInfo* pInfo = pOperator->info;
|
||||
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
|
||||
|
||||
// pInfo->binfo.pRes is not equalled to the input datablock.
|
||||
pInfo->pCurrSortHandle =
|
||||
tsortCreateSortHandle(pInfo->pSortInfo, SORT_SINGLESOURCE_SORT, -1, -1, NULL, pTaskInfo->id.str);
|
||||
|
||||
tsortSetFetchRawDataFp(pInfo->pCurrSortHandle, fetchNextGroupSortDataBlock, applyScalarFunction, pOperator);
|
||||
|
||||
SSortSource* ps = taosMemoryCalloc(1, sizeof(SSortSource));
|
||||
SGroupSortSourceParam* param = taosMemoryCalloc(1, sizeof(SGroupSortSourceParam));
|
||||
param->childOpInfo = pOperator->pDownstream[0];
|
||||
param->grpSortOpInfo = pInfo;
|
||||
ps->param = param;
|
||||
tsortAddSource(pInfo->pCurrSortHandle, ps);
|
||||
|
||||
int32_t code = tsortOpen(pInfo->pCurrSortHandle);
|
||||
taosMemoryFreeClear(ps);
|
||||
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
longjmp(pTaskInfo->env, terrno);
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t finishSortGroup(SOperatorInfo* pOperator) {
|
||||
SGroupSortOperatorInfo* pInfo = pOperator->info;
|
||||
|
||||
SSortExecInfo sortExecInfo = tsortGetSortExecInfo(pInfo->pCurrSortHandle);
|
||||
pInfo->sortExecInfo.sortMethod = sortExecInfo.sortMethod;
|
||||
pInfo->sortExecInfo.sortBuffer = sortExecInfo.sortBuffer;
|
||||
pInfo->sortExecInfo.loops += sortExecInfo.loops;
|
||||
pInfo->sortExecInfo.readBytes += sortExecInfo.readBytes;
|
||||
pInfo->sortExecInfo.writeBytes += sortExecInfo.writeBytes;
|
||||
if (pInfo->pCurrSortHandle != NULL) {
|
||||
tsortDestroySortHandle(pInfo->pCurrSortHandle);
|
||||
}
|
||||
pInfo->pCurrSortHandle = NULL;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
SSDataBlock* doGroupSort(SOperatorInfo* pOperator) {
|
||||
if (pOperator->status == OP_EXEC_DONE) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
|
||||
SGroupSortOperatorInfo* pInfo = pOperator->info;
|
||||
|
||||
int32_t code = pOperator->fpSet._openFn(pOperator);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
longjmp(pTaskInfo->env, code);
|
||||
}
|
||||
|
||||
if (!pInfo->hasGroupId) {
|
||||
pInfo->hasGroupId = true;
|
||||
|
||||
pInfo->prefetchedSortInput = pOperator->pDownstream[0]->fpSet.getNextFn(pOperator->pDownstream[0]);
|
||||
pInfo->currGroupId = pInfo->prefetchedSortInput->info.groupId;
|
||||
pInfo->childOpStatus = CHILD_OP_NEW_GROUP;
|
||||
beginSortGroup(pOperator);
|
||||
}
|
||||
|
||||
SSDataBlock* pBlock = NULL;
|
||||
while (pInfo->pCurrSortHandle != NULL) {
|
||||
// beginSortGroup would fetch all child blocks of pInfo->currGroupId;
|
||||
ASSERT(pInfo->childOpStatus != CHILD_OP_SAME_GROUP);
|
||||
pBlock = getGroupSortedBlockData(pInfo->pCurrSortHandle, pInfo->binfo.pRes, pOperator->resultInfo.capacity,
|
||||
pInfo->pColMatchInfo, pInfo);
|
||||
if (pBlock != NULL) {
|
||||
pBlock->info.groupId = pInfo->currGroupId;
|
||||
pOperator->resultInfo.totalRows += pBlock->info.rows;
|
||||
return pBlock;
|
||||
} else {
|
||||
if (pInfo->childOpStatus == CHILD_OP_NEW_GROUP) {
|
||||
finishSortGroup(pOperator);
|
||||
pInfo->currGroupId = pInfo->prefetchedSortInput->info.groupId;
|
||||
beginSortGroup(pOperator);
|
||||
} else if (pInfo->childOpStatus == CHILD_OP_FINISHED) {
|
||||
finishSortGroup(pOperator);
|
||||
doSetOperatorCompleted(pOperator);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32_t getGroupSortExplainExecInfo(SOperatorInfo* pOptr, void** pOptrExplain, uint32_t* len) {
|
||||
SGroupSortOperatorInfo* pInfo = (SGroupSortOperatorInfo*)pOptr->info;
|
||||
*pOptrExplain = &pInfo->sortExecInfo;
|
||||
*len = sizeof(SSortExecInfo);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
// TODO:
|
||||
SOperatorInfo* createGroupSortOperatorInfo(SOperatorInfo* downstream, SSortPhysiNode* pSortPhyNode,
|
||||
SExecTaskInfo* pTaskInfo) {
|
||||
SSortOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SSortOperatorInfo));
|
||||
SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
|
||||
if (pInfo == NULL || pOperator == NULL /* || rowSize > 100 * 1024 * 1024*/) {
|
||||
goto _error;
|
||||
}
|
||||
|
||||
SDataBlockDescNode* pDescNode = pSortPhyNode->node.pOutputDataBlockDesc;
|
||||
|
||||
int32_t numOfCols = 0;
|
||||
SSDataBlock* pResBlock = createResDataBlock(pDescNode);
|
||||
SExprInfo* pExprInfo = createExprInfo(pSortPhyNode->pExprs, NULL, &numOfCols);
|
||||
|
||||
int32_t numOfOutputCols = 0;
|
||||
SArray* pColMatchColInfo =
|
||||
extractColMatchInfo(pSortPhyNode->pTargets, pDescNode, &numOfOutputCols, COL_MATCH_FROM_SLOT_ID);
|
||||
|
||||
pOperator->exprSupp.pCtx = createSqlFunctionCtx(pExprInfo, numOfCols, &pOperator->exprSupp.rowEntryInfoOffset);
|
||||
pInfo->binfo.pRes = pResBlock;
|
||||
|
||||
initResultSizeInfo(pOperator, 1024);
|
||||
|
||||
pInfo->pSortInfo = createSortInfo(pSortPhyNode->pSortKeys);
|
||||
;
|
||||
pInfo->pColMatchInfo = pColMatchColInfo;
|
||||
pOperator->name = "GroupSortOperator";
|
||||
// TODO
|
||||
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_SORT;
|
||||
pOperator->blocking = true;
|
||||
pOperator->status = OP_NOT_OPENED;
|
||||
pOperator->info = pInfo;
|
||||
pOperator->exprSupp.pExprInfo = pExprInfo;
|
||||
pOperator->exprSupp.numOfExprs = numOfCols;
|
||||
pOperator->pTaskInfo = pTaskInfo;
|
||||
|
||||
pOperator->fpSet = createOperatorFpSet(operatorDummyOpenFn, doGroupSort, NULL, NULL, destroyOrderOperatorInfo, NULL,
|
||||
NULL, getGroupSortExplainExecInfo);
|
||||
|
||||
int32_t code = appendDownstream(pOperator, &downstream, 1);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _error;
|
||||
}
|
||||
|
||||
return pOperator;
|
||||
|
||||
_error:
|
||||
pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
taosMemoryFree(pInfo);
|
||||
taosMemoryFree(pOperator);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void destroyGroupSortOperatorInfo(void* param, int32_t numOfOutput) {
|
||||
SGroupSortOperatorInfo* pInfo = (SGroupSortOperatorInfo*)param;
|
||||
pInfo->binfo.pRes = blockDataDestroy(pInfo->binfo.pRes);
|
||||
|
||||
taosArrayDestroy(pInfo->pSortInfo);
|
||||
taosArrayDestroy(pInfo->pColMatchInfo);
|
||||
}
|
||||
|
||||
// TODO: sort group
|
||||
// TODO: msortCompare compare group id in multiway merge sort.
|
||||
// TODO: table merge scan, group first, then for each group, multiple readers
|
||||
|
||||
//=====================================================================================
|
||||
// Multiway Sort Merge operator
|
||||
typedef struct SMultiwaySortMergeOperatorInfo {
|
||||
SOptrBasicInfo binfo;
|
||||
|
||||
|
@ -259,11 +519,12 @@ int32_t doOpenMultiwaySortMergeOperator(SOperatorInfo* pOperator) {
|
|||
|
||||
int32_t numOfBufPage = pInfo->sortBufSize / pInfo->bufPageSize;
|
||||
|
||||
pInfo->pSortHandle = tsortCreateSortHandle(pInfo->pSortInfo, SORT_MULTISOURCE_MERGE,
|
||||
pInfo->bufPageSize, numOfBufPage, pInfo->pInputBlock, pTaskInfo->id.str);
|
||||
pInfo->pSortHandle = tsortCreateSortHandle(pInfo->pSortInfo, SORT_MULTISOURCE_MERGE, pInfo->bufPageSize, numOfBufPage,
|
||||
pInfo->pInputBlock, pTaskInfo->id.str);
|
||||
|
||||
tsortSetFetchRawDataFp(pInfo->pSortHandle, loadNextDataBlock, NULL, NULL);
|
||||
|
||||
tsortSetCompareGroupId(pInfo->pSortHandle, true);
|
||||
|
||||
for (int32_t i = 0; i < pOperator->numOfDownstream; ++i) {
|
||||
SSortSource* ps = taosMemoryCalloc(1, sizeof(SSortSource));
|
||||
ps->param = pOperator->pDownstream[i];
|
||||
|
@ -286,7 +547,7 @@ int32_t doOpenMultiwaySortMergeOperator(SOperatorInfo* pOperator) {
|
|||
SSDataBlock* getMultiwaySortedBlockData(SSortHandle* pHandle, SSDataBlock* pDataBlock, int32_t capacity,
|
||||
SArray* pColMatchInfo, SOperatorInfo* pOperator) {
|
||||
SMultiwaySortMergeOperatorInfo* pInfo = pOperator->info;
|
||||
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
|
||||
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
|
||||
|
||||
blockDataCleanup(pDataBlock);
|
||||
|
||||
|
@ -387,24 +648,23 @@ SOperatorInfo* createMultiwaySortMergeOperatorInfo(SOperatorInfo** downStreams,
|
|||
goto _error;
|
||||
}
|
||||
|
||||
|
||||
initResultSizeInfo(pOperator, 1024);
|
||||
|
||||
pInfo->binfo.pRes = pResBlock;
|
||||
pInfo->pSortInfo = pSortInfo;
|
||||
pInfo->binfo.pRes = pResBlock;
|
||||
pInfo->pSortInfo = pSortInfo;
|
||||
pInfo->pColMatchInfo = pColMatchColInfo;
|
||||
pInfo->pInputBlock = pInputBlock;
|
||||
pOperator->name = "MultiwaySortMerge";
|
||||
pInfo->pInputBlock = pInputBlock;
|
||||
pOperator->name = "MultiwaySortMerge";
|
||||
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_MERGE;
|
||||
pOperator->blocking = false;
|
||||
pOperator->status = OP_NOT_OPENED;
|
||||
pOperator->info = pInfo;
|
||||
pOperator->blocking = false;
|
||||
pOperator->status = OP_NOT_OPENED;
|
||||
pOperator->info = pInfo;
|
||||
pOperator->pTaskInfo = pTaskInfo;
|
||||
|
||||
pInfo->bufPageSize = getProperSortPageSize(rowSize);
|
||||
pInfo->bufPageSize = getProperSortPageSize(rowSize);
|
||||
|
||||
// one additional is reserved for merged result.
|
||||
pInfo->sortBufSize = pInfo->bufPageSize * (numStreams + 1);
|
||||
pInfo->sortBufSize = pInfo->bufPageSize * (numStreams + 1);
|
||||
|
||||
pOperator->fpSet =
|
||||
createOperatorFpSet(doOpenMultiwaySortMergeOperator, doMultiwaySortMerge, NULL, NULL,
|
||||
|
@ -421,4 +681,4 @@ _error:
|
|||
taosMemoryFree(pInfo);
|
||||
taosMemoryFree(pOperator);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -684,6 +684,7 @@ static void doInterpUnclosedTimeWindow(SOperatorInfo* pOperatorInfo, int32_t num
|
|||
}
|
||||
|
||||
void printDataBlock(SSDataBlock* pBlock, const char* flag) {
|
||||
if (pBlock == NULL) return;
|
||||
SArray* blocks = taosArrayInit(1, sizeof(SSDataBlock));
|
||||
taosArrayPush(blocks, pBlock);
|
||||
blockDebugShowData(blocks, flag);
|
||||
|
@ -1262,7 +1263,7 @@ static int32_t getAllIntervalWindow(SHashObj* pHashMap, SArray* resWins) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
bool isCloseWindow(STimeWindow *pWin, STimeWindowAggSupp* pSup) {
|
||||
bool isCloseWindow(STimeWindow* pWin, STimeWindowAggSupp* pSup) {
|
||||
ASSERT(pSup->maxTs == INT64_MIN || pSup->maxTs > 0);
|
||||
return pSup->maxTs != INT64_MIN && pWin->ekey < pSup->maxTs - pSup->waterMark;
|
||||
}
|
||||
|
@ -2402,7 +2403,7 @@ SOperatorInfo* createStreamFinalIntervalOperatorInfo(SOperatorInfo* downstream,
|
|||
initResultRowInfo(&pInfo->binfo.resultRowInfo);
|
||||
pInfo->pChildren = NULL;
|
||||
if (numOfChild > 0) {
|
||||
pInfo->pChildren = taosArrayInit(numOfChild, sizeof(void *));
|
||||
pInfo->pChildren = taosArrayInit(numOfChild, sizeof(void*));
|
||||
for (int32_t i = 0; i < numOfChild; i++) {
|
||||
SOperatorInfo* pChildOp = createStreamFinalIntervalOperatorInfo(NULL, pPhyNode, pTaskInfo, 0);
|
||||
if (pChildOp) {
|
||||
|
@ -3027,12 +3028,14 @@ static SSDataBlock* doStreamSessionAgg(SOperatorInfo* pOperator) {
|
|||
} else if (pOperator->status == OP_RES_TO_RETURN) {
|
||||
doBuildDeleteDataBlock(pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
|
||||
if (pInfo->pDelRes->info.rows > 0) {
|
||||
/*printDataBlock(pInfo->pDelRes, "session del");*/
|
||||
return pInfo->pDelRes;
|
||||
}
|
||||
doBuildResultDatablock(pOperator, pBInfo, &pInfo->groupResInfo, pInfo->streamAggSup.pResultBuf);
|
||||
if (pBInfo->pRes->info.rows == 0 || !hasDataInGroupInfo(&pInfo->groupResInfo)) {
|
||||
doSetOperatorCompleted(pOperator);
|
||||
}
|
||||
/*printDataBlock(pBInfo->pRes, "session insert");*/
|
||||
return pBInfo->pRes->info.rows == 0 ? NULL : pBInfo->pRes;
|
||||
}
|
||||
|
||||
|
@ -3100,9 +3103,11 @@ static SSDataBlock* doStreamSessionAgg(SOperatorInfo* pOperator) {
|
|||
blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
|
||||
doBuildDeleteDataBlock(pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
|
||||
if (pInfo->pDelRes->info.rows > 0) {
|
||||
/*printDataBlock(pInfo->pDelRes, "session del");*/
|
||||
return pInfo->pDelRes;
|
||||
}
|
||||
doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->streamAggSup.pResultBuf);
|
||||
/*printDataBlock(pBInfo->pRes, "session insert");*/
|
||||
return pBInfo->pRes->info.rows == 0 ? NULL : pBInfo->pRes;
|
||||
}
|
||||
|
||||
|
@ -3667,25 +3672,25 @@ _error:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
typedef struct SMergeIntervalAggOperatorInfo {
|
||||
typedef struct SMergeAlignedIntervalAggOperatorInfo {
|
||||
SIntervalAggOperatorInfo intervalAggOperatorInfo;
|
||||
|
||||
bool hasGroupId;
|
||||
uint64_t groupId;
|
||||
SSDataBlock* prefetchedBlock;
|
||||
bool inputBlocksFinished;
|
||||
} SMergeIntervalAggOperatorInfo;
|
||||
} SMergeAlignedIntervalAggOperatorInfo;
|
||||
|
||||
void destroyMergeIntervalOperatorInfo(void* param, int32_t numOfOutput) {
|
||||
SMergeIntervalAggOperatorInfo* miaInfo = (SMergeIntervalAggOperatorInfo*)param;
|
||||
void destroyMergeAlignedIntervalOperatorInfo(void* param, int32_t numOfOutput) {
|
||||
SMergeAlignedIntervalAggOperatorInfo* miaInfo = (SMergeAlignedIntervalAggOperatorInfo*)param;
|
||||
destroyIntervalOperatorInfo(&miaInfo->intervalAggOperatorInfo, numOfOutput);
|
||||
}
|
||||
|
||||
static int32_t outputMergeIntervalResult(SOperatorInfo* pOperatorInfo, uint64_t tableGroupId, SSDataBlock* pResultBlock,
|
||||
TSKEY wstartTs) {
|
||||
SMergeIntervalAggOperatorInfo* miaInfo = pOperatorInfo->info;
|
||||
SIntervalAggOperatorInfo* iaInfo = &miaInfo->intervalAggOperatorInfo;
|
||||
SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;
|
||||
static int32_t outputMergeAlignedIntervalResult(SOperatorInfo* pOperatorInfo, uint64_t tableGroupId,
|
||||
SSDataBlock* pResultBlock, TSKEY wstartTs) {
|
||||
SMergeAlignedIntervalAggOperatorInfo* miaInfo = pOperatorInfo->info;
|
||||
SIntervalAggOperatorInfo* iaInfo = &miaInfo->intervalAggOperatorInfo;
|
||||
SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;
|
||||
|
||||
SExprSupp* pSup = &pOperatorInfo->exprSupp;
|
||||
bool ascScan = (iaInfo->order == TSDB_ORDER_ASC);
|
||||
|
@ -3702,10 +3707,10 @@ static int32_t outputMergeIntervalResult(SOperatorInfo* pOperatorInfo, uint64_t
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void doMergeIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResultRowInfo, SSDataBlock* pBlock,
|
||||
int32_t scanFlag, SSDataBlock* pResultBlock) {
|
||||
SMergeIntervalAggOperatorInfo* miaInfo = pOperatorInfo->info;
|
||||
SIntervalAggOperatorInfo* iaInfo = &miaInfo->intervalAggOperatorInfo;
|
||||
static void doMergeAlignedIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResultRowInfo,
|
||||
SSDataBlock* pBlock, int32_t scanFlag, SSDataBlock* pResultBlock) {
|
||||
SMergeAlignedIntervalAggOperatorInfo* miaInfo = pOperatorInfo->info;
|
||||
SIntervalAggOperatorInfo* iaInfo = &miaInfo->intervalAggOperatorInfo;
|
||||
|
||||
SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;
|
||||
SExprSupp* pSup = &pOperatorInfo->exprSupp;
|
||||
|
@ -3722,7 +3727,7 @@ static void doMergeIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo*
|
|||
win.ekey =
|
||||
taosTimeAdd(win.skey, iaInfo->interval.interval, iaInfo->interval.intervalUnit, iaInfo->interval.precision) - 1;
|
||||
|
||||
// TODO: remove the hash table usage (groupid + winkey => result row position)
|
||||
// TODO: remove the hash table (groupid + winkey => result row position)
|
||||
int32_t ret = setTimeWindowOutputBuf(pResultRowInfo, &win, (scanFlag == MAIN_SCAN), &pResult, tableGroupId,
|
||||
pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset, &iaInfo->aggSup, pTaskInfo);
|
||||
if (ret != TSDB_CODE_SUCCESS || pResult == NULL) {
|
||||
|
@ -3744,7 +3749,7 @@ static void doMergeIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo*
|
|||
doApplyFunctions(pTaskInfo, pSup->pCtx, &currWin, &iaInfo->twAggSup.timeWindowData, startPos, currPos - startPos,
|
||||
tsCols, pBlock->info.rows, numOfOutput, iaInfo->order);
|
||||
|
||||
outputMergeIntervalResult(pOperatorInfo, tableGroupId, pResultBlock, currTs);
|
||||
outputMergeAlignedIntervalResult(pOperatorInfo, tableGroupId, pResultBlock, currTs);
|
||||
|
||||
currTs = tsCols[currPos];
|
||||
currWin.skey = currTs;
|
||||
|
@ -3763,14 +3768,14 @@ static void doMergeIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo*
|
|||
doApplyFunctions(pTaskInfo, pSup->pCtx, &currWin, &iaInfo->twAggSup.timeWindowData, startPos, currPos - startPos,
|
||||
tsCols, pBlock->info.rows, numOfOutput, iaInfo->order);
|
||||
|
||||
outputMergeIntervalResult(pOperatorInfo, tableGroupId, pResultBlock, currTs);
|
||||
outputMergeAlignedIntervalResult(pOperatorInfo, tableGroupId, pResultBlock, currTs);
|
||||
}
|
||||
|
||||
static SSDataBlock* doMergeIntervalAgg(SOperatorInfo* pOperator) {
|
||||
static SSDataBlock* doMergeAlignedIntervalAgg(SOperatorInfo* pOperator) {
|
||||
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
|
||||
|
||||
SMergeIntervalAggOperatorInfo* miaInfo = pOperator->info;
|
||||
SIntervalAggOperatorInfo* iaInfo = &miaInfo->intervalAggOperatorInfo;
|
||||
SMergeAlignedIntervalAggOperatorInfo* miaInfo = pOperator->info;
|
||||
SIntervalAggOperatorInfo* iaInfo = &miaInfo->intervalAggOperatorInfo;
|
||||
if (pOperator->status == OP_EXEC_DONE) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -3790,6 +3795,7 @@ static SSDataBlock* doMergeIntervalAgg(SOperatorInfo* pOperator) {
|
|||
} else {
|
||||
pBlock = miaInfo->prefetchedBlock;
|
||||
miaInfo->groupId = pBlock->info.groupId;
|
||||
miaInfo->prefetchedBlock = NULL;
|
||||
}
|
||||
|
||||
if (pBlock == NULL) {
|
||||
|
@ -3807,7 +3813,7 @@ static SSDataBlock* doMergeIntervalAgg(SOperatorInfo* pOperator) {
|
|||
|
||||
getTableScanInfo(pOperator, &iaInfo->order, &scanFlag);
|
||||
setInputDataBlock(pOperator, pSup->pCtx, pBlock, iaInfo->order, scanFlag, true);
|
||||
doMergeIntervalAggImpl(pOperator, &iaInfo->binfo.resultRowInfo, pBlock, scanFlag, pRes);
|
||||
doMergeAlignedIntervalAggImpl(pOperator, &iaInfo->binfo.resultRowInfo, pBlock, scanFlag, pRes);
|
||||
|
||||
if (pRes->info.rows >= pOperator->resultInfo.threshold) {
|
||||
break;
|
||||
|
@ -3826,11 +3832,11 @@ static SSDataBlock* doMergeIntervalAgg(SOperatorInfo* pOperator) {
|
|||
return (rows == 0) ? NULL : pRes;
|
||||
}
|
||||
|
||||
SOperatorInfo* createMergeIntervalOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExprInfo, int32_t numOfCols,
|
||||
SSDataBlock* pResBlock, SInterval* pInterval, int32_t primaryTsSlotId,
|
||||
SExecTaskInfo* pTaskInfo) {
|
||||
SMergeIntervalAggOperatorInfo* miaInfo = taosMemoryCalloc(1, sizeof(SMergeIntervalAggOperatorInfo));
|
||||
SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
|
||||
SOperatorInfo* createMergeAlignedIntervalOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExprInfo,
|
||||
int32_t numOfCols, SSDataBlock* pResBlock, SInterval* pInterval,
|
||||
int32_t primaryTsSlotId, SExecTaskInfo* pTaskInfo) {
|
||||
SMergeAlignedIntervalAggOperatorInfo* miaInfo = taosMemoryCalloc(1, sizeof(SMergeAlignedIntervalAggOperatorInfo));
|
||||
SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
|
||||
if (miaInfo == NULL || pOperator == NULL) {
|
||||
goto _error;
|
||||
}
|
||||
|
@ -3864,6 +3870,283 @@ SOperatorInfo* createMergeIntervalOperatorInfo(SOperatorInfo* downstream, SExprI
|
|||
|
||||
initResultRowInfo(&iaInfo->binfo.resultRowInfo);
|
||||
|
||||
pOperator->name = "TimeMergeAlignedIntervalAggOperator";
|
||||
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL;
|
||||
pOperator->blocking = false;
|
||||
pOperator->status = OP_NOT_OPENED;
|
||||
pOperator->exprSupp.pExprInfo = pExprInfo;
|
||||
pOperator->pTaskInfo = pTaskInfo;
|
||||
pOperator->exprSupp.numOfExprs = numOfCols;
|
||||
pOperator->info = miaInfo;
|
||||
|
||||
pOperator->fpSet = createOperatorFpSet(operatorDummyOpenFn, doMergeAlignedIntervalAgg, NULL, NULL,
|
||||
destroyMergeAlignedIntervalOperatorInfo, NULL, NULL, NULL);
|
||||
|
||||
code = appendDownstream(pOperator, &downstream, 1);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _error;
|
||||
}
|
||||
|
||||
return pOperator;
|
||||
|
||||
_error:
|
||||
destroyMergeAlignedIntervalOperatorInfo(miaInfo, numOfCols);
|
||||
taosMemoryFreeClear(miaInfo);
|
||||
taosMemoryFreeClear(pOperator);
|
||||
pTaskInfo->code = code;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//=====================================================================================================================
|
||||
// merge interval operator
|
||||
typedef struct SMergeIntervalAggOperatorInfo {
|
||||
SIntervalAggOperatorInfo intervalAggOperatorInfo;
|
||||
|
||||
SHashObj* groupIntervalHash;
|
||||
bool hasGroupId;
|
||||
uint64_t groupId;
|
||||
SSDataBlock* prefetchedBlock;
|
||||
bool inputBlocksFinished;
|
||||
} SMergeIntervalAggOperatorInfo;
|
||||
|
||||
void destroyMergeIntervalOperatorInfo(void* param, int32_t numOfOutput) {
|
||||
SMergeIntervalAggOperatorInfo* miaInfo = (SMergeIntervalAggOperatorInfo*)param;
|
||||
taosHashCleanup(miaInfo->groupIntervalHash);
|
||||
destroyIntervalOperatorInfo(&miaInfo->intervalAggOperatorInfo, numOfOutput);
|
||||
}
|
||||
|
||||
static int32_t outputPrevIntervalResult(SOperatorInfo* pOperatorInfo, uint64_t tableGroupId, SSDataBlock* pResultBlock,
|
||||
STimeWindow* newWin) {
|
||||
SMergeIntervalAggOperatorInfo* miaInfo = pOperatorInfo->info;
|
||||
SIntervalAggOperatorInfo* iaInfo = &miaInfo->intervalAggOperatorInfo;
|
||||
SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;
|
||||
bool ascScan = (iaInfo->order == TSDB_ORDER_ASC);
|
||||
SExprSupp* pExprSup = &pOperatorInfo->exprSupp;
|
||||
|
||||
STimeWindow* prevWin = taosHashGet(miaInfo->groupIntervalHash, &tableGroupId, sizeof(tableGroupId));
|
||||
if (prevWin == NULL) {
|
||||
taosHashPut(miaInfo->groupIntervalHash, &tableGroupId, sizeof(tableGroupId), newWin, sizeof(STimeWindow));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (newWin == NULL || (ascScan && newWin->skey > prevWin->ekey || (!ascScan) && newWin->skey < prevWin->ekey)) {
|
||||
SET_RES_WINDOW_KEY(iaInfo->aggSup.keyBuf, &prevWin->skey, TSDB_KEYSIZE, tableGroupId);
|
||||
SResultRowPosition* p1 = (SResultRowPosition*)taosHashGet(iaInfo->aggSup.pResultRowHashTable, iaInfo->aggSup.keyBuf,
|
||||
GET_RES_WINDOW_KEY_LEN(TSDB_KEYSIZE));
|
||||
ASSERT(p1 != NULL);
|
||||
|
||||
finalizeResultRowIntoResultDataBlock(iaInfo->aggSup.pResultBuf, p1, pExprSup->pCtx, pExprSup->pExprInfo,
|
||||
pExprSup->numOfExprs, pExprSup->rowEntryInfoOffset, pResultBlock, pTaskInfo);
|
||||
taosHashRemove(iaInfo->aggSup.pResultRowHashTable, iaInfo->aggSup.keyBuf, GET_RES_WINDOW_KEY_LEN(TSDB_KEYSIZE));
|
||||
if (newWin == NULL) {
|
||||
taosHashRemove(miaInfo->groupIntervalHash, &tableGroupId, sizeof(tableGroupId));
|
||||
} else {
|
||||
taosHashPut(miaInfo->groupIntervalHash, &tableGroupId, sizeof(tableGroupId), newWin, sizeof(STimeWindow));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void doMergeIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResultRowInfo, SSDataBlock* pBlock,
|
||||
int32_t scanFlag, SSDataBlock* pResultBlock) {
|
||||
SMergeIntervalAggOperatorInfo* miaInfo = pOperatorInfo->info;
|
||||
SIntervalAggOperatorInfo* iaInfo = &miaInfo->intervalAggOperatorInfo;
|
||||
|
||||
SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;
|
||||
SExprSupp* pExprSup = &pOperatorInfo->exprSupp;
|
||||
|
||||
int32_t startPos = 0;
|
||||
int32_t numOfOutput = pExprSup->numOfExprs;
|
||||
int64_t* tsCols = extractTsCol(pBlock, iaInfo);
|
||||
uint64_t tableGroupId = pBlock->info.groupId;
|
||||
bool ascScan = (iaInfo->order == TSDB_ORDER_ASC);
|
||||
TSKEY blockStartTs = getStartTsKey(&pBlock->info.window, tsCols);
|
||||
SResultRow* pResult = NULL;
|
||||
|
||||
STimeWindow win = getActiveTimeWindow(iaInfo->aggSup.pResultBuf, pResultRowInfo, blockStartTs, &iaInfo->interval,
|
||||
iaInfo->interval.precision, &iaInfo->win);
|
||||
|
||||
int32_t ret =
|
||||
setTimeWindowOutputBuf(pResultRowInfo, &win, (scanFlag == MAIN_SCAN), &pResult, tableGroupId, pExprSup->pCtx,
|
||||
numOfOutput, pExprSup->rowEntryInfoOffset, &iaInfo->aggSup, pTaskInfo);
|
||||
if (ret != TSDB_CODE_SUCCESS || pResult == NULL) {
|
||||
longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
TSKEY ekey = ascScan ? win.ekey : win.skey;
|
||||
int32_t forwardRows =
|
||||
getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, iaInfo->order);
|
||||
ASSERT(forwardRows > 0);
|
||||
|
||||
// prev time window not interpolation yet.
|
||||
if (iaInfo->timeWindowInterpo) {
|
||||
SResultRowPosition pos = addToOpenWindowList(pResultRowInfo, pResult);
|
||||
doInterpUnclosedTimeWindow(pOperatorInfo, numOfOutput, pResultRowInfo, pBlock, scanFlag, tsCols, &pos);
|
||||
|
||||
// restore current time window
|
||||
ret = setTimeWindowOutputBuf(pResultRowInfo, &win, (scanFlag == MAIN_SCAN), &pResult, tableGroupId, pExprSup->pCtx,
|
||||
numOfOutput, pExprSup->rowEntryInfoOffset, &iaInfo->aggSup, pTaskInfo);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
// window start key interpolation
|
||||
doWindowBorderInterpolation(iaInfo, pBlock, pResult, &win, startPos, forwardRows, pExprSup);
|
||||
}
|
||||
|
||||
updateTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &win, true);
|
||||
doApplyFunctions(pTaskInfo, pExprSup->pCtx, &win, &iaInfo->twAggSup.timeWindowData, startPos, forwardRows, tsCols,
|
||||
pBlock->info.rows, numOfOutput, iaInfo->order);
|
||||
doCloseWindow(pResultRowInfo, iaInfo, pResult);
|
||||
|
||||
// output previous interval results after this interval (&win) is closed
|
||||
outputPrevIntervalResult(pOperatorInfo, tableGroupId, pResultBlock, &win);
|
||||
|
||||
STimeWindow nextWin = win;
|
||||
while (1) {
|
||||
int32_t prevEndPos = forwardRows - 1 + startPos;
|
||||
startPos = getNextQualifiedWindow(&iaInfo->interval, &nextWin, &pBlock->info, tsCols, prevEndPos, iaInfo->order);
|
||||
if (startPos < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// null data, failed to allocate more memory buffer
|
||||
int32_t code =
|
||||
setTimeWindowOutputBuf(pResultRowInfo, &nextWin, (scanFlag == MAIN_SCAN), &pResult, tableGroupId,
|
||||
pExprSup->pCtx, numOfOutput, pExprSup->rowEntryInfoOffset, &iaInfo->aggSup, pTaskInfo);
|
||||
if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
|
||||
longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
ekey = ascScan ? nextWin.ekey : nextWin.skey;
|
||||
forwardRows =
|
||||
getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, iaInfo->order);
|
||||
|
||||
// window start(end) key interpolation
|
||||
doWindowBorderInterpolation(iaInfo, pBlock, pResult, &nextWin, startPos, forwardRows, pExprSup);
|
||||
|
||||
updateTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &nextWin, true);
|
||||
doApplyFunctions(pTaskInfo, pExprSup->pCtx, &nextWin, &iaInfo->twAggSup.timeWindowData, startPos, forwardRows,
|
||||
tsCols, pBlock->info.rows, numOfOutput, iaInfo->order);
|
||||
doCloseWindow(pResultRowInfo, iaInfo, pResult);
|
||||
|
||||
// output previous interval results after this interval (&nextWin) is closed
|
||||
outputPrevIntervalResult(pOperatorInfo, tableGroupId, pResultBlock, &nextWin);
|
||||
}
|
||||
|
||||
if (iaInfo->timeWindowInterpo) {
|
||||
saveDataBlockLastRow(iaInfo->pPrevValues, pBlock, iaInfo->pInterpCols);
|
||||
}
|
||||
}
|
||||
|
||||
static SSDataBlock* doMergeIntervalAgg(SOperatorInfo* pOperator) {
|
||||
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
|
||||
|
||||
SMergeIntervalAggOperatorInfo* miaInfo = pOperator->info;
|
||||
SIntervalAggOperatorInfo* iaInfo = &miaInfo->intervalAggOperatorInfo;
|
||||
SExprSupp* pExpSupp = &pOperator->exprSupp;
|
||||
|
||||
if (pOperator->status == OP_EXEC_DONE) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SSDataBlock* pRes = iaInfo->binfo.pRes;
|
||||
blockDataCleanup(pRes);
|
||||
blockDataEnsureCapacity(pRes, pOperator->resultInfo.capacity);
|
||||
|
||||
if (!miaInfo->inputBlocksFinished) {
|
||||
SOperatorInfo* downstream = pOperator->pDownstream[0];
|
||||
int32_t scanFlag = MAIN_SCAN;
|
||||
while (1) {
|
||||
SSDataBlock* pBlock = NULL;
|
||||
if (miaInfo->prefetchedBlock == NULL) {
|
||||
pBlock = downstream->fpSet.getNextFn(downstream);
|
||||
} else {
|
||||
pBlock = miaInfo->prefetchedBlock;
|
||||
miaInfo->groupId = pBlock->info.groupId;
|
||||
miaInfo->prefetchedBlock = NULL;
|
||||
}
|
||||
|
||||
if (pBlock == NULL) {
|
||||
miaInfo->inputBlocksFinished = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!miaInfo->hasGroupId) {
|
||||
miaInfo->hasGroupId = true;
|
||||
miaInfo->groupId = pBlock->info.groupId;
|
||||
} else if (miaInfo->groupId != pBlock->info.groupId) {
|
||||
miaInfo->prefetchedBlock = pBlock;
|
||||
break;
|
||||
}
|
||||
|
||||
getTableScanInfo(pOperator, &iaInfo->order, &scanFlag);
|
||||
setInputDataBlock(pOperator, pExpSupp->pCtx, pBlock, iaInfo->order, scanFlag, true);
|
||||
doMergeIntervalAggImpl(pOperator, &iaInfo->binfo.resultRowInfo, pBlock, scanFlag, pRes);
|
||||
|
||||
if (pRes->info.rows >= pOperator->resultInfo.threshold) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pRes->info.groupId = miaInfo->groupId;
|
||||
} else {
|
||||
void* p = taosHashIterate(miaInfo->groupIntervalHash, NULL);
|
||||
if (p != NULL) {
|
||||
size_t len = 0;
|
||||
uint64_t* pKey = taosHashGetKey(p, &len);
|
||||
outputPrevIntervalResult(pOperator, *pKey, pRes, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (pRes->info.rows == 0) {
|
||||
doSetOperatorCompleted(pOperator);
|
||||
}
|
||||
|
||||
size_t rows = pRes->info.rows;
|
||||
pOperator->resultInfo.totalRows += rows;
|
||||
return (rows == 0) ? NULL : pRes;
|
||||
}
|
||||
|
||||
SOperatorInfo* createMergeIntervalOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExprInfo, int32_t numOfCols,
|
||||
SSDataBlock* pResBlock, SInterval* pInterval, int32_t primaryTsSlotId,
|
||||
SExecTaskInfo* pTaskInfo) {
|
||||
SMergeIntervalAggOperatorInfo* miaInfo = taosMemoryCalloc(1, sizeof(SMergeIntervalAggOperatorInfo));
|
||||
SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
|
||||
if (miaInfo == NULL || pOperator == NULL) {
|
||||
goto _error;
|
||||
}
|
||||
|
||||
SIntervalAggOperatorInfo* iaInfo = &miaInfo->intervalAggOperatorInfo;
|
||||
|
||||
iaInfo->win = pTaskInfo->window;
|
||||
iaInfo->order = TSDB_ORDER_ASC;
|
||||
iaInfo->interval = *pInterval;
|
||||
iaInfo->execModel = pTaskInfo->execModel;
|
||||
|
||||
iaInfo->primaryTsIndex = primaryTsSlotId;
|
||||
|
||||
SExprSupp* pExprSupp = &pOperator->exprSupp;
|
||||
|
||||
size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
|
||||
initResultSizeInfo(pOperator, 4096);
|
||||
|
||||
int32_t code = initAggInfo(pExprSupp, &iaInfo->aggSup, pExprInfo, numOfCols, keyBufSize, pTaskInfo->id.str);
|
||||
initBasicInfo(&iaInfo->binfo, pResBlock);
|
||||
|
||||
initExecTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &iaInfo->win);
|
||||
|
||||
iaInfo->timeWindowInterpo = timeWindowinterpNeeded(pExprSupp->pCtx, numOfCols, iaInfo);
|
||||
if (iaInfo->timeWindowInterpo) {
|
||||
iaInfo->binfo.resultRowInfo.openWindow = tdListNew(sizeof(SResultRowPosition));
|
||||
if (iaInfo->binfo.resultRowInfo.openWindow == NULL) {
|
||||
goto _error;
|
||||
}
|
||||
}
|
||||
|
||||
initResultRowInfo(&iaInfo->binfo.resultRowInfo);
|
||||
|
||||
pOperator->name = "TimeMergeIntervalAggOperator";
|
||||
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL;
|
||||
pOperator->blocking = false;
|
||||
|
@ -3889,4 +4172,4 @@ _error:
|
|||
taosMemoryFreeClear(pOperator);
|
||||
pTaskInfo->code = code;
|
||||
return NULL;
|
||||
}
|
||||
}
|
|
@ -86,6 +86,7 @@ SSortHandle* tsortCreateSortHandle(SArray* pSortInfo, int32_t type, int32_t page
|
|||
|
||||
pSortHandle->pOrderedSource = taosArrayInit(4, POINTER_BYTES);
|
||||
pSortHandle->cmpParam.orderInfo = pSortInfo;
|
||||
pSortHandle->cmpParam.cmpGroupId = false;
|
||||
|
||||
tsortSetComparFp(pSortHandle, msortComparFn);
|
||||
|
||||
|
@ -374,6 +375,12 @@ int32_t msortComparFn(const void *pLeft, const void *pRight, void *param) {
|
|||
SSDataBlock* pLeftBlock = pLeftSource->src.pBlock;
|
||||
SSDataBlock* pRightBlock = pRightSource->src.pBlock;
|
||||
|
||||
if (pParam->cmpGroupId) {
|
||||
if (pLeftBlock->info.groupId != pRightBlock->info.groupId) {
|
||||
return pLeftBlock->info.groupId < pRightBlock->info.groupId ? -1 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
for(int32_t i = 0; i < pInfo->size; ++i) {
|
||||
SBlockOrderInfo* pOrder = TARRAY_GET_ELEM(pInfo, i);
|
||||
SColumnInfoData* pLeftColInfoData = TARRAY_GET_ELEM(pLeftBlock->pDataBlock, pOrder->slotId);
|
||||
|
@ -680,6 +687,11 @@ int32_t tsortSetComparFp(SSortHandle* pHandle, _sort_merge_compar_fn_t fp) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t tsortSetCompareGroupId(SSortHandle* pHandle, bool compareGroupId) {
|
||||
pHandle->cmpParam.cmpGroupId = compareGroupId;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
STupleHandle* tsortNextTuple(SSortHandle* pHandle) {
|
||||
if (pHandle->cmpParam.numOfSources == pHandle->numOfCompletedSources) {
|
||||
return NULL;
|
||||
|
|
|
@ -101,6 +101,11 @@ bool getDerivativeFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv);
|
|||
bool derivativeFuncSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResInfo);
|
||||
int32_t derivativeFunction(SqlFunctionCtx *pCtx);
|
||||
|
||||
bool getIrateFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv);
|
||||
bool irateFuncSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResInfo);
|
||||
int32_t irateFunction(SqlFunctionCtx *pCtx);
|
||||
int32_t irateFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock);
|
||||
|
||||
bool getFirstLastFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv);
|
||||
int32_t firstFunction(SqlFunctionCtx *pCtx);
|
||||
int32_t firstFunctionMerge(SqlFunctionCtx *pCtx);
|
||||
|
|
|
@ -978,6 +978,21 @@ static int32_t translateDerivative(SFunctionNode* pFunc, char* pErrBuf, int32_t
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t translateIrate(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||
if (1 != LIST_LENGTH(pFunc->pParameterList)) {
|
||||
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
|
||||
}
|
||||
|
||||
uint8_t colType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
|
||||
|
||||
if (!IS_NUMERIC_TYPE(colType)) {
|
||||
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||
}
|
||||
|
||||
pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes, .type = TSDB_DATA_TYPE_DOUBLE};
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t translateFirstLast(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||
// first(col_list) will be rewritten as first(col)
|
||||
if (1 != LIST_LENGTH(pFunc->pParameterList)) {
|
||||
|
@ -1796,6 +1811,16 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
.processFunc = derivativeFunction,
|
||||
.finalizeFunc = functionFinalize
|
||||
},
|
||||
{
|
||||
.name = "irate",
|
||||
.type = FUNCTION_TYPE_IRATE,
|
||||
.classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_TIMELINE_FUNC,
|
||||
.translateFunc = translateIrate,
|
||||
.getEnvFunc = getIrateFuncEnv,
|
||||
.initFunc = irateFuncSetup,
|
||||
.processFunc = irateFunction,
|
||||
.finalizeFunc = irateFinalize
|
||||
},
|
||||
{
|
||||
.name = "last_row",
|
||||
.type = FUNCTION_TYPE_LAST_ROW,
|
||||
|
|
|
@ -59,6 +59,12 @@ typedef struct STuplePos {
|
|||
int32_t offset;
|
||||
} STuplePos;
|
||||
|
||||
typedef struct SMinmaxResInfo {
|
||||
bool assign; // assign the first value or not
|
||||
int64_t v;
|
||||
STuplePos tuplePos;
|
||||
} SMinmaxResInfo;
|
||||
|
||||
typedef struct STopBotResItem {
|
||||
SVariant v;
|
||||
uint64_t uid; // it is a table uid, used to extract tag data during building of the final result for the tag data
|
||||
|
@ -148,6 +154,12 @@ typedef struct SElapsedInfo {
|
|||
int64_t timeUnit;
|
||||
} SElapsedInfo;
|
||||
|
||||
typedef struct STwaInfo {
|
||||
double dOutput;
|
||||
SPoint1 p;
|
||||
STimeWindow win;
|
||||
} STwaInfo;
|
||||
|
||||
typedef struct SHistoFuncBin {
|
||||
double lower;
|
||||
double upper;
|
||||
|
@ -234,6 +246,22 @@ typedef struct SUniqueInfo {
|
|||
char pItems[];
|
||||
} SUniqueInfo;
|
||||
|
||||
typedef struct SDerivInfo {
|
||||
double prevValue; // previous value
|
||||
TSKEY prevTs; // previous timestamp
|
||||
bool ignoreNegative; // ignore the negative value
|
||||
int64_t tsWindow; // time window for derivative
|
||||
bool valueSet; // the value has been set already
|
||||
} SDerivInfo;
|
||||
|
||||
typedef struct SRateInfo {
|
||||
double firstValue;
|
||||
TSKEY firstKey;
|
||||
double lastValue;
|
||||
TSKEY lastKey;
|
||||
int8_t hasResult; // flag to denote has value
|
||||
} SRateInfo;
|
||||
|
||||
#define SET_VAL(_info, numOfElem, res) \
|
||||
do { \
|
||||
if ((numOfElem) <= 0) { \
|
||||
|
@ -927,12 +955,6 @@ EFuncDataRequired statisDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWin
|
|||
return FUNC_DATA_REQUIRED_STATIS_LOAD;
|
||||
}
|
||||
|
||||
typedef struct SMinmaxResInfo {
|
||||
bool assign; // assign the first value or not
|
||||
int64_t v;
|
||||
STuplePos tuplePos;
|
||||
} SMinmaxResInfo;
|
||||
|
||||
bool minmaxFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
|
||||
if (!functionSetup(pCtx, pResultInfo)) {
|
||||
return false; // not initialized since it has been initialized
|
||||
|
@ -4665,12 +4687,6 @@ int32_t uniqueFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
|
|||
return pResInfo->numOfRes;
|
||||
}
|
||||
|
||||
typedef struct STwaInfo {
|
||||
double dOutput;
|
||||
SPoint1 p;
|
||||
STimeWindow win;
|
||||
} STwaInfo;
|
||||
|
||||
bool getTwaFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
|
||||
pEnv->calcMemSize = sizeof(STwaInfo);
|
||||
return true;
|
||||
|
@ -5119,14 +5135,6 @@ int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
typedef struct SDerivInfo {
|
||||
double prevValue; // previous value
|
||||
TSKEY prevTs; // previous timestamp
|
||||
bool ignoreNegative; // ignore the negative value
|
||||
int64_t tsWindow; // time window for derivative
|
||||
bool valueSet; // the value has been set already
|
||||
} SDerivInfo;
|
||||
|
||||
bool getDerivativeFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
|
||||
pEnv->calcMemSize = sizeof(SDerivInfo);
|
||||
return true;
|
||||
|
@ -5221,6 +5229,117 @@ int32_t derivativeFunction(SqlFunctionCtx* pCtx) {
|
|||
return numOfElems;
|
||||
}
|
||||
|
||||
bool getIrateFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
|
||||
pEnv->calcMemSize = sizeof(SRateInfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool irateFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
|
||||
if (!functionSetup(pCtx, pResInfo)) {
|
||||
return false; // not initialized since it has been initialized
|
||||
}
|
||||
|
||||
SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
|
||||
|
||||
pInfo->firstKey = INT64_MIN;
|
||||
pInfo->lastKey = INT64_MIN;
|
||||
pInfo->firstValue = (double)INT64_MIN;
|
||||
pInfo->lastValue = (double)INT64_MIN;
|
||||
|
||||
pInfo->hasResult = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t irateFunction(SqlFunctionCtx* pCtx) {
|
||||
SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
|
||||
SRateInfo* pRateInfo = GET_ROWCELL_INTERBUF(pResInfo);
|
||||
|
||||
SInputColumnInfoData* pInput = &pCtx->input;
|
||||
SColumnInfoData* pInputCol = pInput->pData[0];
|
||||
|
||||
SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
|
||||
|
||||
TSKEY* tsList = (int64_t*)pInput->pPTS->pData;
|
||||
|
||||
int32_t numOfElems = 0;
|
||||
int32_t type = pInputCol->info.type;
|
||||
|
||||
for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
|
||||
if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
numOfElems++;
|
||||
|
||||
char* data = colDataGetData(pInputCol, i);
|
||||
double v = 0;
|
||||
GET_TYPED_DATA(v, double, type, data);
|
||||
|
||||
if (INT64_MIN == pRateInfo->lastKey) {
|
||||
pRateInfo->lastValue = v;
|
||||
pRateInfo->lastKey = tsList[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tsList[i] > pRateInfo->lastKey) {
|
||||
if ((INT64_MIN == pRateInfo->firstKey) || pRateInfo->lastKey > pRateInfo->firstKey) {
|
||||
pRateInfo->firstValue = pRateInfo->lastValue;
|
||||
pRateInfo->firstKey = pRateInfo->lastKey;
|
||||
}
|
||||
|
||||
pRateInfo->lastValue = v;
|
||||
pRateInfo->lastKey = tsList[i];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((INT64_MIN == pRateInfo->firstKey) || tsList[i] > pRateInfo->firstKey) {
|
||||
pRateInfo->firstValue = v;
|
||||
pRateInfo->firstKey = tsList[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SET_VAL(pResInfo, numOfElems, 1);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static double doCalcRate(const SRateInfo* pRateInfo, double tickPerSec) {
|
||||
if ((INT64_MIN == pRateInfo->lastKey) || (INT64_MIN == pRateInfo->firstKey) ||
|
||||
(pRateInfo->firstKey >= pRateInfo->lastKey)) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double diff = 0;
|
||||
// If the previous value of the last is greater than the last value, only keep the last point instead of the delta
|
||||
// value between two values.
|
||||
diff = pRateInfo->lastValue;
|
||||
if (diff >= pRateInfo->firstValue) {
|
||||
diff -= pRateInfo->firstValue;
|
||||
}
|
||||
|
||||
int64_t duration = pRateInfo->lastKey - pRateInfo->firstKey;
|
||||
if (duration == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (duration > 0)? ((double)diff) / (duration/tickPerSec):0.0;
|
||||
}
|
||||
|
||||
int32_t irateFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
|
||||
int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
|
||||
SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
|
||||
|
||||
SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
|
||||
pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
|
||||
|
||||
SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
|
||||
double result = doCalcRate(pInfo, 1000);
|
||||
colDataAppend(pCol, pBlock->info.rows, (const char*)&result, pResInfo->isNullRes);
|
||||
|
||||
return pResInfo->numOfRes;
|
||||
}
|
||||
|
||||
int32_t interpFunction(SqlFunctionCtx* pCtx) {
|
||||
#if 0
|
||||
int32_t fillType = (int32_t) pCtx->param[2].i64;
|
||||
|
|
|
@ -186,6 +186,13 @@ bool fmIsInterpFunc(int32_t funcId) {
|
|||
return FUNCTION_TYPE_INTERP == funcMgtBuiltins[funcId].type;
|
||||
}
|
||||
|
||||
bool fmIsLastRowFunc(int32_t funcId) {
|
||||
if (funcId < 0 || funcId >= funcMgtBuiltinsNum) {
|
||||
return false;
|
||||
}
|
||||
return FUNCTION_TYPE_LAST_ROW == funcMgtBuiltins[funcId].type;
|
||||
}
|
||||
|
||||
void fmFuncMgtDestroy() {
|
||||
void* m = gFunMgtService.pFuncNameHashTable;
|
||||
if (m != NULL && atomic_val_compare_exchange_ptr((void**)&gFunMgtService.pFuncNameHashTable, m, 0) == m) {
|
||||
|
|
|
@ -702,7 +702,7 @@ SNode* nodesCloneNode(const SNode* pNode) {
|
|||
case QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN:
|
||||
return physiSysTableScanCopy((const SSystemTableScanPhysiNode*)pNode, (SSystemTableScanPhysiNode*)pDst);
|
||||
case QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL:
|
||||
|
|
|
@ -220,6 +220,8 @@ const char* nodesNodeName(ENodeType type) {
|
|||
return "PhysiSystemTableScan";
|
||||
case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN:
|
||||
return "PhysiBlockDistScan";
|
||||
case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN:
|
||||
return "PhysiLastRowScan";
|
||||
case QUERY_NODE_PHYSICAL_PLAN_PROJECT:
|
||||
return "PhysiProject";
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN:
|
||||
|
@ -234,8 +236,8 @@ const char* nodesNodeName(ENodeType type) {
|
|||
return "PhysiSort";
|
||||
case QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL:
|
||||
return "PhysiHashInterval";
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL:
|
||||
return "PhysiMergeInterval";
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL:
|
||||
return "PhysiMergeAlignedInterval";
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL:
|
||||
return "PhysiStreamInterval";
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL:
|
||||
|
@ -4105,6 +4107,7 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
|
|||
return logicPlanToJson(pObj, pJson);
|
||||
case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN:
|
||||
return physiTagScanNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN:
|
||||
|
@ -4125,7 +4128,7 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
|
|||
case QUERY_NODE_PHYSICAL_PLAN_SORT:
|
||||
return physiSortNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL:
|
||||
|
@ -4245,6 +4248,7 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) {
|
|||
return jsonToLogicPlan(pJson, pObj);
|
||||
case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN:
|
||||
return jsonToPhysiTagScanNode(pJson, pObj);
|
||||
case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN:
|
||||
|
@ -4265,7 +4269,7 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) {
|
|||
case QUERY_NODE_PHYSICAL_PLAN_SORT:
|
||||
return jsonToPhysiSortNode(pJson, pObj);
|
||||
case QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL:
|
||||
|
|
|
@ -273,6 +273,8 @@ SNode* nodesMakeNode(ENodeType type) {
|
|||
return makeNode(type, sizeof(SSystemTableScanPhysiNode));
|
||||
case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN:
|
||||
return makeNode(type, sizeof(SBlockDistScanPhysiNode));
|
||||
case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN:
|
||||
return makeNode(type, sizeof(SLastRowScanPhysiNode));
|
||||
case QUERY_NODE_PHYSICAL_PLAN_PROJECT:
|
||||
return makeNode(type, sizeof(SProjectPhysiNode));
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN:
|
||||
|
@ -287,8 +289,8 @@ SNode* nodesMakeNode(ENodeType type) {
|
|||
return makeNode(type, sizeof(SSortPhysiNode));
|
||||
case QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL:
|
||||
return makeNode(type, sizeof(SIntervalPhysiNode));
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL:
|
||||
return makeNode(type, sizeof(SMergeIntervalPhysiNode));
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL:
|
||||
return makeNode(type, sizeof(SMergeAlignedIntervalPhysiNode));
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL:
|
||||
return makeNode(type, sizeof(SStreamIntervalPhysiNode));
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL:
|
||||
|
@ -781,6 +783,7 @@ void nodesDestroyNode(SNode* pNode) {
|
|||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN:
|
||||
destroyScanPhysiNode((SScanPhysiNode*)pNode);
|
||||
break;
|
||||
case QUERY_NODE_PHYSICAL_PLAN_PROJECT: {
|
||||
|
@ -825,7 +828,7 @@ void nodesDestroyNode(SNode* pNode) {
|
|||
break;
|
||||
}
|
||||
case QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL:
|
||||
|
|
|
@ -757,8 +757,9 @@ boolean_primary(A) ::= NK_LP(C) boolean_value_expression(B) NK_RP(D).
|
|||
common_expression(A) ::= expression(B). { A = B; }
|
||||
common_expression(A) ::= boolean_value_expression(B). { A = B; }
|
||||
|
||||
/************************************************ from_clause *********************************************************/
|
||||
from_clause(A) ::= FROM table_reference_list(B). { A = B; }
|
||||
/************************************************ from_clause_opt *********************************************************/
|
||||
from_clause_opt(A) ::= . { A = NULL; }
|
||||
from_clause_opt(A) ::= FROM table_reference_list(B). { A = B; }
|
||||
|
||||
table_reference_list(A) ::= table_reference(B). { A = B; }
|
||||
table_reference_list(A) ::= table_reference_list(B) NK_COMMA table_reference(C). { A = createJoinTableNode(pCxt, JOIN_TYPE_INNER, B, C, NULL); }
|
||||
|
@ -792,9 +793,9 @@ join_type(A) ::= INNER.
|
|||
|
||||
/************************************************ query_specification *************************************************/
|
||||
query_specification(A) ::=
|
||||
SELECT set_quantifier_opt(B) select_list(C) from_clause(D) where_clause_opt(E)
|
||||
partition_by_clause_opt(F) range_opt(J) every_opt(K) fill_opt(L) twindow_clause_opt(G)
|
||||
group_by_clause_opt(H) having_clause_opt(I). {
|
||||
SELECT set_quantifier_opt(B) select_list(C) from_clause_opt(D)
|
||||
where_clause_opt(E) partition_by_clause_opt(F) range_opt(J) every_opt(K)
|
||||
fill_opt(L) twindow_clause_opt(G) group_by_clause_opt(H) having_clause_opt(I). {
|
||||
A = createSelectStmt(pCxt, B, C, D);
|
||||
A = addWhereClause(pCxt, A, E);
|
||||
A = addPartitionByClause(pCxt, A, F);
|
||||
|
|
|
@ -227,12 +227,16 @@ static int32_t calcConstGroupBy(SCalcConstContext* pCxt, SSelectStmt* pSelect) {
|
|||
}
|
||||
}
|
||||
}
|
||||
DESTORY_LIST(pSelect->pGroupByList);
|
||||
NODES_DESTORY_LIST(pSelect->pGroupByList);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t calcConstSelect(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
|
||||
static int32_t calcConstSelectWithoutFrom(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
|
||||
return calcConstProjections(pCxt, pSelect, subquery);
|
||||
}
|
||||
|
||||
static int32_t calcConstSelectFrom(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
|
||||
int32_t code = calcConstFromTable(pCxt, pSelect->pFromTable);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = calcConstProjections(pCxt, pSelect, subquery);
|
||||
|
@ -258,6 +262,14 @@ static int32_t calcConstSelect(SCalcConstContext* pCxt, SSelectStmt* pSelect, bo
|
|||
return code;
|
||||
}
|
||||
|
||||
static int32_t calcConstSelect(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
|
||||
if (NULL == pSelect->pFromTable) {
|
||||
return calcConstSelectWithoutFrom(pCxt, pSelect, subquery);
|
||||
} else {
|
||||
return calcConstSelectFrom(pCxt, pSelect, subquery);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t calcConstDelete(SCalcConstContext* pCxt, SDeleteStmt* pDelete) {
|
||||
int32_t code = calcConstFromTable(pCxt, pDelete->pFromTable);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
|
|
|
@ -689,6 +689,10 @@ static EDealRes translateColumnUseAlias(STranslateContext* pCxt, SColumnNode** p
|
|||
}
|
||||
|
||||
static EDealRes translateColumn(STranslateContext* pCxt, SColumnNode** pCol) {
|
||||
if (NULL != pCxt->pCurrSelectStmt && NULL == pCxt->pCurrSelectStmt->pFromTable) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_INVALID_COLUMN, (*pCol)->colName);
|
||||
}
|
||||
|
||||
// count(*)/first(*)/last(*) and so on
|
||||
if (0 == strcmp((*pCol)->colName, "*")) {
|
||||
return DEAL_RES_CONTINUE;
|
||||
|
@ -1200,6 +1204,7 @@ static void setFuncClassification(SSelectStmt* pSelect, SFunctionNode* pFunc) {
|
|||
pSelect->hasUniqueFunc = pSelect->hasUniqueFunc ? true : (FUNCTION_TYPE_UNIQUE == pFunc->funcType);
|
||||
pSelect->hasTailFunc = pSelect->hasTailFunc ? true : (FUNCTION_TYPE_TAIL == pFunc->funcType);
|
||||
pSelect->hasInterpFunc = pSelect->hasInterpFunc ? true : (FUNCTION_TYPE_INTERP == pFunc->funcType);
|
||||
pSelect->hasLastRowFunc = pSelect->hasLastRowFunc ? true : (FUNCTION_TYPE_LAST_ROW == pFunc->funcType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2489,7 +2494,13 @@ static int32_t replaceOrderByAlias(STranslateContext* pCxt, SNodeList* pProjecti
|
|||
return pCxt->errCode;
|
||||
}
|
||||
|
||||
static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
static int32_t translateSelectWithoutFrom(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
pCxt->pCurrSelectStmt = pSelect;
|
||||
pCxt->currClause = SQL_CLAUSE_SELECT;
|
||||
return translateExprList(pCxt, pSelect->pProjectionList);
|
||||
}
|
||||
|
||||
static int32_t translateSelectFrom(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
pCxt->pCurrSelectStmt = pSelect;
|
||||
int32_t code = translateFrom(pCxt, pSelect->pFromTable);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
|
@ -2538,6 +2549,14 @@ static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
|||
return code;
|
||||
}
|
||||
|
||||
static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
if (NULL == pSelect->pFromTable) {
|
||||
return translateSelectWithoutFrom(pCxt, pSelect);
|
||||
} else {
|
||||
return translateSelectFrom(pCxt, pSelect);
|
||||
}
|
||||
}
|
||||
|
||||
static SNode* createSetOperProject(const char* pTableAlias, SNode* pNode) {
|
||||
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
|
||||
if (NULL == pCol) {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -388,4 +388,10 @@ TEST_F(ParserSelectTest, informationSchema) {
|
|||
run("SELECT * FROM information_schema.user_databases WHERE name = 'information_schema'");
|
||||
}
|
||||
|
||||
TEST_F(ParserSelectTest, withoutFrom) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("SELECT 1");
|
||||
}
|
||||
|
||||
} // namespace ParserTest
|
||||
|
|
|
@ -296,6 +296,59 @@ static int32_t createScanLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect
|
|||
return code;
|
||||
}
|
||||
|
||||
static int32_t createColumnByLastRow(SNodeList* pFuncs, SNodeList** pOutput) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
SNodeList* pCols = NULL;
|
||||
SNode* pFunc = NULL;
|
||||
FOREACH(pFunc, pFuncs) {
|
||||
SFunctionNode* pLastRow = (SFunctionNode*)pFunc;
|
||||
SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pLastRow->pParameterList, 0);
|
||||
snprintf(pCol->colName, sizeof(pCol->colName), "%s", pLastRow->node.aliasName);
|
||||
snprintf(pCol->node.aliasName, sizeof(pCol->colName), "%s", pLastRow->node.aliasName);
|
||||
NODES_CLEAR_LIST(pLastRow->pParameterList);
|
||||
code = nodesListMakeStrictAppend(&pCols, (SNode*)pCol);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
*pOutput = pCols;
|
||||
} else {
|
||||
nodesDestroyList(pCols);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t createLastRowScanLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SRealTableNode* pRealTable,
|
||||
SLogicNode** pLogicNode) {
|
||||
SScanLogicNode* pScan = NULL;
|
||||
int32_t code = makeScanLogicNode(pCxt, pRealTable, false, (SLogicNode**)&pScan);
|
||||
|
||||
SNodeList* pFuncs = NULL;
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
pScan->scanType = SCAN_TYPE_LAST_ROW;
|
||||
code = nodesCollectFuncs(pSelect, SQL_CLAUSE_FROM, fmIsLastRowFunc, &pFuncs);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = rewriteExprsForSelect(pFuncs, pSelect, SQL_CLAUSE_FROM);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = createColumnByLastRow(pFuncs, &pScan->pScanCols);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = createColumnByRewriteExprs(pScan->pScanCols, &pScan->node.pTargets);
|
||||
}
|
||||
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
*pLogicNode = (SLogicNode*)pScan;
|
||||
} else {
|
||||
nodesDestroyNode((SNode*)pScan);
|
||||
}
|
||||
nodesDestroyList(pFuncs);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t createSubqueryLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, STempTableNode* pTable,
|
||||
SLogicNode** pLogicNode) {
|
||||
return createQueryLogicNode(pCxt, pTable->pSubquery, pLogicNode);
|
||||
|
@ -367,7 +420,11 @@ static int32_t doCreateLogicNodeByTable(SLogicPlanContext* pCxt, SSelectStmt* pS
|
|||
SLogicNode** pLogicNode) {
|
||||
switch (nodeType(pTable)) {
|
||||
case QUERY_NODE_REAL_TABLE:
|
||||
return createScanLogicNode(pCxt, pSelect, (SRealTableNode*)pTable, pLogicNode);
|
||||
if (pSelect->hasLastRowFunc) {
|
||||
return createLastRowScanLogicNode(pCxt, pSelect, (SRealTableNode*)pTable, pLogicNode);
|
||||
} else {
|
||||
return createScanLogicNode(pCxt, pSelect, (SRealTableNode*)pTable, pLogicNode);
|
||||
}
|
||||
case QUERY_NODE_TEMP_TABLE:
|
||||
return createSubqueryLogicNode(pCxt, pSelect, (STempTableNode*)pTable, pLogicNode);
|
||||
case QUERY_NODE_JOIN_TABLE:
|
||||
|
@ -844,7 +901,12 @@ static int32_t createDistinctLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSe
|
|||
return code;
|
||||
}
|
||||
|
||||
static int32_t createSelectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
|
||||
static int32_t createSelectWithoutFromLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect,
|
||||
SLogicNode** pLogicNode) {
|
||||
return createProjectLogicNode(pCxt, pSelect, pLogicNode);
|
||||
}
|
||||
|
||||
static int32_t createSelectFromLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
|
||||
SLogicNode* pRoot = NULL;
|
||||
int32_t code = createLogicNodeByTable(pCxt, pSelect, pSelect->pFromTable, &pRoot);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
|
@ -884,6 +946,14 @@ static int32_t createSelectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSele
|
|||
return code;
|
||||
}
|
||||
|
||||
static int32_t createSelectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
|
||||
if (NULL == pSelect->pFromTable) {
|
||||
return createSelectWithoutFromLogicNode(pCxt, pSelect, pLogicNode);
|
||||
} else {
|
||||
return createSelectFromLogicNode(pCxt, pSelect, pLogicNode);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t createSetOpRootLogicNode(SLogicPlanContext* pCxt, SSetOperator* pSetOperator, FCreateSetOpLogicNode func,
|
||||
SLogicNode** pRoot) {
|
||||
return createRootLogicNode(pCxt, pSetOperator, pSetOperator->precision, (FCreateLogicNode)func, pRoot);
|
||||
|
|
|
@ -293,16 +293,22 @@ static int32_t cpdCondAppend(SNode** pCond, SNode** pAdditionalCond) {
|
|||
return code;
|
||||
}
|
||||
|
||||
static int32_t cpdCalcTimeRange(SScanLogicNode* pScan, SNode** pPrimaryKeyCond, SNode** pOtherCond) {
|
||||
bool isStrict = false;
|
||||
int32_t code = filterGetTimeRange(*pPrimaryKeyCond, &pScan->scanRange, &isStrict);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
if (isStrict) {
|
||||
nodesDestroyNode(*pPrimaryKeyCond);
|
||||
} else {
|
||||
code = cpdCondAppend(pOtherCond, pPrimaryKeyCond);
|
||||
static int32_t cpdCalcTimeRange(SOptimizeContext* pCxt, SScanLogicNode* pScan, SNode** pPrimaryKeyCond,
|
||||
SNode** pOtherCond) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
if (pCxt->pPlanCxt->topicQuery || pCxt->pPlanCxt->streamQuery) {
|
||||
code = cpdCondAppend(pOtherCond, pPrimaryKeyCond);
|
||||
} else {
|
||||
bool isStrict = false;
|
||||
code = filterGetTimeRange(*pPrimaryKeyCond, &pScan->scanRange, &isStrict);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
if (isStrict) {
|
||||
nodesDestroyNode(*pPrimaryKeyCond);
|
||||
} else {
|
||||
code = cpdCondAppend(pOtherCond, pPrimaryKeyCond);
|
||||
}
|
||||
*pPrimaryKeyCond = NULL;
|
||||
}
|
||||
*pPrimaryKeyCond = NULL;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
@ -344,7 +350,7 @@ static int32_t cpdOptimizeScanCondition(SOptimizeContext* pCxt, SScanLogicNode*
|
|||
SNode* pOtherCond = NULL;
|
||||
int32_t code = nodesPartitionCond(&pScan->node.pConditions, &pPrimaryKeyCond, &pTagCond, &pOtherCond);
|
||||
if (TSDB_CODE_SUCCESS == code && NULL != pPrimaryKeyCond) {
|
||||
code = cpdCalcTimeRange(pScan, &pPrimaryKeyCond, &pOtherCond);
|
||||
code = cpdCalcTimeRange(pCxt, pScan, &pPrimaryKeyCond, &pOtherCond);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code && NULL != pTagCond) {
|
||||
code = cpdApplyTagIndex(pScan, &pTagCond, &pOtherCond);
|
||||
|
@ -1126,7 +1132,7 @@ static int32_t partTagsOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSub
|
|||
break;
|
||||
}
|
||||
}
|
||||
DESTORY_LIST(((SAggLogicNode*)pNode)->pGroupKeys);
|
||||
NODES_DESTORY_LIST(((SAggLogicNode*)pNode)->pGroupKeys);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = partTagsOptRebuildTbanme(pScan->pPartTags);
|
||||
|
|
|
@ -462,6 +462,8 @@ static ENodeType getScanOperatorType(EScanType scanType) {
|
|||
return QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN;
|
||||
case SCAN_TYPE_BLOCK_INFO:
|
||||
return QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN;
|
||||
case SCAN_TYPE_LAST_ROW:
|
||||
return QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -559,6 +561,7 @@ static int32_t createScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan* pSubplan,
|
|||
switch (pScanLogicNode->scanType) {
|
||||
case SCAN_TYPE_TAG:
|
||||
case SCAN_TYPE_BLOCK_INFO:
|
||||
case SCAN_TYPE_LAST_ROW:
|
||||
return createSimpleScanPhysiNode(pCxt, pSubplan, pScanLogicNode, pPhyNode);
|
||||
case SCAN_TYPE_TABLE:
|
||||
return createTableScanPhysiNode(pCxt, pSubplan, pScanLogicNode, pPhyNode);
|
||||
|
@ -732,7 +735,7 @@ static int32_t rewritePrecalcExprs(SPhysiPlanContext* pCxt, SNodeList* pList, SN
|
|||
SRewritePrecalcExprsCxt cxt = {.errCode = TSDB_CODE_SUCCESS, .pPrecalcExprs = *pPrecalcExprs};
|
||||
nodesRewriteExprs(*pRewrittenList, doRewritePrecalcExprs, &cxt);
|
||||
if (0 == LIST_LENGTH(cxt.pPrecalcExprs) || TSDB_CODE_SUCCESS != cxt.errCode) {
|
||||
DESTORY_LIST(*pPrecalcExprs);
|
||||
NODES_DESTORY_LIST(*pPrecalcExprs);
|
||||
}
|
||||
return cxt.errCode;
|
||||
}
|
||||
|
@ -914,8 +917,16 @@ static int32_t createProjectPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChild
|
|||
pProject->slimit = pProjectLogicNode->slimit;
|
||||
pProject->soffset = pProjectLogicNode->soffset;
|
||||
|
||||
int32_t code = setListSlotId(pCxt, ((SPhysiNode*)nodesListGetNode(pChildren, 0))->pOutputDataBlockDesc->dataBlockId,
|
||||
-1, pProjectLogicNode->pProjections, &pProject->pProjections);
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
if (0 == LIST_LENGTH(pChildren)) {
|
||||
pProject->pProjections = nodesCloneList(pProjectLogicNode->pProjections);
|
||||
if (NULL == pProject->pProjections) {
|
||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
} else {
|
||||
code = setListSlotId(pCxt, ((SPhysiNode*)nodesListGetNode(pChildren, 0))->pOutputDataBlockDesc->dataBlockId, -1,
|
||||
pProjectLogicNode->pProjections, &pProject->pProjections);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = addDataBlockSlotsForProject(pCxt, pProjectLogicNode->stmtName, pProject->pProjections,
|
||||
pProject->node.pOutputDataBlockDesc);
|
||||
|
@ -1038,7 +1049,7 @@ static ENodeType getIntervalOperatorType(EWindowAlgorithm windowAlgo) {
|
|||
case INTERVAL_ALGO_HASH:
|
||||
return QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL;
|
||||
case INTERVAL_ALGO_MERGE:
|
||||
return QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL;
|
||||
return QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL;
|
||||
case INTERVAL_ALGO_STREAM_FINAL:
|
||||
return QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL;
|
||||
case INTERVAL_ALGO_STREAM_SEMI:
|
||||
|
|
|
@ -934,7 +934,7 @@ static int32_t unionSplitSubplan(SSplitContext* pCxt, SLogicSubplan* pUnionSubpl
|
|||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
nodesDestroyList(pSubplanChildren);
|
||||
DESTORY_LIST(pSplitNode->pChildren);
|
||||
NODES_DESTORY_LIST(pSplitNode->pChildren);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
|
|
@ -83,3 +83,21 @@ TEST_F(PlanBasicTest, interpFunc) {
|
|||
|
||||
run("SELECT INTERP(c1) FROM t1 RANGE('2017-7-14 18:00:00', '2017-7-14 19:00:00') EVERY(5s) FILL(LINEAR)");
|
||||
}
|
||||
|
||||
TEST_F(PlanBasicTest, lastRowFunc) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("SELECT LAST_ROW(c1) FROM t1");
|
||||
|
||||
run("SELECT LAST_ROW(*) FROM t1");
|
||||
|
||||
run("SELECT LAST_ROW(c1, c2) FROM t1");
|
||||
|
||||
run("SELECT LAST_ROW(c1) FROM st1");
|
||||
}
|
||||
|
||||
TEST_F(PlanBasicTest, withoutFrom) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("SELECT 1");
|
||||
}
|
||||
|
|
|
@ -533,6 +533,10 @@ int32_t syncNodeOnSnapshotSendCb(SSyncNode *pSyncNode, SyncSnapshotSend *pMsg) {
|
|||
ASSERT(writeCode == 0);
|
||||
|
||||
pSyncNode->pFsm->FpSnapshotStopWrite(pSyncNode->pFsm, pReceiver->pWriter, true);
|
||||
if (pReceiver->snapshot.lastApplyIndex > pReceiver->pSyncNode->commitIndex) {
|
||||
pReceiver->pSyncNode->commitIndex = pReceiver->snapshot.lastApplyIndex;
|
||||
}
|
||||
|
||||
pSyncNode->pLogStore->syncLogSetBeginIndex(pSyncNode->pLogStore, pMsg->lastIndex + 1);
|
||||
|
||||
// maybe update lastconfig
|
||||
|
@ -552,7 +556,7 @@ int32_t syncNodeOnSnapshotSendCb(SSyncNode *pSyncNode, SyncSnapshotSend *pMsg) {
|
|||
pSyncNode->pFsm->FpGetSnapshotInfo(pSyncNode->pFsm, &snapshot);
|
||||
|
||||
do {
|
||||
char *eventLog = snapshotReceiver2SimpleStr(pReceiver, "snapshot receiver finish");
|
||||
char *eventLog = snapshotReceiver2SimpleStr(pReceiver, "snapshot receiver finish, apply snapshot");
|
||||
syncNodeEventLog(pSyncNode, eventLog);
|
||||
taosMemoryFree(eventLog);
|
||||
} while (0);
|
||||
|
@ -563,7 +567,7 @@ int32_t syncNodeOnSnapshotSendCb(SSyncNode *pSyncNode, SyncSnapshotSend *pMsg) {
|
|||
needRsp = true;
|
||||
|
||||
do {
|
||||
char *eventLog = snapshotReceiver2SimpleStr(pReceiver, "snapshot receiver end");
|
||||
char *eventLog = snapshotReceiver2SimpleStr(pReceiver, "snapshot receiver stop");
|
||||
syncNodeEventLog(pSyncNode, eventLog);
|
||||
taosMemoryFree(eventLog);
|
||||
} while (0);
|
||||
|
|
|
@ -65,7 +65,7 @@ int main(int argc, char** argv) {
|
|||
SSyncLogStore* pLog = logStoreCreate(pSyncNode);
|
||||
assert(pLog != NULL);
|
||||
|
||||
logStorePrint2((char*)"==syncLogStoreCheck==", pLog);
|
||||
logStoreSimplePrint2((char*)"==syncLogStoreCheck2==", pLog);
|
||||
|
||||
walClose(pWal);
|
||||
logStoreDestory(pLog);
|
||||
|
|
|
@ -183,6 +183,8 @@ typedef enum { ConnNormal, ConnAcquire, ConnRelease, ConnBroken, ConnInPool } Co
|
|||
#define transContLenFromMsg(msgLen) (msgLen - sizeof(STransMsgHead));
|
||||
#define transIsReq(type) (type & 1U)
|
||||
|
||||
#define transLabel(trans) ((STrans*)trans)->label
|
||||
|
||||
// int rpcAuthenticateMsg(void* pMsg, int msgLen, void* pAuth, void* pKey);
|
||||
// void rpcBuildAuthHead(void* pMsg, int msgLen, void* pAuth, void* pKey);
|
||||
//// int32_t rpcCompressRpcMsg(char* pCont, int32_t contLen);
|
||||
|
|
|
@ -32,8 +32,13 @@ extern "C" {
|
|||
#define tTrace(...) { if (rpcDebugFlag & DEBUG_TRACE) { taosPrintLog("RPC ", DEBUG_TRACE, rpcDebugFlag, __VA_ARGS__); }}
|
||||
#define tDump(x, y) { if (rpcDebugFlag & DEBUG_DUMP) { taosDumpData((unsigned char *)x, y); } }
|
||||
|
||||
//#define tTR(param, ...) do { char buf[40] = {0};TRACE_TO_STR(trace, buf);tTrace("TRID: %s "param, buf, __VA_ARGS__);} while(0)
|
||||
#define tGTrace(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); tTrace(param ", gtid:%s", __VA_ARGS__, buf);}
|
||||
#define tGTrace(param, ...) do { if (rpcDebugFlag & DEBUG_TRACE){char buf[40] = {0}; TRACE_TO_STR(trace, buf); tTrace(param ", gtid:%s", __VA_ARGS__, buf);}} while(0)
|
||||
#define tGFatal(param, ...) do {if (rpcDebugFlag & DEBUG_FATAL){ char buf[40] = {0}; TRACE_TO_STR(trace, buf); tFatal(param ", gtid:%s", __VA_ARGS__, buf); }} while (0)
|
||||
#define tGError(param, ...) do { if (rpcDebugFlag & DEBUG_ERROR){ char buf[40] = {0}; TRACE_TO_STR(trace, buf); tError(param ", gtid:%s", __VA_ARGS__, buf);} } while(0)
|
||||
#define tGWarn(param, ...) do { if (rpcDebugFlag & DEBUG_WARN) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); tWarn(param ", gtid:%s", __VA_ARGS__, buf); }} while(0)
|
||||
#define tGInfo(param, ...) do { if (rpcDebugFlag & DEBUG_INFO) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); tInfo(param ", gtid:%s", __VA_ARGS__, buf); }} while(0)
|
||||
#define tGDebug(param,...) do {if (rpcDebugFlag & DEBUG_DEBUG){ char buf[40] = {0}; TRACE_TO_STR(trace, buf); tDebug(param ", gtid:%s", __VA_ARGS__, buf); }} while(0)
|
||||
|
||||
|
||||
// clang-format on
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -175,6 +175,7 @@ static void cliReleaseUnfinishedMsg(SCliConn* conn) {
|
|||
#define CONN_SHOULD_RELEASE(conn, head) \
|
||||
do { \
|
||||
if ((head)->release == 1 && (head->msgLen) == sizeof(*head)) { \
|
||||
int connStatus = conn->status; \
|
||||
uint64_t ahandle = head->ahandle; \
|
||||
CONN_GET_MSGCTX_BY_AHANDLE(conn, ahandle); \
|
||||
conn->status = ConnRelease; \
|
||||
|
@ -186,7 +187,9 @@ static void cliReleaseUnfinishedMsg(SCliConn* conn) {
|
|||
} \
|
||||
destroyCmsg(pMsg); \
|
||||
cliReleaseUnfinishedMsg(conn); \
|
||||
addConnToPool(((SCliThrdObj*)conn->hostThrd)->pool, conn); \
|
||||
if (connStatus != ConnInPool) { \
|
||||
addConnToPool(((SCliThrdObj*)conn->hostThrd)->pool, conn); \
|
||||
} \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
@ -450,7 +453,7 @@ void* destroyConnPool(void* pool) {
|
|||
while (connList != NULL) {
|
||||
while (!QUEUE_IS_EMPTY(&connList->conn)) {
|
||||
queue* h = QUEUE_HEAD(&connList->conn);
|
||||
QUEUE_REMOVE(h);
|
||||
// QUEUE_REMOVE(h);
|
||||
SCliConn* c = QUEUE_DATA(h, SCliConn, conn);
|
||||
cliDestroyConn(c, true);
|
||||
}
|
||||
|
@ -476,18 +479,19 @@ static SCliConn* getConnFromPool(void* pool, char* ip, uint32_t port) {
|
|||
if (QUEUE_IS_EMPTY(&plist->conn)) {
|
||||
return NULL;
|
||||
}
|
||||
queue* h = QUEUE_HEAD(&plist->conn);
|
||||
QUEUE_REMOVE(h);
|
||||
queue* h = QUEUE_HEAD(&plist->conn);
|
||||
SCliConn* conn = QUEUE_DATA(h, SCliConn, conn);
|
||||
conn->status = ConnNormal;
|
||||
QUEUE_REMOVE(&conn->conn);
|
||||
QUEUE_INIT(&conn->conn);
|
||||
assert(h == &conn->conn);
|
||||
return conn;
|
||||
}
|
||||
static void addConnToPool(void* pool, SCliConn* conn) {
|
||||
SCliThrdObj* thrd = conn->hostThrd;
|
||||
CONN_HANDLE_THREAD_QUIT(thrd);
|
||||
|
||||
STrans* pTransInst = ((SCliThrdObj*)conn->hostThrd)->pTransInst;
|
||||
STrans* pTransInst = thrd->pTransInst;
|
||||
conn->expireTime = taosGetTimestampMs() + CONN_PERSIST_TIME(pTransInst->idleTime);
|
||||
transQueueClear(&conn->cliMsgs);
|
||||
transCtxCleanup(&conn->ctx);
|
||||
|
@ -500,6 +504,7 @@ static void addConnToPool(void* pool, SCliConn* conn) {
|
|||
SConnList* plist = taosHashGet((SHashObj*)pool, key, strlen(key));
|
||||
// list already create before
|
||||
assert(plist != NULL);
|
||||
QUEUE_INIT(&conn->conn);
|
||||
QUEUE_PUSH(&plist->conn, &conn->conn);
|
||||
assert(!QUEUE_IS_EMPTY(&plist->conn));
|
||||
}
|
||||
|
@ -561,7 +566,6 @@ static SCliConn* cliCreateConn(SCliThrdObj* pThrd) {
|
|||
}
|
||||
static void cliDestroyConn(SCliConn* conn, bool clear) {
|
||||
tTrace("%s conn %p remove from conn pool", CONN_GET_INST_LABEL(conn), conn);
|
||||
|
||||
QUEUE_REMOVE(&conn->conn);
|
||||
if (clear) {
|
||||
uv_close((uv_handle_t*)conn->stream, cliDestroy);
|
||||
|
@ -778,11 +782,11 @@ void cliHandleReq(SCliMsg* pMsg, SCliThrdObj* pThrd) {
|
|||
|
||||
int ret = transSetConnOption((uv_tcp_t*)conn->stream);
|
||||
if (ret) {
|
||||
tError("%s conn %p failed to set conn option, errmsg %s", pTransInst->label, conn, uv_err_name(ret));
|
||||
tError("%s conn %p failed to set conn option, errmsg %s", transLabel(pTransInst), conn, uv_err_name(ret));
|
||||
}
|
||||
int fd = taosCreateSocketWithTimeOutOpt(TRANS_CONN_TIMEOUT);
|
||||
if (fd == -1) {
|
||||
tTrace("%s conn %p failed to create socket", pTransInst->label, conn);
|
||||
tTrace("%s conn %p failed to create socket", transLabel(pTransInst), conn);
|
||||
cliHandleExcept(conn);
|
||||
return;
|
||||
}
|
||||
|
@ -1006,7 +1010,9 @@ int cliAppCb(SCliConn* pConn, STransMsg* pResp, SCliMsg* pMsg) {
|
|||
tTrace("%s use remote epset, inUse: %d, retry count:%d, limit: %d", pTransInst->label, pEpSet->inUse,
|
||||
pCtx->retryCount + 1, TRANS_RETRY_COUNT_LIMIT);
|
||||
}
|
||||
addConnToPool(pThrd->pool, pConn);
|
||||
if (pConn->status != ConnInPool) {
|
||||
addConnToPool(pThrd->pool, pConn);
|
||||
}
|
||||
|
||||
STaskArg* arg = taosMemoryMalloc(sizeof(STaskArg));
|
||||
arg->param1 = pMsg;
|
||||
|
@ -1110,7 +1116,7 @@ void transSendRequest(void* shandle, const SEpSet* pEpSet, STransMsg* pReq, STra
|
|||
SCliThrdObj* thrd = ((SCliObj*)pTransInst->tcphandle)->pThreadObj[idx];
|
||||
|
||||
STraceId* trace = &pReq->info.traceId;
|
||||
tGTrace("%s send request at thread:%08" PRId64 ", dst: %s:%d, app:%p", pTransInst->label, thrd->pid,
|
||||
tGTrace("%s send request at thread:%08" PRId64 ", dst: %s:%d, app:%p", transLabel(pTransInst), thrd->pid,
|
||||
EPSET_GET_INUSE_IP(&pCtx->epSet), EPSET_GET_INUSE_PORT(&pCtx->epSet), pReq->info.ahandle);
|
||||
ASSERT(transSendAsync(thrd->asyncPool, &(cliMsg->q)) == 0);
|
||||
}
|
||||
|
@ -1143,7 +1149,7 @@ void transSendRecv(void* shandle, const SEpSet* pEpSet, STransMsg* pReq, STransM
|
|||
SCliThrdObj* thrd = ((SCliObj*)pTransInst->tcphandle)->pThreadObj[idx];
|
||||
|
||||
STraceId* trace = &pReq->info.traceId;
|
||||
tGTrace("%s send request at thread:%08" PRId64 ", dst: %s:%d, app:%p", pTransInst->label, thrd->pid,
|
||||
tGTrace("%s send request at thread:%08" PRId64 ", dst: %s:%d, app:%p", transLabel(pTransInst), thrd->pid,
|
||||
EPSET_GET_INUSE_IP(&pCtx->epSet), EPSET_GET_INUSE_PORT(&pCtx->epSet), pReq->info.ahandle);
|
||||
|
||||
transSendAsync(thrd->asyncPool, &(cliMsg->q));
|
||||
|
|
|
@ -284,12 +284,12 @@ static void uvHandleReq(SSvrConn* pConn) {
|
|||
if (pConn->status == ConnNormal && pHead->noResp == 0) {
|
||||
transRefSrvHandle(pConn);
|
||||
|
||||
tGTrace("conn %p %s received from %s:%d, local info: %s:%d, msg size: %d", pConn, TMSG_INFO(transMsg.msgType),
|
||||
taosInetNtoa(pConn->addr.sin_addr), ntohs(pConn->addr.sin_port), taosInetNtoa(pConn->localAddr.sin_addr),
|
||||
ntohs(pConn->localAddr.sin_port), transMsg.contLen);
|
||||
} else {
|
||||
tGTrace("conn %p %s received from %s:%d, local info: %s:%d, msg size: %d, resp:%d, code: %d", pConn,
|
||||
tGTrace("%s conn %p %s received from %s:%d, local info: %s:%d, msg size: %d", transLabel(pConn), pConn,
|
||||
TMSG_INFO(transMsg.msgType), taosInetNtoa(pConn->addr.sin_addr), ntohs(pConn->addr.sin_port),
|
||||
taosInetNtoa(pConn->localAddr.sin_addr), ntohs(pConn->localAddr.sin_port), transMsg.contLen);
|
||||
} else {
|
||||
tGTrace("%s conn %p %s received from %s:%d, local info: %s:%d, msg size: %d, resp:%d, code: %d", transLabel(pConn),
|
||||
pConn, TMSG_INFO(transMsg.msgType), taosInetNtoa(pConn->addr.sin_addr), ntohs(pConn->addr.sin_port),
|
||||
taosInetNtoa(pConn->localAddr.sin_addr), ntohs(pConn->localAddr.sin_port), transMsg.contLen, pHead->noResp,
|
||||
transMsg.code);
|
||||
// no ref here
|
||||
|
@ -304,7 +304,8 @@ static void uvHandleReq(SSvrConn* pConn) {
|
|||
transMsg.info.refId = pConn->refId;
|
||||
transMsg.info.traceId = pHead->traceId;
|
||||
|
||||
tGTrace("handle %p conn: %p translated to app, refId: %" PRIu64 "", transMsg.info.handle, pConn, pConn->refId);
|
||||
tGTrace("%s handle %p conn: %p translated to app, refId: %" PRIu64 "", transLabel(pConn), transMsg.info.handle, pConn,
|
||||
pConn->refId);
|
||||
assert(transMsg.info.handle != NULL);
|
||||
|
||||
if (pHead->noResp == 1) {
|
||||
|
@ -330,12 +331,12 @@ void uvOnRecvCb(uv_stream_t* cli, ssize_t nread, const uv_buf_t* buf) {
|
|||
SConnBuffer* pBuf = &conn->readBuf;
|
||||
if (nread > 0) {
|
||||
pBuf->len += nread;
|
||||
tTrace("conn %p total read: %d, current read: %d", conn, pBuf->len, (int)nread);
|
||||
tTrace("%s conn %p total read: %d, current read: %d", transLabel(conn->pTransInst), conn, pBuf->len, (int)nread);
|
||||
if (transReadComplete(pBuf)) {
|
||||
tTrace("conn %p alread read complete packet", conn);
|
||||
tTrace("%s conn %p alread read complete packet", transLabel(conn->pTransInst), conn);
|
||||
uvHandleReq(conn);
|
||||
} else {
|
||||
tTrace("conn %p read partial packet, continue to read", conn);
|
||||
tTrace("%s conn %p read partial packet, continue to read", transLabel(conn->pTransInst), conn);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -343,12 +344,12 @@ void uvOnRecvCb(uv_stream_t* cli, ssize_t nread, const uv_buf_t* buf) {
|
|||
return;
|
||||
}
|
||||
|
||||
tError("conn %p read error: %s", conn, uv_err_name(nread));
|
||||
tError("%s conn %p read error: %s", transLabel(conn->pTransInst), conn, uv_err_name(nread));
|
||||
if (nread < 0) {
|
||||
conn->broken = true;
|
||||
if (conn->status == ConnAcquire) {
|
||||
if (conn->regArg.init) {
|
||||
tTrace("conn %p broken, notify server app", conn);
|
||||
tTrace("%s conn %p broken, notify server app", transLabel(conn->pTransInst), conn);
|
||||
STrans* pTransInst = conn->pTransInst;
|
||||
(*pTransInst->cfp)(pTransInst->parent, &(conn->regArg.msg), NULL);
|
||||
memset(&conn->regArg, 0, sizeof(conn->regArg));
|
||||
|
@ -457,9 +458,9 @@ static void uvPrepareSendData(SSvrMsg* smsg, uv_buf_t* wb) {
|
|||
int32_t len = transMsgLenFromCont(pMsg->contLen);
|
||||
|
||||
STraceId* trace = &pMsg->info.traceId;
|
||||
tGTrace("conn %p %s is sent to %s:%d, local info: %s:%d, msglen:%d", pConn, TMSG_INFO(pHead->msgType),
|
||||
taosInetNtoa(pConn->addr.sin_addr), ntohs(pConn->addr.sin_port), taosInetNtoa(pConn->localAddr.sin_addr),
|
||||
ntohs(pConn->localAddr.sin_port), len);
|
||||
tGTrace("%s conn %p %s is sent to %s:%d, local info: %s:%d, msglen:%d", transLabel(pConn->pTransInst), pConn,
|
||||
TMSG_INFO(pHead->msgType), taosInetNtoa(pConn->addr.sin_addr), ntohs(pConn->addr.sin_port),
|
||||
taosInetNtoa(pConn->localAddr.sin_addr), ntohs(pConn->localAddr.sin_port), len);
|
||||
pHead->msgLen = htonl(len);
|
||||
|
||||
wb->base = msg;
|
||||
|
@ -737,7 +738,7 @@ static bool addHandleToWorkloop(SWorkThrdObj* pThrd, char* pipeName) {
|
|||
// conn set
|
||||
QUEUE_INIT(&pThrd->conn);
|
||||
|
||||
pThrd->asyncPool = transCreateAsyncPool(pThrd->loop, 5, pThrd, uvWorkerAsyncCb);
|
||||
pThrd->asyncPool = transCreateAsyncPool(pThrd->loop, 1, pThrd, uvWorkerAsyncCb);
|
||||
uv_pipe_connect(&pThrd->connect_req, pThrd->pipe, pipeName, uvOnPipeConnectionCb);
|
||||
// uv_read_start((uv_stream_t*)pThrd->pipe, uvAllocConnBufferCb, uvOnConnectionCb);
|
||||
return true;
|
||||
|
@ -801,7 +802,7 @@ static SSvrConn* createConn(void* hThrd) {
|
|||
|
||||
pConn->refId = exh->refId;
|
||||
transRefSrvHandle(pConn);
|
||||
tTrace("handle %p, conn %p created, refId: %" PRId64 "", exh, pConn, pConn->refId);
|
||||
tTrace("%s handle %p, conn %p created, refId: %" PRId64 "", transLabel(pThrd->pTransInst), exh, pConn, pConn->refId);
|
||||
return pConn;
|
||||
}
|
||||
|
||||
|
@ -848,7 +849,7 @@ static void uvDestroyConn(uv_handle_t* handle) {
|
|||
transReleaseExHandle(refMgt, conn->refId);
|
||||
transRemoveExHandle(refMgt, conn->refId);
|
||||
|
||||
tDebug("conn %p destroy", conn);
|
||||
tDebug("%s conn %p destroy", transLabel(thrd->pTransInst), conn);
|
||||
// uv_timer_stop(&conn->pTimer);
|
||||
transQueueDestroy(&conn->srvMsgs);
|
||||
|
||||
|
@ -977,18 +978,18 @@ void uvHandleRelease(SSvrMsg* msg, SWorkThrdObj* thrd) {
|
|||
uvStartSendRespInternal(msg);
|
||||
return;
|
||||
} else if (conn->status == ConnRelease || conn->status == ConnNormal) {
|
||||
tDebug("conn %p already released, ignore release-msg", conn);
|
||||
tDebug("%s conn %p already released, ignore release-msg", transLabel(thrd->pTransInst), conn);
|
||||
}
|
||||
destroySmsg(msg);
|
||||
}
|
||||
void uvHandleResp(SSvrMsg* msg, SWorkThrdObj* thrd) {
|
||||
// send msg to client
|
||||
tDebug("conn %p start to send resp (2/2)", msg->pConn);
|
||||
tDebug("%s conn %p start to send resp (2/2)", transLabel(thrd->pTransInst), msg->pConn);
|
||||
uvStartSendResp(msg);
|
||||
}
|
||||
void uvHandleRegister(SSvrMsg* msg, SWorkThrdObj* thrd) {
|
||||
SSvrConn* conn = msg->pConn;
|
||||
tDebug("conn %p register brokenlink callback", conn);
|
||||
tDebug("%s conn %p register brokenlink callback", transLabel(thrd->pTransInst), conn);
|
||||
if (conn->status == ConnAcquire) {
|
||||
if (!transQueuePush(&conn->srvMsgs, msg)) {
|
||||
return;
|
||||
|
@ -1094,7 +1095,7 @@ void transReleaseSrvHandle(void* handle) {
|
|||
m->msg = tmsg;
|
||||
m->type = Release;
|
||||
|
||||
tTrace("conn %p start to release", exh->handle);
|
||||
tTrace("%s conn %p start to release", transLabel(pThrd->pTransInst), exh->handle);
|
||||
transSendAsync(pThrd->asyncPool, &m->q);
|
||||
transReleaseExHandle(refMgt, refId);
|
||||
return;
|
||||
|
@ -1152,7 +1153,7 @@ void transRegisterMsg(const STransMsg* msg) {
|
|||
m->msg = tmsg;
|
||||
m->type = Register;
|
||||
|
||||
tTrace("conn %p start to register brokenlink callback", exh->handle);
|
||||
tTrace("%s conn %p start to register brokenlink callback", transLabel(pThrd->pTransInst), exh->handle);
|
||||
transSendAsync(pThrd->asyncPool, &m->q);
|
||||
transReleaseExHandle(refMgt, refId);
|
||||
return;
|
||||
|
|
|
@ -100,7 +100,6 @@ static int32_t walReadChangeFile(SWalReadHandle *pRead, int64_t fileFirstVer) {
|
|||
TdFilePtr pLogTFile = taosOpenFile(fnameStr, TD_FILE_READ);
|
||||
if (pLogTFile == NULL) {
|
||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||
terrno = TSDB_CODE_WAL_INVALID_VER;
|
||||
wError("cannot open file %s, since %s", fnameStr, terrstr());
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,11 @@
|
|||
# ---- dnode
|
||||
./test.sh -f tsim/dnode/create_dnode.sim
|
||||
./test.sh -f tsim/dnode/drop_dnode_has_mnode.sim
|
||||
./test.sh -f tsim/dnode/drop_dnode_has_qnode_snode.sim
|
||||
./test.sh -f tsim/dnode/drop_dnode_has_vnode_replica1.sim
|
||||
#./test.sh -f tsim/dnode/drop_dnode_has_vnode_replica3.sim
|
||||
#./test.sh -f tsim/dnode/drop_dnode_has_multi_vnode_replica1.sim
|
||||
#./test.sh -f tsim/dnode/drop_dnode_has_multi_vnode_replica3.sim
|
||||
|
||||
# ---- insert
|
||||
./test.sh -f tsim/insert/basic0.sim
|
||||
|
|
|
@ -70,6 +70,7 @@ if $data(2)[2] != follower then
|
|||
endi
|
||||
|
||||
print =============== step4: drop dnode 2
|
||||
sql_error drop dnode 1
|
||||
sql drop dnode 2
|
||||
|
||||
print show dnodes;
|
||||
|
@ -83,7 +84,7 @@ if $data00 != 1 then
|
|||
return -1
|
||||
endi
|
||||
|
||||
print show dnodes;
|
||||
print show mnodes;
|
||||
sql show mnodes
|
||||
print $data[0][0] $data[0][1] $data[0][2] $data[0][3] $data[0][4]
|
||||
print $data[1][0] $data[1][1] $data[1][2] $data[1][3] $data[1][4]
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
system sh/stop_dnodes.sh
|
||||
system sh/deploy.sh -n dnode1 -i 1
|
||||
system sh/deploy.sh -n dnode2 -i 2
|
||||
system sh/deploy.sh -n dnode3 -i 3
|
||||
system sh/cfg.sh -n dnode1 -c supportVnodes -v 0
|
||||
system sh/exec.sh -n dnode1 -s start
|
||||
system sh/exec.sh -n dnode2 -s start
|
||||
sql connect
|
||||
|
||||
print =============== step1 create dnode2
|
||||
sql create dnode $hostname port 7200
|
||||
sql create dnode $hostname port 7300
|
||||
|
||||
$x = 0
|
||||
step1:
|
||||
$ = $x + 1
|
||||
sleep 1000
|
||||
if $x == 10 then
|
||||
print ====> dnode not online!
|
||||
return -1
|
||||
endi
|
||||
sql show dnodes
|
||||
print ===> $data00 $data01 $data02 $data03 $data04 $data05
|
||||
print ===> $data10 $data11 $data12 $data13 $data14 $data15
|
||||
if $rows != 3 then
|
||||
return -1
|
||||
endi
|
||||
if $data(1)[4] != ready then
|
||||
goto step1
|
||||
endi
|
||||
if $data(2)[4] != ready then
|
||||
goto step1
|
||||
endi
|
||||
if $data(3)[4] != offline then
|
||||
goto step1
|
||||
endi
|
||||
|
||||
print =============== step2 create database
|
||||
sql create database d1 vgroups 4
|
||||
sql use d1
|
||||
sql create table d1.st (ts timestamp, i int) tags (j int)
|
||||
sql create table d1.c1 using st tags(1)
|
||||
sql show d1.tables
|
||||
if $rows != 1 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
sql show d1.vgroups
|
||||
print $data[0][0] $data[0][1] $data[0][2] $data[0][3] $data[0][4]
|
||||
print $data[0][0] $data[0][1] $data[0][2] $data[0][3] $data[0][4]
|
||||
print $data[0][0] $data[0][1] $data[0][2] $data[0][3] $data[0][4]
|
||||
print $data[0][0] $data[0][1] $data[0][2] $data[0][3] $data[0][4]
|
||||
if $rows != 4 then
|
||||
return -1
|
||||
endi
|
||||
if $data(2)[3] != 2 then
|
||||
return -1
|
||||
endi
|
||||
if $data(3)[3] != 2 then
|
||||
return -1
|
||||
endi
|
||||
if $data(4)[3] != 2 then
|
||||
return -1
|
||||
endi
|
||||
if $data(5)[3] != 2 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
print =============== step3: start dnode 3
|
||||
system sh/exec.sh -n dnode3 -s start
|
||||
$x = 0
|
||||
step4:
|
||||
$ = $x + 1
|
||||
sleep 1000
|
||||
if $x == 10 then
|
||||
print ====> dnode not online!
|
||||
return -1
|
||||
endi
|
||||
sql show dnodes
|
||||
print ===> $data00 $data01 $data02 $data03 $data04 $data05
|
||||
print ===> $data10 $data11 $data12 $data13 $data14 $data15
|
||||
if $rows != 3 then
|
||||
return -1
|
||||
endi
|
||||
if $data(1)[4] != ready then
|
||||
goto step4
|
||||
endi
|
||||
if $data(2)[4] != ready then
|
||||
goto step4
|
||||
endi
|
||||
if $data(3)[4] != ready then
|
||||
goto step4
|
||||
endi
|
||||
|
||||
print =============== step3: drop dnode2
|
||||
sql drop dnode 2
|
||||
|
||||
print show dnodes;
|
||||
sql show dnodes;
|
||||
print $data[0][0] $data[0][1] $data[0][2] $data[0][3] $data[0][4]
|
||||
print $data[1][0] $data[1][1] $data[1][2] $data[1][3] $data[1][4]
|
||||
if $rows != 2 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
sql show d1.vgroups
|
||||
print $data[0][0] $data[0][1] $data[0][2] $data[0][3] $data[0][4]
|
||||
print $data[0][0] $data[0][1] $data[0][2] $data[0][3] $data[0][4]
|
||||
print $data[0][0] $data[0][1] $data[0][2] $data[0][3] $data[0][4]
|
||||
print $data[0][0] $data[0][1] $data[0][2] $data[0][3] $data[0][4]
|
||||
if $rows != 4 then
|
||||
return -1
|
||||
endi
|
||||
if $data(2)[3] != 3 then
|
||||
return -1
|
||||
endi
|
||||
if $data(3)[3] != 3 then
|
||||
return -1
|
||||
endi
|
||||
if $data(4)[3] != 3 then
|
||||
return -1
|
||||
endi
|
||||
if $data(5)[3] != 3 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
print =============== step4: select data
|
||||
sql show d1.tables
|
||||
if $rows != 1 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
system sh/exec.sh -n dnode1 -s stop -x SIGINT
|
||||
system sh/exec.sh -n dnode2 -s stop -x SIGINT
|
||||
system sh/exec.sh -n dnode3 -s stop -x SIGINT
|
|
@ -0,0 +1,135 @@
|
|||
system sh/stop_dnodes.sh
|
||||
system sh/deploy.sh -n dnode1 -i 1
|
||||
system sh/deploy.sh -n dnode2 -i 2
|
||||
system sh/deploy.sh -n dnode3 -i 3
|
||||
system sh/deploy.sh -n dnode4 -i 4
|
||||
system sh/deploy.sh -n dnode5 -i 5
|
||||
system sh/cfg.sh -n dnode1 -c supportVnodes -v 0
|
||||
system sh/exec.sh -n dnode1 -s start
|
||||
system sh/exec.sh -n dnode2 -s start
|
||||
system sh/exec.sh -n dnode3 -s start
|
||||
system sh/exec.sh -n dnode4 -s start
|
||||
sql connect
|
||||
|
||||
print =============== step1 create dnode2 dnode3 dnode4 dnode 5
|
||||
sql create dnode $hostname port 7200
|
||||
sql create dnode $hostname port 7300
|
||||
sql create dnode $hostname port 7400
|
||||
sql create dnode $hostname port 7500
|
||||
|
||||
$x = 0
|
||||
step1:
|
||||
$ = $x + 1
|
||||
sleep 1000
|
||||
if $x == 10 then
|
||||
print ====> dnode not online!
|
||||
return -1
|
||||
endi
|
||||
sql show dnodes
|
||||
print ===> $data00 $data01 $data02 $data03 $data04 $data05
|
||||
print ===> $data10 $data11 $data12 $data13 $data14 $data15
|
||||
if $rows != 3 then
|
||||
return -1
|
||||
endi
|
||||
if $data(1)[4] != ready then
|
||||
goto step1
|
||||
endi
|
||||
if $data(2)[4] != ready then
|
||||
goto step1
|
||||
endi
|
||||
if $data(3)[4] != ready then
|
||||
goto step1
|
||||
endi
|
||||
if $data(4)[4] != ready then
|
||||
goto step1
|
||||
endi
|
||||
if $data(5)[4] != offline then
|
||||
goto step1
|
||||
endi
|
||||
|
||||
print =============== step3 create database
|
||||
sql create database d1 vgroups 4 replica 3
|
||||
sql use d1
|
||||
sql create table d1.st (ts timestamp, i int) tags (j int)
|
||||
sql create table d1.c1 using st tags(1)
|
||||
sql show d1.tables
|
||||
if $rows != 1 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
sql show d1.vgroups
|
||||
print $data[0][0] $data[0][1] $data[0][2] $data[0][3] $data[0][4]
|
||||
if $rows != 1 then
|
||||
return -1
|
||||
endi
|
||||
if $data(2)[3] != 2 then
|
||||
return -1
|
||||
endi
|
||||
if $data(2)[5] != 3 then
|
||||
return -1
|
||||
endi
|
||||
if $data(2)[7] != 4 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
print =============== step4: drop dnode 2
|
||||
system sh/exec.sh -n dnode5 -s start
|
||||
$x = 0
|
||||
step4:
|
||||
$ = $x + 1
|
||||
sleep 1000
|
||||
if $x == 10 then
|
||||
print ====> dnode not online!
|
||||
return -1
|
||||
endi
|
||||
sql show dnodes
|
||||
print ===> $data00 $data01 $data02 $data03 $data04 $data05
|
||||
print ===> $data10 $data11 $data12 $data13 $data14 $data15
|
||||
if $rows != 3 then
|
||||
return -1
|
||||
endi
|
||||
if $data(1)[4] != ready then
|
||||
goto step4
|
||||
endi
|
||||
if $data(2)[4] != ready then
|
||||
goto step4
|
||||
endi
|
||||
if $data(3)[4] != ready then
|
||||
goto step4
|
||||
endi
|
||||
if $data(4)[4] != ready then
|
||||
goto step4
|
||||
endi
|
||||
if $data(5)[4] != ready then
|
||||
goto step4
|
||||
endi
|
||||
|
||||
print =============== step5: drop dnode2
|
||||
sql drop dnode 2
|
||||
|
||||
print show dnodes;
|
||||
sql show dnodes;
|
||||
print $data[0][0] $data[0][1] $data[0][2] $data[0][3] $data[0][4]
|
||||
print $data[1][0] $data[1][1] $data[1][2] $data[1][3] $data[1][4]
|
||||
if $rows != 4 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
print show d1.vgroups
|
||||
sql show d1.vgroups
|
||||
print $data[0][0] $data[0][1] $data[0][2] $data[0][3] $data[0][4]
|
||||
if $rows != 1 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
|
||||
print =============== step6: select data
|
||||
sql show d1.tables
|
||||
if $rows != 1 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
return
|
||||
system sh/exec.sh -n dnode1 -s stop -x SIGINT
|
||||
system sh/exec.sh -n dnode2 -s stop -x SIGINT
|
||||
system sh/exec.sh -n dnode3 -s stop -x SIGINT
|
|
@ -0,0 +1,71 @@
|
|||
system sh/stop_dnodes.sh
|
||||
system sh/deploy.sh -n dnode1 -i 1
|
||||
system sh/deploy.sh -n dnode2 -i 2
|
||||
system sh/exec.sh -n dnode1 -s start
|
||||
system sh/exec.sh -n dnode2 -s start
|
||||
sql connect
|
||||
|
||||
print =============== step1 create dnode2
|
||||
sql create dnode $hostname port 7200
|
||||
|
||||
$x = 0
|
||||
step1:
|
||||
$ = $x + 1
|
||||
sleep 1000
|
||||
if $x == 10 then
|
||||
print ====> dnode not online!
|
||||
return -1
|
||||
endi
|
||||
sql show dnodes
|
||||
print ===> $data00 $data01 $data02 $data03 $data04 $data05
|
||||
print ===> $data10 $data11 $data12 $data13 $data14 $data15
|
||||
if $rows != 2 then
|
||||
return -1
|
||||
endi
|
||||
if $data(1)[4] != ready then
|
||||
goto step1
|
||||
endi
|
||||
if $data(2)[4] != ready then
|
||||
goto step1
|
||||
endi
|
||||
|
||||
print =============== step2: create qnode snode on dnode 2
|
||||
sql create qnode on dnode 2
|
||||
sql create snode on dnode 2
|
||||
|
||||
sql show qnodes
|
||||
if $rows != 1 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
sql show snodes
|
||||
if $rows != 1 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
print =============== step3: drop dnode 2
|
||||
sql drop dnode 2
|
||||
|
||||
print show dnodes;
|
||||
sql show dnodes;
|
||||
print $data[0][0] $data[0][1] $data[0][2] $data[0][3] $data[0][4]
|
||||
print $data[1][0] $data[1][1] $data[1][2] $data[1][3] $data[1][4]
|
||||
if $rows != 1 then
|
||||
return -1
|
||||
endi
|
||||
if $data00 != 1 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
sql show qnodes
|
||||
if $rows != 0 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
sql show snodes
|
||||
if $rows != 0 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
system sh/exec.sh -n dnode1 -s stop -x SIGINT
|
||||
system sh/exec.sh -n dnode2 -s stop -x SIGINT
|
|
@ -0,0 +1,151 @@
|
|||
system sh/stop_dnodes.sh
|
||||
system sh/deploy.sh -n dnode1 -i 1
|
||||
system sh/deploy.sh -n dnode2 -i 2
|
||||
system sh/deploy.sh -n dnode3 -i 3
|
||||
system sh/cfg.sh -n dnode1 -c supportVnodes -v 0
|
||||
system sh/exec.sh -n dnode1 -s start
|
||||
system sh/exec.sh -n dnode2 -s start
|
||||
sql connect
|
||||
|
||||
print =============== step1 create dnode2
|
||||
sql create dnode $hostname port 7200
|
||||
sql create dnode $hostname port 7300
|
||||
|
||||
$x = 0
|
||||
step1:
|
||||
$ = $x + 1
|
||||
sleep 1000
|
||||
if $x == 10 then
|
||||
print ====> dnode not online!
|
||||
return -1
|
||||
endi
|
||||
sql show dnodes
|
||||
print ===> $data00 $data01 $data02 $data03 $data04 $data05
|
||||
print ===> $data10 $data11 $data12 $data13 $data14 $data15
|
||||
if $rows != 3 then
|
||||
return -1
|
||||
endi
|
||||
if $data(1)[4] != ready then
|
||||
goto step1
|
||||
endi
|
||||
if $data(2)[4] != ready then
|
||||
goto step1
|
||||
endi
|
||||
if $data(3)[4] != offline then
|
||||
goto step1
|
||||
endi
|
||||
|
||||
print =============== step2 drop dnode which not exist
|
||||
sql_error drop dnode 1
|
||||
sql_error drop dnode 4
|
||||
|
||||
print =============== step3 create database
|
||||
sql create database d1 vgroups 1
|
||||
sql use d1
|
||||
sql create table d1.st (ts timestamp, i int) tags (j int)
|
||||
sql create table d1.c1 using st tags(1)
|
||||
sql show d1.tables
|
||||
if $rows != 1 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
sql show d1.vgroups
|
||||
print $data[0][0] $data[0][1] $data[0][2] $data[0][3] $data[0][4]
|
||||
if $rows != 1 then
|
||||
return -1
|
||||
endi
|
||||
if $data(2)[3] != 2 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
print =============== step4: drop dnode 2
|
||||
print cant drop since no enough vnodes
|
||||
sql_error drop dnode 2
|
||||
|
||||
system sh/exec.sh -n dnode2 -s stop
|
||||
system sh/exec.sh -n dnode3 -s start
|
||||
$x = 0
|
||||
step4:
|
||||
$ = $x + 1
|
||||
sleep 1000
|
||||
if $x == 10 then
|
||||
print ====> dnode not online!
|
||||
return -1
|
||||
endi
|
||||
sql show dnodes
|
||||
print ===> $data00 $data01 $data02 $data03 $data04 $data05
|
||||
print ===> $data10 $data11 $data12 $data13 $data14 $data15
|
||||
if $rows != 3 then
|
||||
return -1
|
||||
endi
|
||||
if $data(1)[4] != ready then
|
||||
goto step4
|
||||
endi
|
||||
if $data(2)[4] != offline then
|
||||
goto step4
|
||||
endi
|
||||
if $data(3)[4] != ready then
|
||||
goto step4
|
||||
endi
|
||||
|
||||
# cant drop since offline
|
||||
sql_error drop dnode 2
|
||||
|
||||
print =============== step5: start dnode2
|
||||
system sh/exec.sh -n dnode2 -s start
|
||||
|
||||
$x = 0
|
||||
step5:
|
||||
$ = $x + 1
|
||||
sleep 1000
|
||||
if $x == 10 then
|
||||
print ====> dnode not online!
|
||||
return -1
|
||||
endi
|
||||
sql show dnodes
|
||||
print ===> $data00 $data01 $data02 $data03 $data04 $data05
|
||||
print ===> $data10 $data11 $data12 $data13 $data14 $data15
|
||||
if $rows != 3 then
|
||||
return -1
|
||||
endi
|
||||
if $data(1)[4] != ready then
|
||||
goto step5
|
||||
endi
|
||||
if $data(2)[4] != ready then
|
||||
goto step5
|
||||
endi
|
||||
if $data(3)[4] != ready then
|
||||
goto step5
|
||||
endi
|
||||
|
||||
print =============== step6: drop dnode2
|
||||
sql drop dnode 2
|
||||
|
||||
print show dnodes;
|
||||
sql show dnodes;
|
||||
print $data[0][0] $data[0][1] $data[0][2] $data[0][3] $data[0][4]
|
||||
print $data[1][0] $data[1][1] $data[1][2] $data[1][3] $data[1][4]
|
||||
if $rows != 2 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
print show d1.vgroups
|
||||
sql show d1.vgroups
|
||||
print $data[0][0] $data[0][1] $data[0][2] $data[0][3] $data[0][4]
|
||||
if $rows != 1 then
|
||||
return -1
|
||||
endi
|
||||
if $data(2)[3] != 3 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
print =============== step7: select data
|
||||
sql show d1.tables
|
||||
if $rows != 1 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
return
|
||||
system sh/exec.sh -n dnode1 -s stop -x SIGINT
|
||||
system sh/exec.sh -n dnode2 -s stop -x SIGINT
|
||||
system sh/exec.sh -n dnode3 -s stop -x SIGINT
|
|
@ -0,0 +1,137 @@
|
|||
system sh/stop_dnodes.sh
|
||||
system sh/deploy.sh -n dnode1 -i 1
|
||||
system sh/deploy.sh -n dnode2 -i 2
|
||||
system sh/deploy.sh -n dnode3 -i 3
|
||||
system sh/deploy.sh -n dnode4 -i 4
|
||||
system sh/deploy.sh -n dnode5 -i 5
|
||||
system sh/cfg.sh -n dnode1 -c supportVnodes -v 0
|
||||
system sh/exec.sh -n dnode1 -s start
|
||||
system sh/exec.sh -n dnode2 -s start
|
||||
system sh/exec.sh -n dnode3 -s start
|
||||
system sh/exec.sh -n dnode4 -s start
|
||||
sql connect
|
||||
|
||||
print =============== step1 create dnode2 dnode3 dnode4 dnode 5
|
||||
sql create dnode $hostname port 7200
|
||||
sql create dnode $hostname port 7300
|
||||
sql create dnode $hostname port 7400
|
||||
sql create dnode $hostname port 7500
|
||||
|
||||
$x = 0
|
||||
step1:
|
||||
$ = $x + 1
|
||||
sleep 1000
|
||||
if $x == 10 then
|
||||
print ====> dnode not online!
|
||||
return -1
|
||||
endi
|
||||
sql show dnodes
|
||||
print ===> $data00 $data01 $data02 $data03 $data04 $data05
|
||||
print ===> $data10 $data11 $data12 $data13 $data14 $data15
|
||||
if $rows != 3 then
|
||||
return -1
|
||||
endi
|
||||
if $data(1)[4] != ready then
|
||||
goto step1
|
||||
endi
|
||||
if $data(2)[4] != ready then
|
||||
goto step1
|
||||
endi
|
||||
if $data(3)[4] != ready then
|
||||
goto step1
|
||||
endi
|
||||
if $data(4)[4] != ready then
|
||||
goto step1
|
||||
endi
|
||||
if $data(5)[4] != offline then
|
||||
goto step1
|
||||
endi
|
||||
|
||||
print =============== step3 create database
|
||||
sql create database d1 vgroups 1 replica 3
|
||||
sql use d1
|
||||
sql create table d1.st (ts timestamp, i int) tags (j int)
|
||||
sql create table d1.c1 using st tags(1)
|
||||
sql show d1.tables
|
||||
if $rows != 1 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
sql show d1.vgroups
|
||||
print $data[0][0] $data[0][1] $data[0][2] $data[0][3] $data[0][4]
|
||||
if $rows != 1 then
|
||||
return -1
|
||||
endi
|
||||
if $data(2)[3] != 2 then
|
||||
return -1
|
||||
endi
|
||||
if $data(2)[5] != 3 then
|
||||
return -1
|
||||
endi
|
||||
if $data(2)[7] != 4 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
print =============== step4: drop dnode 2
|
||||
system sh/exec.sh -n dnode5 -s start
|
||||
$x = 0
|
||||
step4:
|
||||
$ = $x + 1
|
||||
sleep 1000
|
||||
if $x == 10 then
|
||||
print ====> dnode not online!
|
||||
return -1
|
||||
endi
|
||||
sql show dnodes
|
||||
print ===> $data00 $data01 $data02 $data03 $data04 $data05
|
||||
print ===> $data10 $data11 $data12 $data13 $data14 $data15
|
||||
if $rows != 3 then
|
||||
return -1
|
||||
endi
|
||||
if $data(1)[4] != ready then
|
||||
goto step4
|
||||
endi
|
||||
if $data(2)[4] != ready then
|
||||
goto step4
|
||||
endi
|
||||
if $data(3)[4] != ready then
|
||||
goto step4
|
||||
endi
|
||||
if $data(4)[4] != ready then
|
||||
goto step4
|
||||
endi
|
||||
if $data(5)[4] != ready then
|
||||
goto step4
|
||||
endi
|
||||
|
||||
print =============== step5: drop dnode2
|
||||
sql drop dnode 2
|
||||
|
||||
print show dnodes;
|
||||
sql show dnodes;
|
||||
print $data[0][0] $data[0][1] $data[0][2] $data[0][3] $data[0][4]
|
||||
print $data[1][0] $data[1][1] $data[1][2] $data[1][3] $data[1][4]
|
||||
if $rows != 4 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
print show d1.vgroups
|
||||
sql show d1.vgroups
|
||||
print $data[0][0] $data[0][1] $data[0][2] $data[0][3] $data[0][4]
|
||||
if $rows != 1 then
|
||||
return -1
|
||||
endi
|
||||
#if $data(2)[3] != 3 then
|
||||
# return -1
|
||||
#endi
|
||||
|
||||
print =============== step6: select data
|
||||
sql show d1.tables
|
||||
if $rows != 1 then
|
||||
return -1
|
||||
endi
|
||||
|
||||
return
|
||||
system sh/exec.sh -n dnode1 -s stop -x SIGINT
|
||||
system sh/exec.sh -n dnode2 -s stop -x SIGINT
|
||||
system sh/exec.sh -n dnode3 -s stop -x SIGINT
|
|
@ -518,7 +518,7 @@ class TDTestCase:
|
|||
tdSql.query("select avg(dataint) from jsons1 where jtag is not null")
|
||||
tdSql.checkData(0, 0, 5.3)
|
||||
#tdSql.error("select twa(dataint) from jsons1 where jtag is not null")
|
||||
tdSql.error("select irate(dataint) from jsons1 where jtag is not null")
|
||||
tdSql.query("select irate(dataint) from jsons1 where jtag is not null")
|
||||
#tdSql.query("select sum(dataint) from jsons1 where jtag->'tag1' is not null")
|
||||
#tdSql.checkData(0, 0, 49)
|
||||
tdSql.query("select stddev(dataint) from jsons1 where jtag->'tag1'>1")
|
||||
|
|
|
@ -624,8 +624,7 @@ class TDTestCase:
|
|||
tdLog.info(" sample data is in datas groups ,successed sql is : %s" % sample_query )
|
||||
else:
|
||||
tdLog.exit(" sample data is not in datas groups ,failed sql is : %s" % sample_query )
|
||||
|
||||
|
||||
|
||||
def basic_sample_query(self):
|
||||
tdSql.execute(" drop database if exists db ")
|
||||
tdSql.execute(" create database if not exists db duration 300 ")
|
||||
|
@ -760,6 +759,14 @@ class TDTestCase:
|
|||
|
||||
self.check_sample("select sample( c1 ,3 ) from t1 where c1 between 1 and 10" ,"select c1 from t1 where c1 between 1 and 10")
|
||||
|
||||
tdSql.query("select sample(c1,2) ,c2,c3 ,c5 from stb1")
|
||||
tdSql.checkRows(2)
|
||||
tdSql.checkCols(4)
|
||||
|
||||
self.check_sample("select sample( c1 ,3 ),c2,c3,c4,c5 from t1 where c1 between 1 and 10" ,"select c1,c2,c3,c4,c5 from t1 where c1 between 1 and 10")
|
||||
self.check_sample("select sample( c1 ,3 ),c2,c3,c4,c5 from stb1 where c1 between 1 and 10" ,"select c1,c2,c3,c4,c5 from stb1 where c1 between 1 and 10")
|
||||
self.check_sample("select sample( c1 ,3 ),t1 from stb1 where c1 between 1 and 10" ,"select c1,t1 from stb1 where c1 between 1 and 10")
|
||||
|
||||
# join
|
||||
|
||||
tdSql.query("select sample( ct4.c1 , 1 ) from ct1, ct4 where ct4.ts=ct1.ts")
|
||||
|
@ -772,8 +779,8 @@ class TDTestCase:
|
|||
self.check_sample("select sample(c1,2) from stb1 partition by tbname" , "select c1 from stb1 partition by tbname")
|
||||
|
||||
# nest query
|
||||
# tdSql.query("select sample(c1,2) from (select c1 from t1); ")
|
||||
# tdSql.checkRows(2)
|
||||
tdSql.query("select sample(c1,2) from (select c1 from t1); ")
|
||||
tdSql.checkRows(2)
|
||||
|
||||
# union all
|
||||
tdSql.query("select sample(c1,2) from t1 union all select sample(c1,3) from t1")
|
||||
|
|
Loading…
Reference in New Issue