diff --git a/docs/en/10-cluster/02-cluster-mgmt.md b/docs/en/10-cluster/02-cluster-mgmt.md index 674c92e276..bd3386c411 100644 --- a/docs/en/10-cluster/02-cluster-mgmt.md +++ b/docs/en/10-cluster/02-cluster-mgmt.md @@ -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. ::: diff --git a/docs/en/10-cluster/03-ha-and-lb.md b/docs/en/10-cluster/03-ha-and-lb.md index bd718eef9f..9780e8f6c6 100644 --- a/docs/en/10-cluster/03-ha-and-lb.md +++ b/docs/en/10-cluster/03-ha-and-lb.md @@ -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. diff --git a/docs/en/14-reference/07-tdinsight/assets/15146-tdengine-monitor-dashboard.json b/docs/en/14-reference/07-tdinsight/assets/15146-tdengine-monitor-dashboard.json index f651983528..54dc1062d6 100644 --- a/docs/en/14-reference/07-tdinsight/assets/15146-tdengine-monitor-dashboard.json +++ b/docs/en/14-reference/07-tdinsight/assets/15146-tdengine-monitor-dashboard.json @@ -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" diff --git a/docs/en/14-reference/07-tdinsight/assets/tdengine-grafana-7.x.json b/docs/en/14-reference/07-tdinsight/assets/tdengine-grafana-7.x.json index b4254c428b..1add8522a7 100644 --- a/docs/en/14-reference/07-tdinsight/assets/tdengine-grafana-7.x.json +++ b/docs/en/14-reference/07-tdinsight/assets/tdengine-grafana-7.x.json @@ -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" diff --git a/docs/en/14-reference/07-tdinsight/index.md b/docs/en/14-reference/07-tdinsight/index.md index cebfafa225..e74c9de7b2 100644 --- a/docs/en/14-reference/07-tdinsight/index.md +++ b/docs/en/14-reference/07-tdinsight/index.md @@ -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. diff --git a/docs/en/21-tdinternal/01-arch.md b/docs/en/21-tdinternal/01-arch.md index 4d8bed4d2d..d7d472eb98 100644 --- a/docs/en/21-tdinternal/01-arch.md +++ b/docs/en/21-tdinternal/01-arch.md @@ -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: -![TDengine Database Master Writing Process](write_master.webp) -
Figure 3: TDengine Master writing process
+![TDengine Database Leader Writing Process](write_master.webp) +
Figure 3: TDengine Leader writing process
-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: -![TDengine Database Slave Writing Process](write_slave.webp) -
Figure 4: TDengine Slave Writing Process
+![TDengine Database Follower Writing Process](write_slave.webp) +
Figure 4: TDengine Follower Writing Process
-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. diff --git a/include/libs/function/functionMgt.h b/include/libs/function/functionMgt.h index cbaff29cb2..1f314d19e7 100644 --- a/include/libs/function/functionMgt.h +++ b/include/libs/function/functionMgt.h @@ -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); diff --git a/include/libs/nodes/nodes.h b/include/libs/nodes/nodes.h index 58e2393970..26a100bb1b 100644 --- a/include/libs/nodes/nodes.h +++ b/include/libs/nodes/nodes.h @@ -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, diff --git a/include/libs/nodes/plannodes.h b/include/libs/nodes/plannodes.h index b07e8f39d5..cb09bf6a5f 100644 --- a/include/libs/nodes/plannodes.h +++ b/include/libs/nodes/plannodes.h @@ -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; diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h index 7a63f87412..78013e5457 100644 --- a/include/libs/nodes/querynodes.h +++ b/include/libs/nodes/querynodes.h @@ -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; diff --git a/source/common/src/tdatablock.c b/source/common/src/tdatablock.c index 3c3d3e953d..5594ee9bcf 100644 --- a/source/common/src/tdatablock.c +++ b/source/common/src/tdatablock.c @@ -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; } diff --git a/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c b/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c index 71bbc8ddd4..5e1ef23f1c 100644 --- a/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c +++ b/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c @@ -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; } diff --git a/source/dnode/mgmt/node_util/inc/dmUtil.h b/source/dnode/mgmt/node_util/inc/dmUtil.h index f599de384c..01958aa053 100644 --- a/source/dnode/mgmt/node_util/inc/dmUtil.h +++ b/source/dnode/mgmt/node_util/inc/dmUtil.h @@ -44,6 +44,7 @@ extern "C" { #endif + // clang-format off #define dFatal(...) { if (dDebugFlag & DEBUG_FATAL) { taosPrintLog("DND FATAL ", DEBUG_FATAL, 255, __VA_ARGS__); }} diff --git a/source/dnode/mnode/impl/inc/mndInt.h b/source/dnode/mnode/impl/inc/mndInt.h index 958d82a75d..58266724a5 100644 --- a/source/dnode/mnode/impl/inc/mndInt.h +++ b/source/dnode/mnode/impl/inc/mndInt.h @@ -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 { diff --git a/source/dnode/mnode/impl/inc/mndQnode.h b/source/dnode/mnode/impl/inc/mndQnode.h index 3e38565a4f..17615500c4 100644 --- a/source/dnode/mnode/impl/inc/mndQnode.h +++ b/source/dnode/mnode/impl/inc/mndQnode.h @@ -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 } diff --git a/source/dnode/mnode/impl/inc/mndSnode.h b/source/dnode/mnode/impl/inc/mndSnode.h index 180f18a6dd..ec7bb02ca7 100644 --- a/source/dnode/mnode/impl/inc/mndSnode.h +++ b/source/dnode/mnode/impl/inc/mndSnode.h @@ -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 } diff --git a/source/dnode/mnode/impl/src/mndDnode.c b/source/dnode/mnode/impl/src/mndDnode.c index 58c3570c36..8d06868955 100644 --- a/source/dnode/mnode/impl/src/mndDnode.c +++ b/source/dnode/mnode/impl/src/mndDnode.c @@ -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; } diff --git a/source/dnode/mnode/impl/src/mndProfile.c b/source/dnode/mnode/impl/src/mndProfile.c index 01e3bdcf13..832e328d96 100644 --- a/source/dnode/mnode/impl/src/mndProfile.c +++ b/source/dnode/mnode/impl/src/mndProfile.c @@ -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; } diff --git a/source/dnode/mnode/impl/src/mndQnode.c b/source/dnode/mnode/impl/src/mndQnode.c index f5625f32d5..0a6c97e63c 100644 --- a/source/dnode/mnode/impl/src/mndQnode.c +++ b/source/dnode/mnode/impl/src/mndQnode.c @@ -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; diff --git a/source/dnode/mnode/impl/src/mndSnode.c b/source/dnode/mnode/impl/src/mndSnode.c index 12188a3b3a..df1330197a 100644 --- a/source/dnode/mnode/impl/src/mndSnode.c +++ b/source/dnode/mnode/impl/src/mndSnode.c @@ -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; diff --git a/source/dnode/mnode/impl/src/mndSync.c b/source/dnode/mnode/impl/src/mndSync.c index 8666739dab..e3358b41df 100644 --- a/source/dnode/mnode/impl/src/mndSync.c +++ b/source/dnode/mnode/impl/src/mndSync.c @@ -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); } diff --git a/source/dnode/mnode/impl/src/mndTrans.c b/source/dnode/mnode/impl/src/mndTrans.c index de6a44d456..eec108414e 100644 --- a/source/dnode/mnode/impl/src/mndTrans.c +++ b/source/dnode/mnode/impl/src/mndTrans.c @@ -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) { diff --git a/source/dnode/mnode/impl/src/mndVgroup.c b/source/dnode/mnode/impl/src/mndVgroup.c index 94ddbcd409..696e714a8c 100644 --- a/source/dnode/mnode/impl/src/mndVgroup.c +++ b/source/dnode/mnode/impl/src/mndVgroup.c @@ -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, diff --git a/source/dnode/mnode/sdb/src/sdbFile.c b/source/dnode/mnode/sdb/src/sdbFile.c index 47c4a4ed0f..ff4a9e4ead 100644 --- a/source/dnode/mnode/sdb/src/sdbFile.c +++ b/source/dnode/mnode/sdb/src/sdbFile.c @@ -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; } \ No newline at end of file diff --git a/source/dnode/vnode/src/inc/vnd.h b/source/dnode/vnode/src/inc/vnd.h index 7fa188d83a..32be479116 100644 --- a/source/dnode/vnode/src/inc/vnd.h +++ b/source/dnode/vnode/src/inc/vnd.h @@ -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 diff --git a/source/dnode/vnode/src/tq/tqSink.c b/source/dnode/vnode/src/tq/tqSink.c index 83059e3646..ece66d30fb 100644 --- a/source/dnode/vnode/src/tq/tqSink.c +++ b/source/dnode/vnode/src/tq/tqSink.c @@ -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; diff --git a/source/libs/command/src/explain.c b/source/libs/command/src/explain.c index ae0f669d65..2d55b06f06 100644 --- a/source/libs/command/src/explain.c +++ b/source/libs/command/src/explain.c @@ -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) { diff --git a/source/libs/executor/inc/executorimpl.h b/source/libs/executor/inc/executorimpl.h index 2a0f34cd03..5128148221 100644 --- a/source/libs/executor/inc/executorimpl.h +++ b/source/libs/executor/inc/executorimpl.h @@ -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, diff --git a/source/libs/executor/inc/tsort.h b/source/libs/executor/inc/tsort.h index 363f379ee4..35bdd4ee55 100644 --- a/source/libs/executor/inc/tsort.h +++ b/source/libs/executor/inc/tsort.h @@ -50,6 +50,7 @@ typedef struct SMsortComparParam { void **pSources; int32_t numOfSources; SArray *orderInfo; // SArray + 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 diff --git a/source/libs/executor/src/executil.c b/source/libs/executor/src/executil.c index 27096fe7f9..566abb1451 100644 --- a/source/libs/executor/src/executil.c +++ b/source/libs/executor/src/executil.c @@ -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; diff --git a/source/libs/executor/src/executorimpl.c b/source/libs/executor/src/executorimpl.c index 94675ce253..097b8b9fb8 100644 --- a/source/libs/executor/src/executorimpl.c +++ b/source/libs/executor/src/executorimpl.c @@ -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; diff --git a/source/libs/executor/src/scanoperator.c b/source/libs/executor/src/scanoperator.c index 734c6bfbfb..39a62410f9 100644 --- a/source/libs/executor/src/scanoperator.c +++ b/source/libs/executor/src/scanoperator.c @@ -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); diff --git a/source/libs/executor/src/sortoperator.c b/source/libs/executor/src/sortoperator.c index 9d13276e6d..97be4645a8 100644 --- a/source/libs/executor/src/sortoperator.c +++ b/source/libs/executor/src/sortoperator.c @@ -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; -} \ No newline at end of file +} diff --git a/source/libs/executor/src/timewindowoperator.c b/source/libs/executor/src/timewindowoperator.c index 5495b5e9bf..3ff45d7237 100644 --- a/source/libs/executor/src/timewindowoperator.c +++ b/source/libs/executor/src/timewindowoperator.c @@ -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; -} +} \ No newline at end of file diff --git a/source/libs/executor/src/tsort.c b/source/libs/executor/src/tsort.c index 581935514e..1dd72fd83f 100644 --- a/source/libs/executor/src/tsort.c +++ b/source/libs/executor/src/tsort.c @@ -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; diff --git a/source/libs/function/inc/builtinsimpl.h b/source/libs/function/inc/builtinsimpl.h index e691d562c6..4d2f926c12 100644 --- a/source/libs/function/inc/builtinsimpl.h +++ b/source/libs/function/inc/builtinsimpl.h @@ -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); diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index cfad00f458..6baf45a5b3 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -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, diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 1164b96262..d7ff03ec59 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -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; diff --git a/source/libs/function/src/functionMgt.c b/source/libs/function/src/functionMgt.c index 710b01ce59..5fcf5e239c 100644 --- a/source/libs/function/src/functionMgt.c +++ b/source/libs/function/src/functionMgt.c @@ -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) { diff --git a/source/libs/nodes/src/nodesCloneFuncs.c b/source/libs/nodes/src/nodesCloneFuncs.c index 8290b5628c..0bde0d0581 100644 --- a/source/libs/nodes/src/nodesCloneFuncs.c +++ b/source/libs/nodes/src/nodesCloneFuncs.c @@ -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: diff --git a/source/libs/nodes/src/nodesCodeFuncs.c b/source/libs/nodes/src/nodesCodeFuncs.c index bde5159087..10a933b00b 100644 --- a/source/libs/nodes/src/nodesCodeFuncs.c +++ b/source/libs/nodes/src/nodesCodeFuncs.c @@ -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: diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c index 9b0241f2f1..dff3821a0a 100644 --- a/source/libs/nodes/src/nodesUtilFuncs.c +++ b/source/libs/nodes/src/nodesUtilFuncs.c @@ -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: diff --git a/source/libs/parser/inc/sql.y b/source/libs/parser/inc/sql.y index 54c46ecb5d..16a78712ed 100644 --- a/source/libs/parser/inc/sql.y +++ b/source/libs/parser/inc/sql.y @@ -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); diff --git a/source/libs/parser/src/parCalcConst.c b/source/libs/parser/src/parCalcConst.c index 22d7afd642..0dfc79269e 100644 --- a/source/libs/parser/src/parCalcConst.c +++ b/source/libs/parser/src/parCalcConst.c @@ -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) { diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 502e35cc4c..6c21f71228 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -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) { diff --git a/source/libs/parser/src/sql.c b/source/libs/parser/src/sql.c index c7651137b1..330cf67b22 100644 --- a/source/libs/parser/src/sql.c +++ b/source/libs/parser/src/sql.c @@ -139,16 +139,16 @@ typedef union { #define ParseCTX_STORE #define YYFALLBACK 1 #define YYNSTATE 641 -#define YYNRULE 466 +#define YYNRULE 467 #define YYNTOKEN 242 #define YY_MAX_SHIFT 640 #define YY_MIN_SHIFTREDUCE 933 -#define YY_MAX_SHIFTREDUCE 1398 -#define YY_ERROR_ACTION 1399 -#define YY_ACCEPT_ACTION 1400 -#define YY_NO_ACTION 1401 -#define YY_MIN_REDUCE 1402 -#define YY_MAX_REDUCE 1867 +#define YY_MAX_SHIFTREDUCE 1399 +#define YY_ERROR_ACTION 1400 +#define YY_ACCEPT_ACTION 1401 +#define YY_NO_ACTION 1402 +#define YY_MIN_REDUCE 1403 +#define YY_MAX_REDUCE 1869 /************* End control #defines *******************************************/ #define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) @@ -217,226 +217,226 @@ typedef union { *********** Begin parsing tables **********************************************/ #define YY_ACTTAB_COUNT (2192) static const YYACTIONTYPE yy_action[] = { - /* 0 */ 1697, 1845, 1522, 309, 412, 1697, 413, 1434, 326, 1400, - /* 10 */ 137, 1694, 37, 35, 1490, 1844, 1694, 1710, 417, 1842, + /* 0 */ 1698, 1847, 1523, 309, 412, 1698, 413, 1435, 326, 1401, + /* 10 */ 137, 1695, 37, 35, 1491, 1846, 1695, 1711, 417, 1844, /* 20 */ 318, 556, 1208, 556, 1230, 38, 36, 34, 33, 32, - /* 30 */ 325, 324, 109, 420, 109, 413, 1434, 1690, 1696, 451, - /* 40 */ 1222, 456, 1690, 1696, 1726, 30, 240, 1206, 559, 1533, - /* 50 */ 1793, 1533, 540, 559, 22, 556, 555, 1680, 14, 539, - /* 60 */ 37, 35, 1335, 322, 1214, 1215, 157, 335, 318, 1710, - /* 70 */ 1208, 134, 520, 365, 1790, 38, 36, 34, 33, 32, - /* 80 */ 1535, 1, 1214, 1533, 1739, 67, 555, 85, 1711, 542, - /* 90 */ 1713, 1714, 538, 58, 559, 1206, 1726, 1779, 113, 76, - /* 100 */ 371, 292, 1775, 637, 519, 556, 14, 1528, 1845, 1680, - /* 110 */ 1425, 539, 1214, 1845, 1845, 543, 369, 1277, 1278, 963, - /* 120 */ 1526, 560, 152, 470, 555, 1631, 1842, 154, 152, 2, - /* 130 */ 430, 1842, 1842, 1533, 206, 82, 1739, 290, 478, 86, - /* 140 */ 1711, 542, 1713, 1714, 538, 1369, 559, 40, 118, 1779, - /* 150 */ 1680, 637, 198, 311, 1775, 148, 1525, 967, 968, 1209, + /* 30 */ 325, 324, 109, 420, 109, 413, 1435, 1691, 1697, 451, + /* 40 */ 1222, 456, 1691, 1697, 1727, 30, 240, 1206, 559, 1534, + /* 50 */ 1795, 1534, 540, 559, 22, 556, 555, 1681, 14, 539, + /* 60 */ 37, 35, 1336, 322, 1214, 1215, 157, 335, 318, 1711, + /* 70 */ 1208, 134, 520, 365, 1792, 38, 36, 34, 33, 32, + /* 80 */ 1536, 1, 1214, 1534, 1740, 67, 555, 85, 1712, 542, + /* 90 */ 1714, 1715, 538, 58, 559, 1206, 1727, 1780, 113, 76, + /* 100 */ 371, 292, 1776, 637, 519, 556, 14, 1529, 1847, 1681, + /* 110 */ 1426, 539, 1214, 1847, 1847, 543, 369, 1277, 1278, 963, + /* 120 */ 1527, 560, 152, 470, 555, 1632, 1844, 154, 152, 2, + /* 130 */ 430, 1844, 1844, 1534, 206, 82, 1740, 290, 478, 86, + /* 140 */ 1712, 542, 1714, 1715, 538, 1370, 559, 40, 118, 1780, + /* 150 */ 1681, 637, 198, 311, 1776, 148, 1526, 967, 968, 1209, /* 160 */ 58, 1207, 70, 328, 473, 1277, 1278, 232, 56, 467, - /* 170 */ 364, 134, 363, 1233, 197, 495, 1806, 1223, 330, 1218, - /* 180 */ 1535, 1578, 1580, 1212, 1213, 41, 1259, 1260, 1262, 1263, + /* 170 */ 364, 134, 363, 1233, 197, 495, 1808, 1223, 330, 1218, + /* 180 */ 1536, 1579, 1581, 1212, 1213, 41, 1259, 1260, 1262, 1263, /* 190 */ 1264, 1265, 1266, 535, 557, 1274, 1275, 1276, 1279, 53, - /* 200 */ 1232, 1226, 52, 1579, 1580, 26, 59, 1209, 1845, 1207, + /* 200 */ 1232, 1226, 52, 1580, 1581, 26, 59, 1209, 1847, 1207, /* 210 */ 510, 155, 557, 1274, 1275, 38, 36, 34, 33, 32, - /* 220 */ 37, 35, 153, 155, 1424, 1710, 1842, 402, 318, 67, + /* 220 */ 37, 35, 153, 155, 1425, 1711, 1844, 402, 318, 67, /* 230 */ 1208, 1212, 1213, 302, 1259, 1260, 1262, 1263, 1264, 1265, - /* 240 */ 1266, 535, 557, 1274, 1275, 1276, 1279, 516, 1726, 465, - /* 250 */ 464, 1529, 1726, 489, 463, 1206, 509, 114, 460, 1668, - /* 260 */ 540, 459, 458, 457, 1680, 1680, 14, 539, 37, 35, + /* 240 */ 1266, 535, 557, 1274, 1275, 1276, 1279, 516, 1727, 465, + /* 250 */ 464, 1530, 1727, 489, 463, 1206, 509, 114, 460, 1669, + /* 260 */ 540, 459, 458, 457, 1681, 1681, 14, 539, 37, 35, /* 270 */ 1112, 1113, 1214, 166, 165, 117, 318, 155, 1208, 1299, - /* 280 */ 520, 1511, 303, 58, 301, 300, 356, 453, 58, 2, - /* 290 */ 155, 455, 1739, 508, 1845, 85, 1711, 542, 1713, 1714, - /* 300 */ 538, 1304, 559, 1206, 344, 1779, 358, 354, 152, 292, - /* 310 */ 1775, 637, 1842, 454, 115, 38, 36, 34, 33, 32, - /* 320 */ 1214, 1845, 136, 1524, 1414, 1277, 1278, 1509, 518, 149, - /* 330 */ 1786, 1787, 1233, 1791, 1694, 152, 27, 8, 430, 1842, + /* 280 */ 520, 1512, 303, 58, 301, 300, 356, 453, 58, 2, + /* 290 */ 155, 455, 1740, 508, 1847, 85, 1712, 542, 1714, 1715, + /* 300 */ 538, 1304, 559, 1206, 344, 1780, 358, 354, 152, 292, + /* 310 */ 1776, 637, 1844, 454, 115, 38, 36, 34, 33, 32, + /* 320 */ 1214, 1847, 136, 1525, 1415, 1277, 1278, 1510, 518, 149, + /* 330 */ 1788, 1789, 1233, 1793, 1695, 152, 27, 8, 430, 1844, /* 340 */ 1070, 582, 581, 580, 1074, 579, 1076, 1077, 578, 1079, - /* 350 */ 575, 1403, 1085, 572, 1087, 1088, 569, 566, 81, 637, - /* 360 */ 1690, 1696, 38, 36, 34, 33, 32, 1209, 78, 1207, - /* 370 */ 1359, 559, 99, 1277, 1278, 98, 97, 96, 95, 94, - /* 380 */ 93, 92, 91, 90, 593, 1349, 38, 36, 34, 33, + /* 350 */ 575, 1404, 1085, 572, 1087, 1088, 569, 566, 81, 637, + /* 360 */ 1691, 1697, 38, 36, 34, 33, 32, 1209, 78, 1207, + /* 370 */ 1360, 559, 99, 1277, 1278, 98, 97, 96, 95, 94, + /* 380 */ 93, 92, 91, 90, 593, 1350, 38, 36, 34, 33, /* 390 */ 32, 1212, 1213, 522, 1259, 1260, 1262, 1263, 1264, 1265, - /* 400 */ 1266, 535, 557, 1274, 1275, 1276, 1279, 502, 1357, 1358, - /* 410 */ 1360, 1361, 980, 155, 979, 1209, 99, 1207, 155, 98, + /* 400 */ 1266, 535, 557, 1274, 1275, 1276, 1279, 502, 1358, 1359, + /* 410 */ 1361, 1362, 980, 155, 979, 1209, 99, 1207, 155, 98, /* 420 */ 97, 96, 95, 94, 93, 92, 91, 90, 37, 35, - /* 430 */ 1280, 11, 10, 1710, 462, 461, 318, 162, 1208, 1212, + /* 430 */ 1280, 11, 10, 1711, 462, 461, 318, 162, 1208, 1212, /* 440 */ 1213, 981, 1259, 1260, 1262, 1263, 1264, 1265, 1266, 535, /* 450 */ 557, 1274, 1275, 1276, 1279, 38, 36, 34, 33, 32, - /* 460 */ 1726, 479, 65, 1206, 1845, 64, 593, 155, 540, 980, - /* 470 */ 147, 979, 1585, 1680, 1231, 539, 37, 35, 1843, 308, - /* 480 */ 1214, 1461, 1842, 1572, 318, 1793, 1208, 1423, 1583, 1214, - /* 490 */ 38, 36, 34, 33, 32, 1422, 449, 9, 981, 1234, - /* 500 */ 1739, 1395, 1845, 87, 1711, 542, 1713, 1714, 538, 1789, - /* 510 */ 559, 1206, 1311, 1779, 199, 134, 152, 1778, 1775, 637, - /* 520 */ 1842, 543, 133, 1585, 1536, 1246, 1342, 1680, 1214, 321, - /* 530 */ 323, 1630, 1232, 1277, 1278, 1680, 293, 609, 607, 1583, - /* 540 */ 1421, 615, 614, 613, 333, 9, 612, 611, 610, 119, + /* 460 */ 1727, 479, 65, 1206, 1847, 64, 593, 155, 540, 980, + /* 470 */ 147, 979, 1586, 1681, 1231, 539, 37, 35, 1845, 308, + /* 480 */ 1214, 1462, 1844, 1573, 318, 1795, 1208, 1424, 1584, 1214, + /* 490 */ 38, 36, 34, 33, 32, 1423, 449, 9, 981, 1234, + /* 500 */ 1740, 1396, 1847, 87, 1712, 542, 1714, 1715, 538, 1791, + /* 510 */ 559, 1206, 1311, 1780, 199, 134, 152, 1779, 1776, 637, + /* 520 */ 1844, 543, 133, 1586, 1537, 1246, 1343, 1681, 1214, 321, + /* 530 */ 323, 1631, 1232, 1277, 1278, 1681, 293, 609, 607, 1584, + /* 540 */ 1422, 615, 614, 613, 333, 9, 612, 611, 610, 119, /* 550 */ 605, 604, 603, 602, 601, 600, 599, 598, 127, 594, - /* 560 */ 1246, 1402, 38, 36, 34, 33, 32, 637, 1297, 505, - /* 570 */ 69, 291, 1285, 967, 968, 1209, 1420, 1207, 1232, 1419, - /* 580 */ 1680, 1277, 1278, 1394, 28, 108, 107, 106, 105, 104, + /* 560 */ 1246, 1403, 38, 36, 34, 33, 32, 637, 1297, 505, + /* 570 */ 69, 291, 1285, 967, 968, 1209, 1421, 1207, 1232, 1420, + /* 580 */ 1681, 1277, 1278, 1395, 28, 108, 107, 106, 105, 104, /* 590 */ 103, 102, 101, 100, 38, 36, 34, 33, 32, 1212, - /* 600 */ 1213, 1510, 1259, 1260, 1262, 1263, 1264, 1265, 1266, 535, - /* 610 */ 557, 1274, 1275, 1276, 1279, 556, 1680, 1585, 1585, 1680, - /* 620 */ 1298, 331, 585, 1209, 329, 1207, 370, 231, 1518, 134, - /* 630 */ 34, 33, 32, 1583, 1584, 1418, 37, 35, 1535, 511, - /* 640 */ 506, 200, 1303, 1533, 318, 591, 1208, 1212, 1213, 1417, + /* 600 */ 1213, 1511, 1259, 1260, 1262, 1263, 1264, 1265, 1266, 535, + /* 610 */ 557, 1274, 1275, 1276, 1279, 556, 1681, 1586, 1586, 1681, + /* 620 */ 1298, 331, 585, 1209, 329, 1207, 370, 231, 1519, 134, + /* 630 */ 34, 33, 32, 1584, 1585, 1419, 37, 35, 1536, 511, + /* 640 */ 506, 200, 1303, 1534, 318, 591, 1208, 1212, 1213, 1418, /* 650 */ 1259, 1260, 1262, 1263, 1264, 1265, 1266, 535, 557, 1274, /* 660 */ 1275, 1276, 1279, 556, 125, 124, 588, 587, 586, 411, - /* 670 */ 419, 1206, 415, 415, 372, 1680, 556, 29, 316, 1292, - /* 680 */ 1293, 1294, 1295, 1296, 1300, 1301, 1302, 387, 1214, 1680, - /* 690 */ 185, 1533, 556, 263, 591, 597, 1563, 1505, 1416, 1261, - /* 700 */ 1190, 1191, 140, 388, 1533, 2, 1413, 556, 447, 443, - /* 710 */ 439, 435, 184, 125, 124, 588, 587, 586, 429, 1793, - /* 720 */ 1533, 1698, 1710, 1334, 289, 1232, 1230, 637, 1412, 1700, - /* 730 */ 1411, 455, 1694, 395, 7, 1533, 407, 68, 1680, 556, - /* 740 */ 182, 1277, 1278, 1788, 556, 1261, 1680, 1410, 1409, 1726, - /* 750 */ 1530, 380, 1235, 454, 408, 1657, 382, 540, 1690, 1696, - /* 760 */ 135, 524, 1680, 556, 539, 269, 1702, 1533, 1680, 559, - /* 770 */ 1680, 1621, 1533, 556, 487, 496, 589, 267, 55, 1576, - /* 780 */ 527, 54, 164, 1209, 553, 1207, 373, 1680, 1680, 1739, - /* 790 */ 596, 1533, 287, 1711, 542, 1713, 1714, 538, 167, 559, - /* 800 */ 181, 1533, 173, 1464, 178, 1520, 425, 1212, 1213, 1408, + /* 670 */ 419, 1206, 415, 415, 372, 1681, 556, 29, 316, 1292, + /* 680 */ 1293, 1294, 1295, 1296, 1300, 1301, 1302, 387, 1214, 1681, + /* 690 */ 185, 1534, 556, 263, 591, 597, 1564, 1506, 1417, 1261, + /* 700 */ 1190, 1191, 140, 388, 1534, 2, 1414, 556, 447, 443, + /* 710 */ 439, 435, 184, 125, 124, 588, 587, 586, 429, 1795, + /* 720 */ 1534, 1699, 1711, 1335, 289, 1232, 1230, 637, 1413, 1701, + /* 730 */ 1412, 455, 1695, 395, 7, 1534, 407, 68, 1681, 556, + /* 740 */ 182, 1277, 1278, 1790, 556, 1261, 1681, 1411, 1410, 1727, + /* 750 */ 1531, 380, 1235, 454, 408, 1658, 382, 540, 1691, 1697, + /* 760 */ 135, 524, 1681, 556, 539, 269, 1703, 1534, 1681, 559, + /* 770 */ 1681, 1622, 1534, 556, 487, 496, 589, 267, 55, 1577, + /* 780 */ 527, 54, 164, 1209, 553, 1207, 373, 1681, 1681, 1740, + /* 790 */ 596, 1534, 287, 1712, 542, 1714, 1715, 538, 167, 559, + /* 800 */ 181, 1534, 173, 1465, 178, 1521, 425, 1212, 1213, 1409, /* 810 */ 1259, 1260, 1262, 1263, 1264, 1265, 1266, 535, 557, 1274, - /* 820 */ 1275, 1276, 1279, 58, 590, 171, 406, 1576, 1516, 401, + /* 820 */ 1275, 1276, 1279, 58, 590, 171, 406, 1577, 1517, 401, /* 830 */ 400, 399, 398, 397, 394, 393, 392, 391, 390, 386, - /* 840 */ 385, 384, 383, 377, 376, 375, 374, 203, 1032, 1680, + /* 840 */ 385, 384, 383, 377, 376, 375, 374, 203, 1032, 1681, /* 850 */ 38, 36, 34, 33, 32, 556, 556, 1208, 556, 516, - /* 860 */ 1407, 84, 1406, 465, 464, 1034, 554, 253, 463, 332, - /* 870 */ 1405, 114, 460, 1798, 1330, 459, 458, 457, 608, 1451, - /* 880 */ 212, 534, 1206, 1533, 1533, 190, 1533, 117, 188, 486, - /* 890 */ 1710, 1508, 1261, 62, 61, 368, 293, 1217, 161, 1214, - /* 900 */ 1680, 466, 1680, 192, 362, 516, 191, 1330, 194, 196, - /* 910 */ 1680, 193, 195, 1446, 1444, 288, 584, 1726, 352, 359, - /* 920 */ 350, 346, 342, 158, 337, 519, 115, 477, 1297, 1415, - /* 930 */ 1680, 1333, 539, 117, 1216, 468, 471, 123, 637, 1004, - /* 940 */ 475, 150, 1786, 1787, 532, 1791, 235, 11, 10, 48, - /* 950 */ 525, 216, 1491, 155, 448, 503, 1005, 1739, 1710, 480, - /* 960 */ 86, 1711, 542, 1713, 1714, 538, 1440, 559, 1397, 1398, - /* 970 */ 1779, 528, 115, 39, 311, 1775, 148, 223, 491, 39, - /* 980 */ 1298, 1727, 1710, 334, 591, 1726, 39, 151, 1786, 1787, - /* 990 */ 1356, 1791, 218, 540, 1209, 242, 1207, 1807, 1680, 1435, - /* 1000 */ 539, 1573, 1303, 125, 124, 588, 587, 586, 1809, 1726, + /* 860 */ 1408, 84, 1407, 465, 464, 1034, 554, 253, 463, 332, + /* 870 */ 1406, 114, 460, 1800, 1331, 459, 458, 457, 608, 1452, + /* 880 */ 212, 534, 1206, 1534, 1534, 190, 1534, 117, 188, 486, + /* 890 */ 1711, 1509, 1261, 62, 61, 368, 293, 1217, 161, 1214, + /* 900 */ 1681, 466, 1681, 192, 362, 516, 191, 1331, 194, 196, + /* 910 */ 1681, 193, 195, 1447, 1445, 288, 584, 1727, 352, 359, + /* 920 */ 350, 346, 342, 158, 337, 519, 115, 477, 1297, 1416, + /* 930 */ 1681, 1334, 539, 117, 1216, 468, 471, 123, 637, 1004, + /* 940 */ 475, 150, 1788, 1789, 532, 1793, 235, 11, 10, 48, + /* 950 */ 525, 216, 1492, 155, 448, 503, 1005, 1740, 1711, 480, + /* 960 */ 86, 1712, 542, 1714, 1715, 538, 1441, 559, 1398, 1399, + /* 970 */ 1780, 528, 115, 39, 311, 1776, 148, 223, 491, 39, + /* 980 */ 1298, 1728, 1711, 334, 591, 1727, 39, 151, 1788, 1789, + /* 990 */ 1357, 1793, 218, 540, 1209, 242, 1207, 1809, 1681, 1436, + /* 1000 */ 539, 1574, 1303, 125, 124, 588, 587, 586, 1811, 1727, /* 1010 */ 121, 1220, 633, 517, 1305, 234, 237, 540, 1212, 1213, - /* 1020 */ 1267, 239, 1680, 1710, 539, 1739, 3, 1163, 272, 1711, - /* 1030 */ 542, 1713, 1714, 538, 122, 559, 244, 29, 316, 1292, - /* 1040 */ 1293, 1294, 1295, 1296, 1300, 1301, 1302, 123, 1219, 1739, - /* 1050 */ 1726, 548, 86, 1711, 542, 1713, 1714, 538, 540, 559, - /* 1060 */ 48, 564, 1779, 1680, 1710, 539, 311, 1775, 1858, 1289, - /* 1070 */ 122, 123, 110, 122, 5, 250, 336, 1813, 1230, 339, + /* 1020 */ 1267, 239, 1681, 1711, 539, 1740, 3, 1163, 272, 1712, + /* 1030 */ 542, 1714, 1715, 538, 122, 559, 244, 29, 316, 1292, + /* 1040 */ 1293, 1294, 1295, 1296, 1300, 1301, 1302, 123, 1219, 1740, + /* 1050 */ 1727, 548, 86, 1712, 542, 1714, 1715, 538, 540, 559, + /* 1060 */ 48, 564, 1780, 1681, 1711, 539, 311, 1776, 1860, 1289, + /* 1070 */ 122, 123, 110, 122, 5, 250, 336, 1815, 1230, 339, /* 1080 */ 343, 298, 1174, 1032, 299, 259, 389, 163, 1063, 396, - /* 1090 */ 1739, 1726, 1623, 86, 1711, 542, 1713, 1714, 538, 540, - /* 1100 */ 559, 262, 1091, 1779, 1680, 404, 539, 311, 1775, 1858, - /* 1110 */ 403, 1095, 1102, 1100, 126, 405, 409, 1236, 1836, 410, + /* 1090 */ 1740, 1727, 1624, 86, 1712, 542, 1714, 1715, 538, 540, + /* 1100 */ 559, 262, 1091, 1780, 1681, 404, 539, 311, 1776, 1860, + /* 1110 */ 403, 1095, 1102, 1100, 126, 405, 409, 1236, 1838, 410, /* 1120 */ 418, 1239, 421, 170, 172, 1238, 422, 423, 1240, 426, - /* 1130 */ 424, 1739, 175, 177, 86, 1711, 542, 1713, 1714, 538, - /* 1140 */ 1710, 559, 427, 1237, 1779, 428, 180, 450, 311, 1775, - /* 1150 */ 1858, 431, 452, 66, 183, 1523, 187, 1519, 481, 1797, - /* 1160 */ 189, 128, 307, 89, 260, 129, 1521, 1726, 482, 485, - /* 1170 */ 201, 204, 488, 1517, 130, 540, 131, 490, 207, 1235, - /* 1180 */ 1680, 210, 539, 1810, 504, 546, 6, 492, 1662, 1820, - /* 1190 */ 1661, 1819, 513, 1800, 222, 520, 142, 499, 500, 224, - /* 1200 */ 498, 225, 493, 1710, 501, 1330, 310, 1739, 497, 226, - /* 1210 */ 278, 1711, 542, 1713, 1714, 538, 507, 559, 214, 217, - /* 1220 */ 1710, 116, 1234, 42, 1841, 18, 526, 529, 227, 523, - /* 1230 */ 1726, 233, 312, 1861, 544, 545, 1845, 320, 540, 1794, - /* 1240 */ 1629, 549, 246, 1680, 1628, 539, 551, 1726, 261, 550, - /* 1250 */ 154, 77, 1534, 248, 1842, 540, 75, 562, 520, 264, - /* 1260 */ 1680, 228, 539, 1760, 1577, 1506, 256, 49, 636, 266, - /* 1270 */ 1739, 270, 1674, 278, 1711, 542, 1713, 1714, 538, 279, - /* 1280 */ 559, 271, 268, 1710, 141, 236, 1673, 1739, 530, 60, - /* 1290 */ 87, 1711, 542, 1713, 1714, 538, 238, 559, 1672, 1845, - /* 1300 */ 1779, 1710, 338, 1669, 531, 1775, 340, 341, 1201, 1202, - /* 1310 */ 1726, 159, 345, 152, 1667, 347, 348, 1842, 537, 349, - /* 1320 */ 1666, 1665, 351, 1680, 353, 539, 1664, 355, 1726, 1663, - /* 1330 */ 357, 1647, 160, 360, 361, 1177, 540, 1176, 1641, 1640, - /* 1340 */ 366, 1680, 367, 539, 1639, 1638, 1149, 1616, 63, 1615, - /* 1350 */ 1739, 378, 1710, 286, 1711, 542, 1713, 1714, 538, 536, - /* 1360 */ 559, 533, 1751, 1614, 1613, 1612, 1611, 1610, 1739, 379, - /* 1370 */ 640, 138, 1711, 542, 1713, 1714, 538, 381, 559, 1726, - /* 1380 */ 1609, 1608, 1607, 1606, 258, 1605, 1604, 540, 1603, 1602, - /* 1390 */ 1601, 1600, 1680, 516, 539, 1599, 145, 1598, 1597, 1596, - /* 1400 */ 120, 1595, 631, 627, 623, 619, 257, 1594, 1593, 1592, - /* 1410 */ 1591, 1590, 1589, 1710, 1151, 1588, 521, 1859, 1587, 1739, - /* 1420 */ 1586, 117, 87, 1711, 542, 1713, 1714, 538, 1463, 559, - /* 1430 */ 1431, 83, 1779, 168, 251, 146, 970, 1776, 969, 111, - /* 1440 */ 1726, 520, 1430, 169, 414, 1655, 1649, 416, 540, 1637, - /* 1450 */ 112, 174, 1636, 1680, 176, 539, 1626, 1512, 179, 1462, - /* 1460 */ 115, 1460, 434, 998, 433, 1458, 1710, 552, 438, 1456, - /* 1470 */ 432, 1454, 437, 436, 441, 229, 1786, 515, 442, 514, - /* 1480 */ 1739, 440, 1845, 282, 1711, 542, 1713, 1714, 538, 1710, - /* 1490 */ 559, 444, 445, 1726, 1443, 494, 154, 446, 208, 1442, - /* 1500 */ 1842, 540, 1429, 1514, 186, 1106, 1680, 516, 539, 1105, - /* 1510 */ 1513, 1031, 1452, 1030, 1029, 1028, 1726, 1182, 606, 202, - /* 1520 */ 608, 1025, 512, 47, 540, 1024, 304, 1023, 1447, 1680, - /* 1530 */ 305, 539, 469, 1739, 1445, 117, 138, 1711, 542, 1713, - /* 1540 */ 1714, 538, 315, 559, 306, 1710, 1428, 472, 474, 1427, - /* 1550 */ 88, 476, 1654, 1184, 51, 520, 1739, 1648, 483, 287, - /* 1560 */ 1711, 542, 1713, 1714, 538, 1635, 559, 1634, 1633, 1625, - /* 1570 */ 71, 15, 1726, 4, 115, 209, 39, 1371, 23, 213, - /* 1580 */ 537, 205, 1860, 484, 45, 1680, 211, 539, 50, 229, - /* 1590 */ 1786, 515, 139, 514, 220, 215, 1845, 132, 1710, 1355, - /* 1600 */ 219, 24, 221, 1348, 1700, 72, 230, 1710, 143, 1327, - /* 1610 */ 152, 25, 1739, 1326, 1842, 286, 1711, 542, 1713, 1714, - /* 1620 */ 538, 1710, 559, 44, 1752, 1726, 1388, 17, 1383, 1377, - /* 1630 */ 10, 1382, 313, 540, 1726, 1387, 1386, 314, 1680, 19, - /* 1640 */ 539, 1269, 540, 1268, 31, 1290, 144, 1680, 1726, 539, + /* 1130 */ 424, 1740, 175, 177, 86, 1712, 542, 1714, 1715, 538, + /* 1140 */ 1711, 559, 427, 1237, 1780, 428, 180, 450, 311, 1776, + /* 1150 */ 1860, 431, 452, 66, 183, 1524, 187, 1520, 481, 1799, + /* 1160 */ 189, 128, 307, 89, 260, 129, 1522, 1727, 482, 485, + /* 1170 */ 201, 204, 488, 1518, 130, 540, 131, 490, 207, 1235, + /* 1180 */ 1681, 210, 539, 1812, 504, 546, 6, 492, 1663, 1822, + /* 1190 */ 1662, 1821, 513, 1802, 222, 520, 142, 499, 500, 224, + /* 1200 */ 498, 225, 493, 1711, 501, 1331, 310, 1740, 497, 226, + /* 1210 */ 278, 1712, 542, 1714, 1715, 538, 507, 559, 214, 217, + /* 1220 */ 1711, 116, 1234, 42, 1843, 18, 526, 529, 227, 523, + /* 1230 */ 1727, 233, 312, 1863, 544, 545, 1847, 320, 540, 1796, + /* 1240 */ 1630, 549, 246, 1681, 1629, 539, 551, 1727, 261, 550, + /* 1250 */ 154, 77, 1535, 248, 1844, 540, 75, 562, 520, 264, + /* 1260 */ 1681, 228, 539, 1761, 1578, 1507, 256, 49, 636, 266, + /* 1270 */ 1740, 270, 1675, 278, 1712, 542, 1714, 1715, 538, 279, + /* 1280 */ 559, 271, 268, 1711, 141, 236, 1674, 1740, 530, 60, + /* 1290 */ 87, 1712, 542, 1714, 1715, 538, 238, 559, 1673, 1847, + /* 1300 */ 1780, 1711, 338, 1670, 531, 1776, 340, 341, 1201, 1202, + /* 1310 */ 1727, 159, 345, 152, 1668, 347, 348, 1844, 537, 349, + /* 1320 */ 1667, 1666, 351, 1681, 353, 539, 1665, 355, 1727, 1664, + /* 1330 */ 357, 1648, 160, 360, 361, 1177, 540, 1176, 1642, 1641, + /* 1340 */ 366, 1681, 367, 539, 1640, 1639, 1149, 1617, 63, 1616, + /* 1350 */ 1740, 378, 1711, 286, 1712, 542, 1714, 1715, 538, 536, + /* 1360 */ 559, 533, 1752, 1615, 1614, 1613, 1612, 1611, 1740, 379, + /* 1370 */ 640, 138, 1712, 542, 1714, 1715, 538, 381, 559, 1727, + /* 1380 */ 1610, 1609, 1608, 1607, 258, 1606, 1605, 540, 1604, 1603, + /* 1390 */ 1602, 1601, 1681, 516, 539, 1600, 145, 1599, 1598, 1597, + /* 1400 */ 120, 1596, 631, 627, 623, 619, 257, 1595, 1594, 1593, + /* 1410 */ 1592, 1591, 1590, 1711, 1151, 1589, 521, 1861, 1588, 1740, + /* 1420 */ 1587, 117, 87, 1712, 542, 1714, 1715, 538, 1464, 559, + /* 1430 */ 1432, 83, 1780, 168, 251, 146, 970, 1777, 969, 111, + /* 1440 */ 1727, 520, 1431, 169, 414, 1656, 1650, 416, 540, 1638, + /* 1450 */ 112, 174, 1637, 1681, 176, 539, 1627, 1513, 179, 1463, + /* 1460 */ 115, 1461, 434, 998, 433, 1459, 1711, 552, 438, 1457, + /* 1470 */ 432, 1455, 437, 436, 441, 229, 1788, 515, 442, 514, + /* 1480 */ 1740, 440, 1847, 282, 1712, 542, 1714, 1715, 538, 1711, + /* 1490 */ 559, 444, 445, 1727, 1444, 494, 154, 446, 208, 1443, + /* 1500 */ 1844, 540, 1430, 1515, 186, 1106, 1681, 516, 539, 1105, + /* 1510 */ 1514, 1031, 1453, 1030, 1029, 1028, 1727, 1182, 606, 202, + /* 1520 */ 608, 1025, 512, 47, 540, 1024, 304, 1023, 1448, 1681, + /* 1530 */ 305, 539, 469, 1740, 1446, 117, 138, 1712, 542, 1714, + /* 1540 */ 1715, 538, 315, 559, 306, 1711, 1429, 472, 474, 1428, + /* 1550 */ 88, 476, 1655, 1184, 51, 520, 1740, 1649, 483, 287, + /* 1560 */ 1712, 542, 1714, 1715, 538, 1636, 559, 1635, 1634, 1626, + /* 1570 */ 71, 15, 1727, 4, 115, 209, 39, 1372, 23, 213, + /* 1580 */ 537, 205, 1862, 484, 45, 1681, 211, 539, 50, 229, + /* 1590 */ 1788, 515, 139, 514, 220, 215, 1847, 132, 1711, 1356, + /* 1600 */ 219, 24, 221, 1349, 1701, 72, 230, 1711, 143, 1328, + /* 1610 */ 152, 25, 1740, 1327, 1844, 286, 1712, 542, 1714, 1715, + /* 1620 */ 538, 1711, 559, 44, 1753, 1727, 1389, 17, 1384, 1378, + /* 1630 */ 10, 1383, 313, 540, 1727, 1388, 1387, 314, 1681, 19, + /* 1640 */ 539, 1269, 540, 1268, 31, 1290, 144, 1681, 1727, 539, /* 1650 */ 156, 317, 16, 12, 13, 20, 540, 43, 1254, 21, - /* 1660 */ 319, 1680, 1710, 539, 1624, 1739, 541, 247, 287, 1711, - /* 1670 */ 542, 1713, 1714, 538, 1739, 559, 241, 287, 1711, 542, - /* 1680 */ 1713, 1714, 538, 1710, 559, 1353, 243, 547, 1739, 1726, - /* 1690 */ 245, 273, 1711, 542, 1713, 1714, 538, 540, 559, 73, - /* 1700 */ 74, 78, 1680, 1699, 539, 252, 1742, 1224, 1271, 249, - /* 1710 */ 1726, 1092, 558, 46, 561, 563, 327, 1089, 540, 565, - /* 1720 */ 567, 568, 570, 1680, 1086, 539, 571, 573, 1080, 1739, - /* 1730 */ 574, 576, 274, 1711, 542, 1713, 1714, 538, 1078, 559, - /* 1740 */ 1069, 1710, 1084, 583, 577, 1101, 1083, 79, 1082, 1081, - /* 1750 */ 1739, 80, 1710, 281, 1711, 542, 1713, 1714, 538, 57, - /* 1760 */ 559, 254, 1097, 1710, 996, 592, 1020, 595, 1726, 255, - /* 1770 */ 1038, 1013, 1018, 1017, 1016, 1035, 540, 1015, 1014, 1726, - /* 1780 */ 1012, 1680, 1011, 539, 1033, 1008, 1007, 540, 1006, 1003, - /* 1790 */ 1726, 1002, 1680, 1001, 539, 1459, 617, 616, 540, 618, - /* 1800 */ 1457, 620, 621, 1680, 622, 539, 1455, 624, 1739, 625, - /* 1810 */ 626, 283, 1711, 542, 1713, 1714, 538, 1453, 559, 1739, - /* 1820 */ 629, 628, 275, 1711, 542, 1713, 1714, 538, 1710, 559, - /* 1830 */ 1739, 630, 1441, 284, 1711, 542, 1713, 1714, 538, 632, - /* 1840 */ 559, 1426, 634, 635, 1710, 1210, 265, 638, 639, 1401, - /* 1850 */ 1401, 1401, 1401, 1401, 1401, 1726, 1401, 1401, 1401, 1401, - /* 1860 */ 1401, 1401, 1401, 540, 1401, 1401, 1401, 1401, 1680, 1401, - /* 1870 */ 539, 1726, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 540, - /* 1880 */ 1401, 1401, 1401, 1401, 1680, 1401, 539, 1401, 1401, 1401, - /* 1890 */ 1401, 1401, 1401, 1710, 1401, 1739, 1401, 1401, 276, 1711, - /* 1900 */ 542, 1713, 1714, 538, 1401, 559, 1401, 1710, 1401, 1401, - /* 1910 */ 1401, 1739, 1401, 1401, 285, 1711, 542, 1713, 1714, 538, - /* 1920 */ 1726, 559, 1401, 1401, 1401, 1401, 1401, 1401, 540, 1401, - /* 1930 */ 1401, 1401, 1401, 1680, 1726, 539, 1401, 1401, 1401, 1401, - /* 1940 */ 1401, 1401, 540, 1401, 1401, 1401, 1401, 1680, 1710, 539, - /* 1950 */ 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, - /* 1960 */ 1739, 1401, 1401, 277, 1711, 542, 1713, 1714, 538, 1710, - /* 1970 */ 559, 1401, 1401, 1401, 1739, 1726, 1401, 1722, 1711, 542, - /* 1980 */ 1713, 1714, 538, 540, 559, 1401, 1401, 1401, 1680, 1401, - /* 1990 */ 539, 1401, 1401, 1401, 1401, 1401, 1726, 1401, 1401, 1401, - /* 2000 */ 1401, 1401, 1401, 1401, 540, 1401, 1401, 1401, 1401, 1680, - /* 2010 */ 1401, 539, 1401, 1401, 1401, 1739, 1401, 1401, 1721, 1711, - /* 2020 */ 542, 1713, 1714, 538, 1401, 559, 1401, 1710, 1401, 1401, - /* 2030 */ 1401, 1401, 1401, 1401, 1401, 1401, 1739, 1401, 1710, 1720, - /* 2040 */ 1711, 542, 1713, 1714, 538, 1401, 559, 1401, 1401, 1710, - /* 2050 */ 1401, 1401, 1401, 1401, 1726, 1401, 1401, 1401, 1401, 1401, - /* 2060 */ 1401, 1401, 540, 1401, 1401, 1726, 1401, 1680, 1401, 539, - /* 2070 */ 1401, 1401, 1401, 540, 1401, 1401, 1726, 1401, 1680, 1401, - /* 2080 */ 539, 1401, 1401, 1401, 540, 1401, 1401, 1401, 1401, 1680, - /* 2090 */ 1710, 539, 1401, 1401, 1739, 1401, 1401, 296, 1711, 542, - /* 2100 */ 1713, 1714, 538, 1401, 559, 1739, 1401, 1401, 295, 1711, - /* 2110 */ 542, 1713, 1714, 538, 1710, 559, 1739, 1726, 1401, 297, - /* 2120 */ 1711, 542, 1713, 1714, 538, 540, 559, 1401, 1401, 1401, - /* 2130 */ 1680, 1401, 539, 1401, 1401, 1401, 1401, 1401, 1401, 1401, - /* 2140 */ 1401, 1726, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 540, - /* 2150 */ 1401, 1401, 1401, 1401, 1680, 1401, 539, 1739, 1401, 1401, - /* 2160 */ 294, 1711, 542, 1713, 1714, 538, 1401, 559, 1401, 1401, - /* 2170 */ 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, 1401, - /* 2180 */ 1401, 1739, 1401, 1401, 280, 1711, 542, 1713, 1714, 538, - /* 2190 */ 1401, 559, + /* 1660 */ 319, 1681, 1711, 539, 1625, 1740, 541, 247, 287, 1712, + /* 1670 */ 542, 1714, 1715, 538, 1740, 559, 241, 287, 1712, 542, + /* 1680 */ 1714, 1715, 538, 1711, 559, 1354, 243, 547, 1740, 1727, + /* 1690 */ 245, 273, 1712, 542, 1714, 1715, 538, 540, 559, 73, + /* 1700 */ 74, 78, 1681, 1700, 539, 252, 1743, 1224, 1271, 249, + /* 1710 */ 1727, 1092, 558, 46, 561, 563, 327, 1089, 540, 565, + /* 1720 */ 567, 568, 570, 1681, 1086, 539, 571, 573, 1080, 1740, + /* 1730 */ 574, 576, 274, 1712, 542, 1714, 1715, 538, 1078, 559, + /* 1740 */ 1069, 1711, 1084, 583, 577, 1101, 1083, 79, 1082, 1081, + /* 1750 */ 1740, 80, 1711, 281, 1712, 542, 1714, 1715, 538, 57, + /* 1760 */ 559, 254, 1097, 1711, 996, 592, 1020, 595, 1727, 255, + /* 1770 */ 1038, 1013, 1018, 1017, 1016, 1035, 540, 1015, 1014, 1727, + /* 1780 */ 1012, 1681, 1011, 539, 1033, 1008, 1007, 540, 1006, 1003, + /* 1790 */ 1727, 1002, 1681, 1001, 539, 1460, 617, 616, 540, 618, + /* 1800 */ 1458, 620, 621, 1681, 622, 539, 1456, 624, 1740, 625, + /* 1810 */ 626, 283, 1712, 542, 1714, 1715, 538, 1454, 559, 1740, + /* 1820 */ 629, 628, 275, 1712, 542, 1714, 1715, 538, 1711, 559, + /* 1830 */ 1740, 630, 1442, 284, 1712, 542, 1714, 1715, 538, 632, + /* 1840 */ 559, 1427, 634, 635, 1711, 1210, 265, 638, 639, 1402, + /* 1850 */ 1402, 1402, 1402, 1402, 1402, 1727, 1402, 1402, 1402, 1402, + /* 1860 */ 1402, 1402, 1402, 540, 1402, 1402, 1402, 1402, 1681, 1402, + /* 1870 */ 539, 1727, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 540, + /* 1880 */ 1402, 1402, 1402, 1402, 1681, 1402, 539, 1402, 1402, 1402, + /* 1890 */ 1402, 1402, 1402, 1711, 1402, 1740, 1402, 1402, 276, 1712, + /* 1900 */ 542, 1714, 1715, 538, 1402, 559, 1402, 1711, 1402, 1402, + /* 1910 */ 1402, 1740, 1402, 1402, 285, 1712, 542, 1714, 1715, 538, + /* 1920 */ 1727, 559, 1402, 1402, 1402, 1402, 1402, 1402, 540, 1402, + /* 1930 */ 1402, 1402, 1402, 1681, 1727, 539, 1402, 1402, 1402, 1402, + /* 1940 */ 1402, 1402, 540, 1402, 1402, 1402, 1402, 1681, 1711, 539, + /* 1950 */ 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, + /* 1960 */ 1740, 1402, 1402, 277, 1712, 542, 1714, 1715, 538, 1711, + /* 1970 */ 559, 1402, 1402, 1402, 1740, 1727, 1402, 1723, 1712, 542, + /* 1980 */ 1714, 1715, 538, 540, 559, 1402, 1402, 1402, 1681, 1402, + /* 1990 */ 539, 1402, 1402, 1402, 1402, 1402, 1727, 1402, 1402, 1402, + /* 2000 */ 1402, 1402, 1402, 1402, 540, 1402, 1402, 1402, 1402, 1681, + /* 2010 */ 1402, 539, 1402, 1402, 1402, 1740, 1402, 1402, 1722, 1712, + /* 2020 */ 542, 1714, 1715, 538, 1402, 559, 1402, 1711, 1402, 1402, + /* 2030 */ 1402, 1402, 1402, 1402, 1402, 1402, 1740, 1402, 1711, 1721, + /* 2040 */ 1712, 542, 1714, 1715, 538, 1402, 559, 1402, 1402, 1711, + /* 2050 */ 1402, 1402, 1402, 1402, 1727, 1402, 1402, 1402, 1402, 1402, + /* 2060 */ 1402, 1402, 540, 1402, 1402, 1727, 1402, 1681, 1402, 539, + /* 2070 */ 1402, 1402, 1402, 540, 1402, 1402, 1727, 1402, 1681, 1402, + /* 2080 */ 539, 1402, 1402, 1402, 540, 1402, 1402, 1402, 1402, 1681, + /* 2090 */ 1711, 539, 1402, 1402, 1740, 1402, 1402, 296, 1712, 542, + /* 2100 */ 1714, 1715, 538, 1402, 559, 1740, 1402, 1402, 295, 1712, + /* 2110 */ 542, 1714, 1715, 538, 1711, 559, 1740, 1727, 1402, 297, + /* 2120 */ 1712, 542, 1714, 1715, 538, 540, 559, 1402, 1402, 1402, + /* 2130 */ 1681, 1402, 539, 1402, 1402, 1402, 1402, 1402, 1402, 1402, + /* 2140 */ 1402, 1727, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 540, + /* 2150 */ 1402, 1402, 1402, 1402, 1681, 1402, 539, 1740, 1402, 1402, + /* 2160 */ 294, 1712, 542, 1714, 1715, 538, 1402, 559, 1402, 1402, + /* 2170 */ 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, 1402, + /* 2180 */ 1402, 1740, 1402, 1402, 280, 1712, 542, 1714, 1715, 538, + /* 2190 */ 1402, 559, }; static const YYCODETYPE yy_lookahead[] = { /* 0 */ 274, 341, 273, 277, 248, 274, 250, 251, 277, 242, @@ -763,71 +763,71 @@ static const short yy_reduce_ofst[] = { /* 260 */ 977, 1005, 1013, 1015, 1014, 1039, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 10 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 20 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 30 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 40 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 50 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 60 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1468, 1399, - /* 70 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 80 */ 1399, 1399, 1399, 1466, 1617, 1399, 1781, 1399, 1399, 1399, - /* 90 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 100 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 110 */ 1399, 1399, 1399, 1468, 1399, 1792, 1792, 1792, 1466, 1399, - /* 120 */ 1399, 1399, 1399, 1399, 1399, 1399, 1562, 1399, 1399, 1399, - /* 130 */ 1399, 1399, 1399, 1399, 1399, 1650, 1399, 1399, 1862, 1399, - /* 140 */ 1399, 1656, 1816, 1399, 1399, 1399, 1399, 1515, 1808, 1784, - /* 150 */ 1798, 1785, 1847, 1847, 1847, 1801, 1399, 1812, 1399, 1399, - /* 160 */ 1399, 1642, 1399, 1399, 1622, 1619, 1619, 1399, 1399, 1399, - /* 170 */ 1399, 1468, 1399, 1468, 1399, 1399, 1468, 1399, 1468, 1399, - /* 180 */ 1399, 1468, 1468, 1399, 1468, 1399, 1399, 1399, 1399, 1399, - /* 190 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 200 */ 1399, 1399, 1466, 1652, 1399, 1466, 1399, 1399, 1466, 1399, - /* 210 */ 1399, 1466, 1399, 1399, 1823, 1821, 1399, 1823, 1821, 1399, - /* 220 */ 1399, 1399, 1835, 1831, 1823, 1839, 1837, 1814, 1812, 1798, - /* 230 */ 1399, 1399, 1399, 1853, 1849, 1865, 1853, 1849, 1853, 1849, - /* 240 */ 1399, 1821, 1399, 1399, 1821, 1399, 1627, 1399, 1399, 1466, - /* 250 */ 1399, 1466, 1399, 1531, 1399, 1399, 1399, 1466, 1399, 1644, - /* 260 */ 1658, 1565, 1565, 1565, 1469, 1404, 1399, 1399, 1399, 1399, - /* 270 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1527, - /* 280 */ 1725, 1834, 1833, 1757, 1756, 1755, 1753, 1724, 1399, 1399, - /* 290 */ 1399, 1399, 1399, 1399, 1718, 1719, 1717, 1716, 1399, 1399, - /* 300 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 310 */ 1399, 1782, 1399, 1850, 1854, 1399, 1399, 1399, 1701, 1399, - /* 320 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 330 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 340 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 350 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 360 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 370 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 380 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 390 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 400 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 410 */ 1399, 1399, 1399, 1433, 1399, 1399, 1399, 1399, 1399, 1399, - /* 420 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 430 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 440 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 450 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 460 */ 1399, 1496, 1495, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 470 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 480 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 490 */ 1399, 1399, 1399, 1399, 1399, 1805, 1815, 1399, 1399, 1399, - /* 500 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 510 */ 1701, 1399, 1832, 1399, 1791, 1787, 1399, 1399, 1783, 1399, - /* 520 */ 1399, 1848, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 530 */ 1399, 1777, 1399, 1750, 1399, 1399, 1399, 1399, 1399, 1399, - /* 540 */ 1399, 1399, 1712, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 550 */ 1399, 1399, 1399, 1399, 1399, 1700, 1399, 1741, 1399, 1399, - /* 560 */ 1399, 1399, 1399, 1399, 1399, 1399, 1559, 1399, 1399, 1399, - /* 570 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1544, - /* 580 */ 1542, 1541, 1540, 1399, 1537, 1399, 1399, 1399, 1399, 1568, - /* 590 */ 1567, 1399, 1399, 1399, 1399, 1399, 1399, 1488, 1399, 1399, - /* 600 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1479, 1399, 1478, - /* 610 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 620 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 630 */ 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, 1399, - /* 640 */ 1399, + /* 0 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 10 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 20 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 30 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 40 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 50 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 60 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1469, 1400, + /* 70 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 80 */ 1400, 1400, 1400, 1467, 1618, 1400, 1782, 1400, 1400, 1400, + /* 90 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 100 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 110 */ 1400, 1400, 1400, 1469, 1400, 1794, 1794, 1794, 1467, 1400, + /* 120 */ 1400, 1400, 1400, 1400, 1400, 1400, 1563, 1400, 1400, 1400, + /* 130 */ 1400, 1400, 1400, 1400, 1400, 1651, 1400, 1400, 1864, 1400, + /* 140 */ 1400, 1657, 1818, 1400, 1400, 1400, 1400, 1516, 1810, 1786, + /* 150 */ 1800, 1787, 1849, 1849, 1849, 1803, 1400, 1814, 1400, 1400, + /* 160 */ 1400, 1643, 1400, 1400, 1623, 1620, 1620, 1400, 1400, 1400, + /* 170 */ 1400, 1469, 1400, 1469, 1400, 1400, 1469, 1400, 1469, 1400, + /* 180 */ 1400, 1469, 1469, 1400, 1469, 1400, 1400, 1400, 1400, 1400, + /* 190 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 200 */ 1400, 1400, 1467, 1653, 1400, 1467, 1400, 1400, 1467, 1400, + /* 210 */ 1400, 1467, 1400, 1400, 1825, 1823, 1400, 1825, 1823, 1400, + /* 220 */ 1400, 1400, 1837, 1833, 1825, 1841, 1839, 1816, 1814, 1800, + /* 230 */ 1400, 1400, 1784, 1855, 1851, 1867, 1855, 1851, 1855, 1851, + /* 240 */ 1400, 1823, 1400, 1400, 1823, 1400, 1628, 1400, 1400, 1467, + /* 250 */ 1400, 1467, 1400, 1532, 1400, 1400, 1400, 1467, 1400, 1645, + /* 260 */ 1659, 1566, 1566, 1566, 1470, 1405, 1400, 1400, 1400, 1400, + /* 270 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1528, + /* 280 */ 1726, 1836, 1835, 1758, 1757, 1756, 1754, 1725, 1400, 1400, + /* 290 */ 1400, 1400, 1400, 1400, 1719, 1720, 1718, 1717, 1400, 1400, + /* 300 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 310 */ 1400, 1783, 1400, 1852, 1856, 1400, 1400, 1400, 1702, 1400, + /* 320 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 330 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 340 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 350 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 360 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 370 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 380 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 390 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 400 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 410 */ 1400, 1400, 1400, 1434, 1400, 1400, 1400, 1400, 1400, 1400, + /* 420 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 430 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 440 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 450 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 460 */ 1400, 1497, 1496, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 470 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 480 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 490 */ 1400, 1400, 1400, 1400, 1400, 1807, 1817, 1400, 1400, 1400, + /* 500 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 510 */ 1702, 1400, 1834, 1400, 1793, 1789, 1400, 1400, 1785, 1400, + /* 520 */ 1400, 1850, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 530 */ 1400, 1778, 1400, 1751, 1400, 1400, 1400, 1400, 1400, 1400, + /* 540 */ 1400, 1400, 1713, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 550 */ 1400, 1400, 1400, 1400, 1400, 1701, 1400, 1742, 1400, 1400, + /* 560 */ 1400, 1400, 1400, 1400, 1400, 1400, 1560, 1400, 1400, 1400, + /* 570 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1545, + /* 580 */ 1543, 1542, 1541, 1400, 1538, 1400, 1400, 1400, 1400, 1569, + /* 590 */ 1568, 1400, 1400, 1400, 1400, 1400, 1400, 1489, 1400, 1400, + /* 600 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1480, 1400, 1479, + /* 610 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 620 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 630 */ 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, 1400, + /* 640 */ 1400, }; /********** End of lemon-generated parsing tables *****************************/ @@ -1508,7 +1508,7 @@ static const char *const yyTokenName[] = { /* 329 */ "boolean_value_expression", /* 330 */ "boolean_primary", /* 331 */ "common_expression", - /* 332 */ "from_clause", + /* 332 */ "from_clause_opt", /* 333 */ "table_reference_list", /* 334 */ "table_reference", /* 335 */ "table_primary", @@ -1928,91 +1928,92 @@ static const char *const yyRuleName[] = { /* 378 */ "boolean_primary ::= NK_LP boolean_value_expression NK_RP", /* 379 */ "common_expression ::= expression", /* 380 */ "common_expression ::= boolean_value_expression", - /* 381 */ "from_clause ::= FROM table_reference_list", - /* 382 */ "table_reference_list ::= table_reference", - /* 383 */ "table_reference_list ::= table_reference_list NK_COMMA table_reference", - /* 384 */ "table_reference ::= table_primary", - /* 385 */ "table_reference ::= joined_table", - /* 386 */ "table_primary ::= table_name alias_opt", - /* 387 */ "table_primary ::= db_name NK_DOT table_name alias_opt", - /* 388 */ "table_primary ::= subquery alias_opt", - /* 389 */ "table_primary ::= parenthesized_joined_table", - /* 390 */ "alias_opt ::=", - /* 391 */ "alias_opt ::= table_alias", - /* 392 */ "alias_opt ::= AS table_alias", - /* 393 */ "parenthesized_joined_table ::= NK_LP joined_table NK_RP", - /* 394 */ "parenthesized_joined_table ::= NK_LP parenthesized_joined_table NK_RP", - /* 395 */ "joined_table ::= table_reference join_type JOIN table_reference ON search_condition", - /* 396 */ "join_type ::=", - /* 397 */ "join_type ::= INNER", - /* 398 */ "query_specification ::= SELECT set_quantifier_opt select_list from_clause where_clause_opt partition_by_clause_opt range_opt every_opt fill_opt twindow_clause_opt group_by_clause_opt having_clause_opt", - /* 399 */ "set_quantifier_opt ::=", - /* 400 */ "set_quantifier_opt ::= DISTINCT", - /* 401 */ "set_quantifier_opt ::= ALL", - /* 402 */ "select_list ::= NK_STAR", - /* 403 */ "select_list ::= select_sublist", - /* 404 */ "select_sublist ::= select_item", - /* 405 */ "select_sublist ::= select_sublist NK_COMMA select_item", - /* 406 */ "select_item ::= common_expression", - /* 407 */ "select_item ::= common_expression column_alias", - /* 408 */ "select_item ::= common_expression AS column_alias", - /* 409 */ "select_item ::= table_name NK_DOT NK_STAR", - /* 410 */ "where_clause_opt ::=", - /* 411 */ "where_clause_opt ::= WHERE search_condition", - /* 412 */ "partition_by_clause_opt ::=", - /* 413 */ "partition_by_clause_opt ::= PARTITION BY expression_list", - /* 414 */ "twindow_clause_opt ::=", - /* 415 */ "twindow_clause_opt ::= SESSION NK_LP column_reference NK_COMMA duration_literal NK_RP", - /* 416 */ "twindow_clause_opt ::= STATE_WINDOW NK_LP expression NK_RP", - /* 417 */ "twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_RP sliding_opt fill_opt", - /* 418 */ "twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt fill_opt", - /* 419 */ "sliding_opt ::=", - /* 420 */ "sliding_opt ::= SLIDING NK_LP duration_literal NK_RP", - /* 421 */ "fill_opt ::=", - /* 422 */ "fill_opt ::= FILL NK_LP fill_mode NK_RP", - /* 423 */ "fill_opt ::= FILL NK_LP VALUE NK_COMMA literal_list NK_RP", - /* 424 */ "fill_mode ::= NONE", - /* 425 */ "fill_mode ::= PREV", - /* 426 */ "fill_mode ::= NULL", - /* 427 */ "fill_mode ::= LINEAR", - /* 428 */ "fill_mode ::= NEXT", - /* 429 */ "group_by_clause_opt ::=", - /* 430 */ "group_by_clause_opt ::= GROUP BY group_by_list", - /* 431 */ "group_by_list ::= expression", - /* 432 */ "group_by_list ::= group_by_list NK_COMMA expression", - /* 433 */ "having_clause_opt ::=", - /* 434 */ "having_clause_opt ::= HAVING search_condition", - /* 435 */ "range_opt ::=", - /* 436 */ "range_opt ::= RANGE NK_LP expression NK_COMMA expression NK_RP", - /* 437 */ "every_opt ::=", - /* 438 */ "every_opt ::= EVERY NK_LP duration_literal NK_RP", - /* 439 */ "query_expression ::= query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt", - /* 440 */ "query_expression_body ::= query_primary", - /* 441 */ "query_expression_body ::= query_expression_body UNION ALL query_expression_body", - /* 442 */ "query_expression_body ::= query_expression_body UNION query_expression_body", - /* 443 */ "query_primary ::= query_specification", - /* 444 */ "query_primary ::= NK_LP query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt NK_RP", - /* 445 */ "order_by_clause_opt ::=", - /* 446 */ "order_by_clause_opt ::= ORDER BY sort_specification_list", - /* 447 */ "slimit_clause_opt ::=", - /* 448 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER", - /* 449 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER", - /* 450 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER", - /* 451 */ "limit_clause_opt ::=", - /* 452 */ "limit_clause_opt ::= LIMIT NK_INTEGER", - /* 453 */ "limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER", - /* 454 */ "limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER", - /* 455 */ "subquery ::= NK_LP query_expression NK_RP", - /* 456 */ "search_condition ::= common_expression", - /* 457 */ "sort_specification_list ::= sort_specification", - /* 458 */ "sort_specification_list ::= sort_specification_list NK_COMMA sort_specification", - /* 459 */ "sort_specification ::= expression ordering_specification_opt null_ordering_opt", - /* 460 */ "ordering_specification_opt ::=", - /* 461 */ "ordering_specification_opt ::= ASC", - /* 462 */ "ordering_specification_opt ::= DESC", - /* 463 */ "null_ordering_opt ::=", - /* 464 */ "null_ordering_opt ::= NULLS FIRST", - /* 465 */ "null_ordering_opt ::= NULLS LAST", + /* 381 */ "from_clause_opt ::=", + /* 382 */ "from_clause_opt ::= FROM table_reference_list", + /* 383 */ "table_reference_list ::= table_reference", + /* 384 */ "table_reference_list ::= table_reference_list NK_COMMA table_reference", + /* 385 */ "table_reference ::= table_primary", + /* 386 */ "table_reference ::= joined_table", + /* 387 */ "table_primary ::= table_name alias_opt", + /* 388 */ "table_primary ::= db_name NK_DOT table_name alias_opt", + /* 389 */ "table_primary ::= subquery alias_opt", + /* 390 */ "table_primary ::= parenthesized_joined_table", + /* 391 */ "alias_opt ::=", + /* 392 */ "alias_opt ::= table_alias", + /* 393 */ "alias_opt ::= AS table_alias", + /* 394 */ "parenthesized_joined_table ::= NK_LP joined_table NK_RP", + /* 395 */ "parenthesized_joined_table ::= NK_LP parenthesized_joined_table NK_RP", + /* 396 */ "joined_table ::= table_reference join_type JOIN table_reference ON search_condition", + /* 397 */ "join_type ::=", + /* 398 */ "join_type ::= INNER", + /* 399 */ "query_specification ::= SELECT set_quantifier_opt select_list from_clause_opt where_clause_opt partition_by_clause_opt range_opt every_opt fill_opt twindow_clause_opt group_by_clause_opt having_clause_opt", + /* 400 */ "set_quantifier_opt ::=", + /* 401 */ "set_quantifier_opt ::= DISTINCT", + /* 402 */ "set_quantifier_opt ::= ALL", + /* 403 */ "select_list ::= NK_STAR", + /* 404 */ "select_list ::= select_sublist", + /* 405 */ "select_sublist ::= select_item", + /* 406 */ "select_sublist ::= select_sublist NK_COMMA select_item", + /* 407 */ "select_item ::= common_expression", + /* 408 */ "select_item ::= common_expression column_alias", + /* 409 */ "select_item ::= common_expression AS column_alias", + /* 410 */ "select_item ::= table_name NK_DOT NK_STAR", + /* 411 */ "where_clause_opt ::=", + /* 412 */ "where_clause_opt ::= WHERE search_condition", + /* 413 */ "partition_by_clause_opt ::=", + /* 414 */ "partition_by_clause_opt ::= PARTITION BY expression_list", + /* 415 */ "twindow_clause_opt ::=", + /* 416 */ "twindow_clause_opt ::= SESSION NK_LP column_reference NK_COMMA duration_literal NK_RP", + /* 417 */ "twindow_clause_opt ::= STATE_WINDOW NK_LP expression NK_RP", + /* 418 */ "twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_RP sliding_opt fill_opt", + /* 419 */ "twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt fill_opt", + /* 420 */ "sliding_opt ::=", + /* 421 */ "sliding_opt ::= SLIDING NK_LP duration_literal NK_RP", + /* 422 */ "fill_opt ::=", + /* 423 */ "fill_opt ::= FILL NK_LP fill_mode NK_RP", + /* 424 */ "fill_opt ::= FILL NK_LP VALUE NK_COMMA literal_list NK_RP", + /* 425 */ "fill_mode ::= NONE", + /* 426 */ "fill_mode ::= PREV", + /* 427 */ "fill_mode ::= NULL", + /* 428 */ "fill_mode ::= LINEAR", + /* 429 */ "fill_mode ::= NEXT", + /* 430 */ "group_by_clause_opt ::=", + /* 431 */ "group_by_clause_opt ::= GROUP BY group_by_list", + /* 432 */ "group_by_list ::= expression", + /* 433 */ "group_by_list ::= group_by_list NK_COMMA expression", + /* 434 */ "having_clause_opt ::=", + /* 435 */ "having_clause_opt ::= HAVING search_condition", + /* 436 */ "range_opt ::=", + /* 437 */ "range_opt ::= RANGE NK_LP expression NK_COMMA expression NK_RP", + /* 438 */ "every_opt ::=", + /* 439 */ "every_opt ::= EVERY NK_LP duration_literal NK_RP", + /* 440 */ "query_expression ::= query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt", + /* 441 */ "query_expression_body ::= query_primary", + /* 442 */ "query_expression_body ::= query_expression_body UNION ALL query_expression_body", + /* 443 */ "query_expression_body ::= query_expression_body UNION query_expression_body", + /* 444 */ "query_primary ::= query_specification", + /* 445 */ "query_primary ::= NK_LP query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt NK_RP", + /* 446 */ "order_by_clause_opt ::=", + /* 447 */ "order_by_clause_opt ::= ORDER BY sort_specification_list", + /* 448 */ "slimit_clause_opt ::=", + /* 449 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER", + /* 450 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER", + /* 451 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER", + /* 452 */ "limit_clause_opt ::=", + /* 453 */ "limit_clause_opt ::= LIMIT NK_INTEGER", + /* 454 */ "limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER", + /* 455 */ "limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER", + /* 456 */ "subquery ::= NK_LP query_expression NK_RP", + /* 457 */ "search_condition ::= common_expression", + /* 458 */ "sort_specification_list ::= sort_specification", + /* 459 */ "sort_specification_list ::= sort_specification_list NK_COMMA sort_specification", + /* 460 */ "sort_specification ::= expression ordering_specification_opt null_ordering_opt", + /* 461 */ "ordering_specification_opt ::=", + /* 462 */ "ordering_specification_opt ::= ASC", + /* 463 */ "ordering_specification_opt ::= DESC", + /* 464 */ "null_ordering_opt ::=", + /* 465 */ "null_ordering_opt ::= NULLS FIRST", + /* 466 */ "null_ordering_opt ::= NULLS LAST", }; #endif /* NDEBUG */ @@ -2180,7 +2181,7 @@ static void yy_destructor( case 329: /* boolean_value_expression */ case 330: /* boolean_primary */ case 331: /* common_expression */ - case 332: /* from_clause */ + case 332: /* from_clause_opt */ case 333: /* table_reference_list */ case 334: /* table_reference */ case 335: /* table_primary */ @@ -2988,91 +2989,92 @@ static const struct { { 330, -3 }, /* (378) boolean_primary ::= NK_LP boolean_value_expression NK_RP */ { 331, -1 }, /* (379) common_expression ::= expression */ { 331, -1 }, /* (380) common_expression ::= boolean_value_expression */ - { 332, -2 }, /* (381) from_clause ::= FROM table_reference_list */ - { 333, -1 }, /* (382) table_reference_list ::= table_reference */ - { 333, -3 }, /* (383) table_reference_list ::= table_reference_list NK_COMMA table_reference */ - { 334, -1 }, /* (384) table_reference ::= table_primary */ - { 334, -1 }, /* (385) table_reference ::= joined_table */ - { 335, -2 }, /* (386) table_primary ::= table_name alias_opt */ - { 335, -4 }, /* (387) table_primary ::= db_name NK_DOT table_name alias_opt */ - { 335, -2 }, /* (388) table_primary ::= subquery alias_opt */ - { 335, -1 }, /* (389) table_primary ::= parenthesized_joined_table */ - { 337, 0 }, /* (390) alias_opt ::= */ - { 337, -1 }, /* (391) alias_opt ::= table_alias */ - { 337, -2 }, /* (392) alias_opt ::= AS table_alias */ - { 338, -3 }, /* (393) parenthesized_joined_table ::= NK_LP joined_table NK_RP */ - { 338, -3 }, /* (394) parenthesized_joined_table ::= NK_LP parenthesized_joined_table NK_RP */ - { 336, -6 }, /* (395) joined_table ::= table_reference join_type JOIN table_reference ON search_condition */ - { 339, 0 }, /* (396) join_type ::= */ - { 339, -1 }, /* (397) join_type ::= INNER */ - { 341, -12 }, /* (398) query_specification ::= SELECT set_quantifier_opt select_list from_clause where_clause_opt partition_by_clause_opt range_opt every_opt fill_opt twindow_clause_opt group_by_clause_opt having_clause_opt */ - { 342, 0 }, /* (399) set_quantifier_opt ::= */ - { 342, -1 }, /* (400) set_quantifier_opt ::= DISTINCT */ - { 342, -1 }, /* (401) set_quantifier_opt ::= ALL */ - { 343, -1 }, /* (402) select_list ::= NK_STAR */ - { 343, -1 }, /* (403) select_list ::= select_sublist */ - { 351, -1 }, /* (404) select_sublist ::= select_item */ - { 351, -3 }, /* (405) select_sublist ::= select_sublist NK_COMMA select_item */ - { 352, -1 }, /* (406) select_item ::= common_expression */ - { 352, -2 }, /* (407) select_item ::= common_expression column_alias */ - { 352, -3 }, /* (408) select_item ::= common_expression AS column_alias */ - { 352, -3 }, /* (409) select_item ::= table_name NK_DOT NK_STAR */ - { 310, 0 }, /* (410) where_clause_opt ::= */ - { 310, -2 }, /* (411) where_clause_opt ::= WHERE search_condition */ - { 344, 0 }, /* (412) partition_by_clause_opt ::= */ - { 344, -3 }, /* (413) partition_by_clause_opt ::= PARTITION BY expression_list */ - { 348, 0 }, /* (414) twindow_clause_opt ::= */ - { 348, -6 }, /* (415) twindow_clause_opt ::= SESSION NK_LP column_reference NK_COMMA duration_literal NK_RP */ - { 348, -4 }, /* (416) twindow_clause_opt ::= STATE_WINDOW NK_LP expression NK_RP */ - { 348, -6 }, /* (417) twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_RP sliding_opt fill_opt */ - { 348, -8 }, /* (418) twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt fill_opt */ - { 296, 0 }, /* (419) sliding_opt ::= */ - { 296, -4 }, /* (420) sliding_opt ::= SLIDING NK_LP duration_literal NK_RP */ - { 347, 0 }, /* (421) fill_opt ::= */ - { 347, -4 }, /* (422) fill_opt ::= FILL NK_LP fill_mode NK_RP */ - { 347, -6 }, /* (423) fill_opt ::= FILL NK_LP VALUE NK_COMMA literal_list NK_RP */ - { 353, -1 }, /* (424) fill_mode ::= NONE */ - { 353, -1 }, /* (425) fill_mode ::= PREV */ - { 353, -1 }, /* (426) fill_mode ::= NULL */ - { 353, -1 }, /* (427) fill_mode ::= LINEAR */ - { 353, -1 }, /* (428) fill_mode ::= NEXT */ - { 349, 0 }, /* (429) group_by_clause_opt ::= */ - { 349, -3 }, /* (430) group_by_clause_opt ::= GROUP BY group_by_list */ - { 354, -1 }, /* (431) group_by_list ::= expression */ - { 354, -3 }, /* (432) group_by_list ::= group_by_list NK_COMMA expression */ - { 350, 0 }, /* (433) having_clause_opt ::= */ - { 350, -2 }, /* (434) having_clause_opt ::= HAVING search_condition */ - { 345, 0 }, /* (435) range_opt ::= */ - { 345, -6 }, /* (436) range_opt ::= RANGE NK_LP expression NK_COMMA expression NK_RP */ - { 346, 0 }, /* (437) every_opt ::= */ - { 346, -4 }, /* (438) every_opt ::= EVERY NK_LP duration_literal NK_RP */ - { 300, -4 }, /* (439) query_expression ::= query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt */ - { 355, -1 }, /* (440) query_expression_body ::= query_primary */ - { 355, -4 }, /* (441) query_expression_body ::= query_expression_body UNION ALL query_expression_body */ - { 355, -3 }, /* (442) query_expression_body ::= query_expression_body UNION query_expression_body */ - { 359, -1 }, /* (443) query_primary ::= query_specification */ - { 359, -6 }, /* (444) query_primary ::= NK_LP query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt NK_RP */ - { 356, 0 }, /* (445) order_by_clause_opt ::= */ - { 356, -3 }, /* (446) order_by_clause_opt ::= ORDER BY sort_specification_list */ - { 357, 0 }, /* (447) slimit_clause_opt ::= */ - { 357, -2 }, /* (448) slimit_clause_opt ::= SLIMIT NK_INTEGER */ - { 357, -4 }, /* (449) slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER */ - { 357, -4 }, /* (450) slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER */ - { 358, 0 }, /* (451) limit_clause_opt ::= */ - { 358, -2 }, /* (452) limit_clause_opt ::= LIMIT NK_INTEGER */ - { 358, -4 }, /* (453) limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER */ - { 358, -4 }, /* (454) limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER */ - { 319, -3 }, /* (455) subquery ::= NK_LP query_expression NK_RP */ - { 340, -1 }, /* (456) search_condition ::= common_expression */ - { 360, -1 }, /* (457) sort_specification_list ::= sort_specification */ - { 360, -3 }, /* (458) sort_specification_list ::= sort_specification_list NK_COMMA sort_specification */ - { 361, -3 }, /* (459) sort_specification ::= expression ordering_specification_opt null_ordering_opt */ - { 362, 0 }, /* (460) ordering_specification_opt ::= */ - { 362, -1 }, /* (461) ordering_specification_opt ::= ASC */ - { 362, -1 }, /* (462) ordering_specification_opt ::= DESC */ - { 363, 0 }, /* (463) null_ordering_opt ::= */ - { 363, -2 }, /* (464) null_ordering_opt ::= NULLS FIRST */ - { 363, -2 }, /* (465) null_ordering_opt ::= NULLS LAST */ + { 332, 0 }, /* (381) from_clause_opt ::= */ + { 332, -2 }, /* (382) from_clause_opt ::= FROM table_reference_list */ + { 333, -1 }, /* (383) table_reference_list ::= table_reference */ + { 333, -3 }, /* (384) table_reference_list ::= table_reference_list NK_COMMA table_reference */ + { 334, -1 }, /* (385) table_reference ::= table_primary */ + { 334, -1 }, /* (386) table_reference ::= joined_table */ + { 335, -2 }, /* (387) table_primary ::= table_name alias_opt */ + { 335, -4 }, /* (388) table_primary ::= db_name NK_DOT table_name alias_opt */ + { 335, -2 }, /* (389) table_primary ::= subquery alias_opt */ + { 335, -1 }, /* (390) table_primary ::= parenthesized_joined_table */ + { 337, 0 }, /* (391) alias_opt ::= */ + { 337, -1 }, /* (392) alias_opt ::= table_alias */ + { 337, -2 }, /* (393) alias_opt ::= AS table_alias */ + { 338, -3 }, /* (394) parenthesized_joined_table ::= NK_LP joined_table NK_RP */ + { 338, -3 }, /* (395) parenthesized_joined_table ::= NK_LP parenthesized_joined_table NK_RP */ + { 336, -6 }, /* (396) joined_table ::= table_reference join_type JOIN table_reference ON search_condition */ + { 339, 0 }, /* (397) join_type ::= */ + { 339, -1 }, /* (398) join_type ::= INNER */ + { 341, -12 }, /* (399) query_specification ::= SELECT set_quantifier_opt select_list from_clause_opt where_clause_opt partition_by_clause_opt range_opt every_opt fill_opt twindow_clause_opt group_by_clause_opt having_clause_opt */ + { 342, 0 }, /* (400) set_quantifier_opt ::= */ + { 342, -1 }, /* (401) set_quantifier_opt ::= DISTINCT */ + { 342, -1 }, /* (402) set_quantifier_opt ::= ALL */ + { 343, -1 }, /* (403) select_list ::= NK_STAR */ + { 343, -1 }, /* (404) select_list ::= select_sublist */ + { 351, -1 }, /* (405) select_sublist ::= select_item */ + { 351, -3 }, /* (406) select_sublist ::= select_sublist NK_COMMA select_item */ + { 352, -1 }, /* (407) select_item ::= common_expression */ + { 352, -2 }, /* (408) select_item ::= common_expression column_alias */ + { 352, -3 }, /* (409) select_item ::= common_expression AS column_alias */ + { 352, -3 }, /* (410) select_item ::= table_name NK_DOT NK_STAR */ + { 310, 0 }, /* (411) where_clause_opt ::= */ + { 310, -2 }, /* (412) where_clause_opt ::= WHERE search_condition */ + { 344, 0 }, /* (413) partition_by_clause_opt ::= */ + { 344, -3 }, /* (414) partition_by_clause_opt ::= PARTITION BY expression_list */ + { 348, 0 }, /* (415) twindow_clause_opt ::= */ + { 348, -6 }, /* (416) twindow_clause_opt ::= SESSION NK_LP column_reference NK_COMMA duration_literal NK_RP */ + { 348, -4 }, /* (417) twindow_clause_opt ::= STATE_WINDOW NK_LP expression NK_RP */ + { 348, -6 }, /* (418) twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_RP sliding_opt fill_opt */ + { 348, -8 }, /* (419) twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt fill_opt */ + { 296, 0 }, /* (420) sliding_opt ::= */ + { 296, -4 }, /* (421) sliding_opt ::= SLIDING NK_LP duration_literal NK_RP */ + { 347, 0 }, /* (422) fill_opt ::= */ + { 347, -4 }, /* (423) fill_opt ::= FILL NK_LP fill_mode NK_RP */ + { 347, -6 }, /* (424) fill_opt ::= FILL NK_LP VALUE NK_COMMA literal_list NK_RP */ + { 353, -1 }, /* (425) fill_mode ::= NONE */ + { 353, -1 }, /* (426) fill_mode ::= PREV */ + { 353, -1 }, /* (427) fill_mode ::= NULL */ + { 353, -1 }, /* (428) fill_mode ::= LINEAR */ + { 353, -1 }, /* (429) fill_mode ::= NEXT */ + { 349, 0 }, /* (430) group_by_clause_opt ::= */ + { 349, -3 }, /* (431) group_by_clause_opt ::= GROUP BY group_by_list */ + { 354, -1 }, /* (432) group_by_list ::= expression */ + { 354, -3 }, /* (433) group_by_list ::= group_by_list NK_COMMA expression */ + { 350, 0 }, /* (434) having_clause_opt ::= */ + { 350, -2 }, /* (435) having_clause_opt ::= HAVING search_condition */ + { 345, 0 }, /* (436) range_opt ::= */ + { 345, -6 }, /* (437) range_opt ::= RANGE NK_LP expression NK_COMMA expression NK_RP */ + { 346, 0 }, /* (438) every_opt ::= */ + { 346, -4 }, /* (439) every_opt ::= EVERY NK_LP duration_literal NK_RP */ + { 300, -4 }, /* (440) query_expression ::= query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt */ + { 355, -1 }, /* (441) query_expression_body ::= query_primary */ + { 355, -4 }, /* (442) query_expression_body ::= query_expression_body UNION ALL query_expression_body */ + { 355, -3 }, /* (443) query_expression_body ::= query_expression_body UNION query_expression_body */ + { 359, -1 }, /* (444) query_primary ::= query_specification */ + { 359, -6 }, /* (445) query_primary ::= NK_LP query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt NK_RP */ + { 356, 0 }, /* (446) order_by_clause_opt ::= */ + { 356, -3 }, /* (447) order_by_clause_opt ::= ORDER BY sort_specification_list */ + { 357, 0 }, /* (448) slimit_clause_opt ::= */ + { 357, -2 }, /* (449) slimit_clause_opt ::= SLIMIT NK_INTEGER */ + { 357, -4 }, /* (450) slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER */ + { 357, -4 }, /* (451) slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER */ + { 358, 0 }, /* (452) limit_clause_opt ::= */ + { 358, -2 }, /* (453) limit_clause_opt ::= LIMIT NK_INTEGER */ + { 358, -4 }, /* (454) limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER */ + { 358, -4 }, /* (455) limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER */ + { 319, -3 }, /* (456) subquery ::= NK_LP query_expression NK_RP */ + { 340, -1 }, /* (457) search_condition ::= common_expression */ + { 360, -1 }, /* (458) sort_specification_list ::= sort_specification */ + { 360, -3 }, /* (459) sort_specification_list ::= sort_specification_list NK_COMMA sort_specification */ + { 361, -3 }, /* (460) sort_specification ::= expression ordering_specification_opt null_ordering_opt */ + { 362, 0 }, /* (461) ordering_specification_opt ::= */ + { 362, -1 }, /* (462) ordering_specification_opt ::= ASC */ + { 362, -1 }, /* (463) ordering_specification_opt ::= DESC */ + { 363, 0 }, /* (464) null_ordering_opt ::= */ + { 363, -2 }, /* (465) null_ordering_opt ::= NULLS FIRST */ + { 363, -2 }, /* (466) null_ordering_opt ::= NULLS LAST */ }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -3349,7 +3351,7 @@ static YYACTIONTYPE yy_reduce( case 66: /* exists_opt ::= */ yytestcase(yyruleno==66); case 240: /* analyze_opt ::= */ yytestcase(yyruleno==240); case 248: /* agg_func_opt ::= */ yytestcase(yyruleno==248); - case 399: /* set_quantifier_opt ::= */ yytestcase(yyruleno==399); + case 400: /* set_quantifier_opt ::= */ yytestcase(yyruleno==400); { yymsp[1].minor.yy481 = false; } break; case 65: /* exists_opt ::= IF EXISTS */ @@ -3491,8 +3493,8 @@ static YYACTIONTYPE yy_reduce( case 228: /* func_list ::= func */ yytestcase(yyruleno==228); case 295: /* literal_list ::= signed_literal */ yytestcase(yyruleno==295); case 349: /* other_para_list ::= star_func_para */ yytestcase(yyruleno==349); - case 404: /* select_sublist ::= select_item */ yytestcase(yyruleno==404); - case 457: /* sort_specification_list ::= sort_specification */ yytestcase(yyruleno==457); + case 405: /* select_sublist ::= select_item */ yytestcase(yyruleno==405); + case 458: /* sort_specification_list ::= sort_specification */ yytestcase(yyruleno==458); { yylhsminor.yy600 = createNodeList(pCxt, yymsp[0].minor.yy392); } yymsp[0].minor.yy600 = yylhsminor.yy600; break; @@ -3503,8 +3505,8 @@ static YYACTIONTYPE yy_reduce( case 229: /* func_list ::= func_list NK_COMMA func */ yytestcase(yyruleno==229); case 296: /* literal_list ::= literal_list NK_COMMA signed_literal */ yytestcase(yyruleno==296); case 350: /* other_para_list ::= other_para_list NK_COMMA star_func_para */ yytestcase(yyruleno==350); - case 405: /* select_sublist ::= select_sublist NK_COMMA select_item */ yytestcase(yyruleno==405); - case 458: /* sort_specification_list ::= sort_specification_list NK_COMMA sort_specification */ yytestcase(yyruleno==458); + case 406: /* select_sublist ::= select_sublist NK_COMMA select_item */ yytestcase(yyruleno==406); + case 459: /* sort_specification_list ::= sort_specification_list NK_COMMA sort_specification */ yytestcase(yyruleno==459); { yylhsminor.yy600 = addNodeToList(pCxt, yymsp[-2].minor.yy600, yymsp[0].minor.yy392); } yymsp[-2].minor.yy600 = yylhsminor.yy600; break; @@ -3585,9 +3587,9 @@ static YYACTIONTYPE yy_reduce( break; case 129: /* specific_tags_opt ::= */ case 160: /* tags_def_opt ::= */ yytestcase(yyruleno==160); - case 412: /* partition_by_clause_opt ::= */ yytestcase(yyruleno==412); - case 429: /* group_by_clause_opt ::= */ yytestcase(yyruleno==429); - case 445: /* order_by_clause_opt ::= */ yytestcase(yyruleno==445); + case 413: /* partition_by_clause_opt ::= */ yytestcase(yyruleno==413); + case 430: /* group_by_clause_opt ::= */ yytestcase(yyruleno==430); + case 446: /* order_by_clause_opt ::= */ yytestcase(yyruleno==446); { yymsp[1].minor.yy600 = NULL; } break; case 130: /* specific_tags_opt ::= NK_LP col_name_list NK_RP */ @@ -3678,7 +3680,7 @@ static YYACTIONTYPE yy_reduce( break; case 161: /* tags_def_opt ::= tags_def */ case 348: /* star_func_para_list ::= other_para_list */ yytestcase(yyruleno==348); - case 403: /* select_list ::= select_sublist */ yytestcase(yyruleno==403); + case 404: /* select_list ::= select_sublist */ yytestcase(yyruleno==404); { yylhsminor.yy600 = yymsp[0].minor.yy600; } yymsp[0].minor.yy600 = yylhsminor.yy600; break; @@ -3851,15 +3853,16 @@ static YYACTIONTYPE yy_reduce( case 217: /* like_pattern_opt ::= */ case 225: /* index_options ::= */ yytestcase(yyruleno==225); case 254: /* into_opt ::= */ yytestcase(yyruleno==254); - case 410: /* where_clause_opt ::= */ yytestcase(yyruleno==410); - case 414: /* twindow_clause_opt ::= */ yytestcase(yyruleno==414); - case 419: /* sliding_opt ::= */ yytestcase(yyruleno==419); - case 421: /* fill_opt ::= */ yytestcase(yyruleno==421); - case 433: /* having_clause_opt ::= */ yytestcase(yyruleno==433); - case 435: /* range_opt ::= */ yytestcase(yyruleno==435); - case 437: /* every_opt ::= */ yytestcase(yyruleno==437); - case 447: /* slimit_clause_opt ::= */ yytestcase(yyruleno==447); - case 451: /* limit_clause_opt ::= */ yytestcase(yyruleno==451); + case 381: /* from_clause_opt ::= */ yytestcase(yyruleno==381); + case 411: /* where_clause_opt ::= */ yytestcase(yyruleno==411); + case 415: /* twindow_clause_opt ::= */ yytestcase(yyruleno==415); + case 420: /* sliding_opt ::= */ yytestcase(yyruleno==420); + case 422: /* fill_opt ::= */ yytestcase(yyruleno==422); + case 434: /* having_clause_opt ::= */ yytestcase(yyruleno==434); + case 436: /* range_opt ::= */ yytestcase(yyruleno==436); + case 438: /* every_opt ::= */ yytestcase(yyruleno==438); + case 448: /* slimit_clause_opt ::= */ yytestcase(yyruleno==448); + case 452: /* limit_clause_opt ::= */ yytestcase(yyruleno==452); { yymsp[1].minor.yy392 = NULL; } break; case 218: /* like_pattern_opt ::= LIKE NK_STRING */ @@ -3918,7 +3921,7 @@ static YYACTIONTYPE yy_reduce( break; case 241: /* analyze_opt ::= ANALYZE */ case 249: /* agg_func_opt ::= AGGREGATE */ yytestcase(yyruleno==249); - case 400: /* set_quantifier_opt ::= DISTINCT */ yytestcase(yyruleno==400); + case 401: /* set_quantifier_opt ::= DISTINCT */ yytestcase(yyruleno==401); { yymsp[0].minor.yy481 = true; } break; case 242: /* explain_options ::= */ @@ -3954,9 +3957,9 @@ static YYACTIONTYPE yy_reduce( { pCxt->pRootNode = createDropStreamStmt(pCxt, yymsp[-1].minor.yy481, &yymsp[0].minor.yy57); } break; case 255: /* into_opt ::= INTO full_table_name */ - case 381: /* from_clause ::= FROM table_reference_list */ yytestcase(yyruleno==381); - case 411: /* where_clause_opt ::= WHERE search_condition */ yytestcase(yyruleno==411); - case 434: /* having_clause_opt ::= HAVING search_condition */ yytestcase(yyruleno==434); + case 382: /* from_clause_opt ::= FROM table_reference_list */ yytestcase(yyruleno==382); + case 412: /* where_clause_opt ::= WHERE search_condition */ yytestcase(yyruleno==412); + case 435: /* having_clause_opt ::= HAVING search_condition */ yytestcase(yyruleno==435); { yymsp[-1].minor.yy392 = yymsp[0].minor.yy392; } break; case 256: /* stream_options ::= */ @@ -4040,12 +4043,12 @@ static YYACTIONTYPE yy_reduce( case 377: /* boolean_primary ::= predicate */ yytestcase(yyruleno==377); case 379: /* common_expression ::= expression */ yytestcase(yyruleno==379); case 380: /* common_expression ::= boolean_value_expression */ yytestcase(yyruleno==380); - case 382: /* table_reference_list ::= table_reference */ yytestcase(yyruleno==382); - case 384: /* table_reference ::= table_primary */ yytestcase(yyruleno==384); - case 385: /* table_reference ::= joined_table */ yytestcase(yyruleno==385); - case 389: /* table_primary ::= parenthesized_joined_table */ yytestcase(yyruleno==389); - case 440: /* query_expression_body ::= query_primary */ yytestcase(yyruleno==440); - case 443: /* query_primary ::= query_specification */ yytestcase(yyruleno==443); + case 383: /* table_reference_list ::= table_reference */ yytestcase(yyruleno==383); + case 385: /* table_reference ::= table_primary */ yytestcase(yyruleno==385); + case 386: /* table_reference ::= joined_table */ yytestcase(yyruleno==386); + case 390: /* table_primary ::= parenthesized_joined_table */ yytestcase(yyruleno==390); + case 441: /* query_expression_body ::= query_primary */ yytestcase(yyruleno==441); + case 444: /* query_primary ::= query_specification */ yytestcase(yyruleno==444); { yylhsminor.yy392 = yymsp[0].minor.yy392; } yymsp[0].minor.yy392 = yylhsminor.yy392; break; @@ -4105,8 +4108,8 @@ static YYACTIONTYPE yy_reduce( case 292: /* signed_literal ::= duration_literal */ case 294: /* signed_literal ::= literal_func */ yytestcase(yyruleno==294); case 351: /* star_func_para ::= expression */ yytestcase(yyruleno==351); - case 406: /* select_item ::= common_expression */ yytestcase(yyruleno==406); - case 456: /* search_condition ::= common_expression */ yytestcase(yyruleno==456); + case 407: /* select_item ::= common_expression */ yytestcase(yyruleno==407); + case 457: /* search_condition ::= common_expression */ yytestcase(yyruleno==457); { yylhsminor.yy392 = releaseRawExprNode(pCxt, yymsp[0].minor.yy392); } yymsp[0].minor.yy392 = yylhsminor.yy392; break; @@ -4221,7 +4224,7 @@ static YYACTIONTYPE yy_reduce( yymsp[0].minor.yy600 = yylhsminor.yy600; break; case 352: /* star_func_para ::= table_name NK_DOT NK_STAR */ - case 409: /* select_item ::= table_name NK_DOT NK_STAR */ yytestcase(yyruleno==409); + case 410: /* select_item ::= table_name NK_DOT NK_STAR */ yytestcase(yyruleno==410); { yylhsminor.yy392 = createColumnNode(pCxt, &yymsp[-2].minor.yy57, &yymsp[0].minor.yy0); } yymsp[-2].minor.yy392 = yylhsminor.yy392; break; @@ -4330,47 +4333,47 @@ static YYACTIONTYPE yy_reduce( } yymsp[-2].minor.yy392 = yylhsminor.yy392; break; - case 383: /* table_reference_list ::= table_reference_list NK_COMMA table_reference */ + case 384: /* table_reference_list ::= table_reference_list NK_COMMA table_reference */ { yylhsminor.yy392 = createJoinTableNode(pCxt, JOIN_TYPE_INNER, yymsp[-2].minor.yy392, yymsp[0].minor.yy392, NULL); } yymsp[-2].minor.yy392 = yylhsminor.yy392; break; - case 386: /* table_primary ::= table_name alias_opt */ + case 387: /* table_primary ::= table_name alias_opt */ { yylhsminor.yy392 = createRealTableNode(pCxt, NULL, &yymsp[-1].minor.yy57, &yymsp[0].minor.yy57); } yymsp[-1].minor.yy392 = yylhsminor.yy392; break; - case 387: /* table_primary ::= db_name NK_DOT table_name alias_opt */ + case 388: /* table_primary ::= db_name NK_DOT table_name alias_opt */ { yylhsminor.yy392 = createRealTableNode(pCxt, &yymsp[-3].minor.yy57, &yymsp[-1].minor.yy57, &yymsp[0].minor.yy57); } yymsp[-3].minor.yy392 = yylhsminor.yy392; break; - case 388: /* table_primary ::= subquery alias_opt */ + case 389: /* table_primary ::= subquery alias_opt */ { yylhsminor.yy392 = createTempTableNode(pCxt, releaseRawExprNode(pCxt, yymsp[-1].minor.yy392), &yymsp[0].minor.yy57); } yymsp[-1].minor.yy392 = yylhsminor.yy392; break; - case 390: /* alias_opt ::= */ + case 391: /* alias_opt ::= */ { yymsp[1].minor.yy57 = nil_token; } break; - case 391: /* alias_opt ::= table_alias */ + case 392: /* alias_opt ::= table_alias */ { yylhsminor.yy57 = yymsp[0].minor.yy57; } yymsp[0].minor.yy57 = yylhsminor.yy57; break; - case 392: /* alias_opt ::= AS table_alias */ + case 393: /* alias_opt ::= AS table_alias */ { yymsp[-1].minor.yy57 = yymsp[0].minor.yy57; } break; - case 393: /* parenthesized_joined_table ::= NK_LP joined_table NK_RP */ - case 394: /* parenthesized_joined_table ::= NK_LP parenthesized_joined_table NK_RP */ yytestcase(yyruleno==394); + case 394: /* parenthesized_joined_table ::= NK_LP joined_table NK_RP */ + case 395: /* parenthesized_joined_table ::= NK_LP parenthesized_joined_table NK_RP */ yytestcase(yyruleno==395); { yymsp[-2].minor.yy392 = yymsp[-1].minor.yy392; } break; - case 395: /* joined_table ::= table_reference join_type JOIN table_reference ON search_condition */ + case 396: /* joined_table ::= table_reference join_type JOIN table_reference ON search_condition */ { yylhsminor.yy392 = createJoinTableNode(pCxt, yymsp[-4].minor.yy204, yymsp[-5].minor.yy392, yymsp[-2].minor.yy392, yymsp[0].minor.yy392); } yymsp[-5].minor.yy392 = yylhsminor.yy392; break; - case 396: /* join_type ::= */ + case 397: /* join_type ::= */ { yymsp[1].minor.yy204 = JOIN_TYPE_INNER; } break; - case 397: /* join_type ::= INNER */ + case 398: /* join_type ::= INNER */ { yymsp[0].minor.yy204 = JOIN_TYPE_INNER; } break; - case 398: /* query_specification ::= SELECT set_quantifier_opt select_list from_clause where_clause_opt partition_by_clause_opt range_opt every_opt fill_opt twindow_clause_opt group_by_clause_opt having_clause_opt */ + case 399: /* query_specification ::= SELECT set_quantifier_opt select_list from_clause_opt where_clause_opt partition_by_clause_opt range_opt every_opt fill_opt twindow_clause_opt group_by_clause_opt having_clause_opt */ { yymsp[-11].minor.yy392 = createSelectStmt(pCxt, yymsp[-10].minor.yy481, yymsp[-9].minor.yy600, yymsp[-8].minor.yy392); yymsp[-11].minor.yy392 = addWhereClause(pCxt, yymsp[-11].minor.yy392, yymsp[-7].minor.yy392); @@ -4383,74 +4386,74 @@ static YYACTIONTYPE yy_reduce( yymsp[-11].minor.yy392 = addFillClause(pCxt, yymsp[-11].minor.yy392, yymsp[-3].minor.yy392); } break; - case 401: /* set_quantifier_opt ::= ALL */ + case 402: /* set_quantifier_opt ::= ALL */ { yymsp[0].minor.yy481 = false; } break; - case 402: /* select_list ::= NK_STAR */ + case 403: /* select_list ::= NK_STAR */ { yymsp[0].minor.yy600 = NULL; } break; - case 407: /* select_item ::= common_expression column_alias */ + case 408: /* select_item ::= common_expression column_alias */ { yylhsminor.yy392 = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, yymsp[-1].minor.yy392), &yymsp[0].minor.yy57); } yymsp[-1].minor.yy392 = yylhsminor.yy392; break; - case 408: /* select_item ::= common_expression AS column_alias */ + case 409: /* select_item ::= common_expression AS column_alias */ { yylhsminor.yy392 = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, yymsp[-2].minor.yy392), &yymsp[0].minor.yy57); } yymsp[-2].minor.yy392 = yylhsminor.yy392; break; - case 413: /* partition_by_clause_opt ::= PARTITION BY expression_list */ - case 430: /* group_by_clause_opt ::= GROUP BY group_by_list */ yytestcase(yyruleno==430); - case 446: /* order_by_clause_opt ::= ORDER BY sort_specification_list */ yytestcase(yyruleno==446); + case 414: /* partition_by_clause_opt ::= PARTITION BY expression_list */ + case 431: /* group_by_clause_opt ::= GROUP BY group_by_list */ yytestcase(yyruleno==431); + case 447: /* order_by_clause_opt ::= ORDER BY sort_specification_list */ yytestcase(yyruleno==447); { yymsp[-2].minor.yy600 = yymsp[0].minor.yy600; } break; - case 415: /* twindow_clause_opt ::= SESSION NK_LP column_reference NK_COMMA duration_literal NK_RP */ + case 416: /* twindow_clause_opt ::= SESSION NK_LP column_reference NK_COMMA duration_literal NK_RP */ { yymsp[-5].minor.yy392 = createSessionWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy392), releaseRawExprNode(pCxt, yymsp[-1].minor.yy392)); } break; - case 416: /* twindow_clause_opt ::= STATE_WINDOW NK_LP expression NK_RP */ + case 417: /* twindow_clause_opt ::= STATE_WINDOW NK_LP expression NK_RP */ { yymsp[-3].minor.yy392 = createStateWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-1].minor.yy392)); } break; - case 417: /* twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_RP sliding_opt fill_opt */ + case 418: /* twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_RP sliding_opt fill_opt */ { yymsp[-5].minor.yy392 = createIntervalWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy392), NULL, yymsp[-1].minor.yy392, yymsp[0].minor.yy392); } break; - case 418: /* twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt fill_opt */ + case 419: /* twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt fill_opt */ { yymsp[-7].minor.yy392 = createIntervalWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-5].minor.yy392), releaseRawExprNode(pCxt, yymsp[-3].minor.yy392), yymsp[-1].minor.yy392, yymsp[0].minor.yy392); } break; - case 420: /* sliding_opt ::= SLIDING NK_LP duration_literal NK_RP */ - case 438: /* every_opt ::= EVERY NK_LP duration_literal NK_RP */ yytestcase(yyruleno==438); + case 421: /* sliding_opt ::= SLIDING NK_LP duration_literal NK_RP */ + case 439: /* every_opt ::= EVERY NK_LP duration_literal NK_RP */ yytestcase(yyruleno==439); { yymsp[-3].minor.yy392 = releaseRawExprNode(pCxt, yymsp[-1].minor.yy392); } break; - case 422: /* fill_opt ::= FILL NK_LP fill_mode NK_RP */ + case 423: /* fill_opt ::= FILL NK_LP fill_mode NK_RP */ { yymsp[-3].minor.yy392 = createFillNode(pCxt, yymsp[-1].minor.yy270, NULL); } break; - case 423: /* fill_opt ::= FILL NK_LP VALUE NK_COMMA literal_list NK_RP */ + case 424: /* fill_opt ::= FILL NK_LP VALUE NK_COMMA literal_list NK_RP */ { yymsp[-5].minor.yy392 = createFillNode(pCxt, FILL_MODE_VALUE, createNodeListNode(pCxt, yymsp[-1].minor.yy600)); } break; - case 424: /* fill_mode ::= NONE */ + case 425: /* fill_mode ::= NONE */ { yymsp[0].minor.yy270 = FILL_MODE_NONE; } break; - case 425: /* fill_mode ::= PREV */ + case 426: /* fill_mode ::= PREV */ { yymsp[0].minor.yy270 = FILL_MODE_PREV; } break; - case 426: /* fill_mode ::= NULL */ + case 427: /* fill_mode ::= NULL */ { yymsp[0].minor.yy270 = FILL_MODE_NULL; } break; - case 427: /* fill_mode ::= LINEAR */ + case 428: /* fill_mode ::= LINEAR */ { yymsp[0].minor.yy270 = FILL_MODE_LINEAR; } break; - case 428: /* fill_mode ::= NEXT */ + case 429: /* fill_mode ::= NEXT */ { yymsp[0].minor.yy270 = FILL_MODE_NEXT; } break; - case 431: /* group_by_list ::= expression */ + case 432: /* group_by_list ::= expression */ { yylhsminor.yy600 = createNodeList(pCxt, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, yymsp[0].minor.yy392))); } yymsp[0].minor.yy600 = yylhsminor.yy600; break; - case 432: /* group_by_list ::= group_by_list NK_COMMA expression */ + case 433: /* group_by_list ::= group_by_list NK_COMMA expression */ { yylhsminor.yy600 = addNodeToList(pCxt, yymsp[-2].minor.yy600, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, yymsp[0].minor.yy392))); } yymsp[-2].minor.yy600 = yylhsminor.yy600; break; - case 436: /* range_opt ::= RANGE NK_LP expression NK_COMMA expression NK_RP */ + case 437: /* range_opt ::= RANGE NK_LP expression NK_COMMA expression NK_RP */ { yymsp[-5].minor.yy392 = createInterpTimeRange(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy392), releaseRawExprNode(pCxt, yymsp[-1].minor.yy392)); } break; - case 439: /* query_expression ::= query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt */ + case 440: /* query_expression ::= query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt */ { yylhsminor.yy392 = addOrderByClause(pCxt, yymsp[-3].minor.yy392, yymsp[-2].minor.yy600); yylhsminor.yy392 = addSlimitClause(pCxt, yylhsminor.yy392, yymsp[-1].minor.yy392); @@ -4458,56 +4461,56 @@ static YYACTIONTYPE yy_reduce( } yymsp[-3].minor.yy392 = yylhsminor.yy392; break; - case 441: /* query_expression_body ::= query_expression_body UNION ALL query_expression_body */ + case 442: /* query_expression_body ::= query_expression_body UNION ALL query_expression_body */ { yylhsminor.yy392 = createSetOperator(pCxt, SET_OP_TYPE_UNION_ALL, yymsp[-3].minor.yy392, yymsp[0].minor.yy392); } yymsp[-3].minor.yy392 = yylhsminor.yy392; break; - case 442: /* query_expression_body ::= query_expression_body UNION query_expression_body */ + case 443: /* query_expression_body ::= query_expression_body UNION query_expression_body */ { yylhsminor.yy392 = createSetOperator(pCxt, SET_OP_TYPE_UNION, yymsp[-2].minor.yy392, yymsp[0].minor.yy392); } yymsp[-2].minor.yy392 = yylhsminor.yy392; break; - case 444: /* query_primary ::= NK_LP query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt NK_RP */ + case 445: /* query_primary ::= NK_LP query_expression_body order_by_clause_opt slimit_clause_opt limit_clause_opt NK_RP */ { yymsp[-5].minor.yy392 = yymsp[-4].minor.yy392; } yy_destructor(yypParser,356,&yymsp[-3].minor); yy_destructor(yypParser,357,&yymsp[-2].minor); yy_destructor(yypParser,358,&yymsp[-1].minor); break; - case 448: /* slimit_clause_opt ::= SLIMIT NK_INTEGER */ - case 452: /* limit_clause_opt ::= LIMIT NK_INTEGER */ yytestcase(yyruleno==452); + case 449: /* slimit_clause_opt ::= SLIMIT NK_INTEGER */ + case 453: /* limit_clause_opt ::= LIMIT NK_INTEGER */ yytestcase(yyruleno==453); { yymsp[-1].minor.yy392 = createLimitNode(pCxt, &yymsp[0].minor.yy0, NULL); } break; - case 449: /* slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER */ - case 453: /* limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER */ yytestcase(yyruleno==453); + case 450: /* slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER */ + case 454: /* limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER */ yytestcase(yyruleno==454); { yymsp[-3].minor.yy392 = createLimitNode(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); } break; - case 450: /* slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER */ - case 454: /* limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER */ yytestcase(yyruleno==454); + case 451: /* slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER */ + case 455: /* limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER */ yytestcase(yyruleno==455); { yymsp[-3].minor.yy392 = createLimitNode(pCxt, &yymsp[0].minor.yy0, &yymsp[-2].minor.yy0); } break; - case 455: /* subquery ::= NK_LP query_expression NK_RP */ + case 456: /* subquery ::= NK_LP query_expression NK_RP */ { yylhsminor.yy392 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-1].minor.yy392); } yymsp[-2].minor.yy392 = yylhsminor.yy392; break; - case 459: /* sort_specification ::= expression ordering_specification_opt null_ordering_opt */ + case 460: /* sort_specification ::= expression ordering_specification_opt null_ordering_opt */ { yylhsminor.yy392 = createOrderByExprNode(pCxt, releaseRawExprNode(pCxt, yymsp[-2].minor.yy392), yymsp[-1].minor.yy162, yymsp[0].minor.yy529); } yymsp[-2].minor.yy392 = yylhsminor.yy392; break; - case 460: /* ordering_specification_opt ::= */ + case 461: /* ordering_specification_opt ::= */ { yymsp[1].minor.yy162 = ORDER_ASC; } break; - case 461: /* ordering_specification_opt ::= ASC */ + case 462: /* ordering_specification_opt ::= ASC */ { yymsp[0].minor.yy162 = ORDER_ASC; } break; - case 462: /* ordering_specification_opt ::= DESC */ + case 463: /* ordering_specification_opt ::= DESC */ { yymsp[0].minor.yy162 = ORDER_DESC; } break; - case 463: /* null_ordering_opt ::= */ + case 464: /* null_ordering_opt ::= */ { yymsp[1].minor.yy529 = NULL_ORDER_DEFAULT; } break; - case 464: /* null_ordering_opt ::= NULLS FIRST */ + case 465: /* null_ordering_opt ::= NULLS FIRST */ { yymsp[-1].minor.yy529 = NULL_ORDER_FIRST; } break; - case 465: /* null_ordering_opt ::= NULLS LAST */ + case 466: /* null_ordering_opt ::= NULLS LAST */ { yymsp[-1].minor.yy529 = NULL_ORDER_LAST; } break; default: diff --git a/source/libs/parser/test/parSelectTest.cpp b/source/libs/parser/test/parSelectTest.cpp index 11e09cd83d..e7ab1cb61b 100644 --- a/source/libs/parser/test/parSelectTest.cpp +++ b/source/libs/parser/test/parSelectTest.cpp @@ -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 diff --git a/source/libs/planner/src/planLogicCreater.c b/source/libs/planner/src/planLogicCreater.c index 36d2efc13f..eafc6ba37a 100644 --- a/source/libs/planner/src/planLogicCreater.c +++ b/source/libs/planner/src/planLogicCreater.c @@ -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); diff --git a/source/libs/planner/src/planOptimizer.c b/source/libs/planner/src/planOptimizer.c index cd3218cf94..3155828f32 100644 --- a/source/libs/planner/src/planOptimizer.c +++ b/source/libs/planner/src/planOptimizer.c @@ -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); diff --git a/source/libs/planner/src/planPhysiCreater.c b/source/libs/planner/src/planPhysiCreater.c index ff78370c52..37765edfc5 100644 --- a/source/libs/planner/src/planPhysiCreater.c +++ b/source/libs/planner/src/planPhysiCreater.c @@ -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: diff --git a/source/libs/planner/src/planSpliter.c b/source/libs/planner/src/planSpliter.c index 29119bf1d2..f0e0e84bd9 100644 --- a/source/libs/planner/src/planSpliter.c +++ b/source/libs/planner/src/planSpliter.c @@ -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; } diff --git a/source/libs/planner/test/planBasicTest.cpp b/source/libs/planner/test/planBasicTest.cpp index f74c7df355..790c418b17 100644 --- a/source/libs/planner/test/planBasicTest.cpp +++ b/source/libs/planner/test/planBasicTest.cpp @@ -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"); +} diff --git a/source/libs/sync/src/syncSnapshot.c b/source/libs/sync/src/syncSnapshot.c index 3e062d395f..ff3dc56f71 100644 --- a/source/libs/sync/src/syncSnapshot.c +++ b/source/libs/sync/src/syncSnapshot.c @@ -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); diff --git a/source/libs/sync/test/syncLogStoreCheck2.cpp b/source/libs/sync/test/syncLogStoreCheck2.cpp index 431b291ca7..80679bc85c 100644 --- a/source/libs/sync/test/syncLogStoreCheck2.cpp +++ b/source/libs/sync/test/syncLogStoreCheck2.cpp @@ -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); diff --git a/source/libs/transport/inc/transComm.h b/source/libs/transport/inc/transComm.h index 146b127422..327fe50814 100644 --- a/source/libs/transport/inc/transComm.h +++ b/source/libs/transport/inc/transComm.h @@ -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); diff --git a/source/libs/transport/inc/transLog.h b/source/libs/transport/inc/transLog.h index 81099941c6..121939787c 100644 --- a/source/libs/transport/inc/transLog.h +++ b/source/libs/transport/inc/transLog.h @@ -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 diff --git a/source/libs/transport/src/transCli.c b/source/libs/transport/src/transCli.c index 912c8b59c2..bf03ea26ba 100644 --- a/source/libs/transport/src/transCli.c +++ b/source/libs/transport/src/transCli.c @@ -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)); diff --git a/source/libs/transport/src/transSvr.c b/source/libs/transport/src/transSvr.c index f9558d7252..593a790a21 100644 --- a/source/libs/transport/src/transSvr.c +++ b/source/libs/transport/src/transSvr.c @@ -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; diff --git a/source/libs/wal/src/walRead.c b/source/libs/wal/src/walRead.c index b1129b441c..9bed6d230b 100644 --- a/source/libs/wal/src/walRead.c +++ b/source/libs/wal/src/walRead.c @@ -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; } diff --git a/tests/script/jenkins/basic.txt b/tests/script/jenkins/basic.txt index dbfd05146c..1ab6491736 100644 --- a/tests/script/jenkins/basic.txt +++ b/tests/script/jenkins/basic.txt @@ -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 diff --git a/tests/script/tsim/dnode/drop_dnode_has_mnode.sim b/tests/script/tsim/dnode/drop_dnode_has_mnode.sim index 1dbec2c04d..16cd2bb3b0 100644 --- a/tests/script/tsim/dnode/drop_dnode_has_mnode.sim +++ b/tests/script/tsim/dnode/drop_dnode_has_mnode.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] diff --git a/tests/script/tsim/dnode/drop_dnode_has_multi_vnode_replica1.sim b/tests/script/tsim/dnode/drop_dnode_has_multi_vnode_replica1.sim new file mode 100644 index 0000000000..15ad13b6fa --- /dev/null +++ b/tests/script/tsim/dnode/drop_dnode_has_multi_vnode_replica1.sim @@ -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 diff --git a/tests/script/tsim/dnode/drop_dnode_has_multi_vnode_replica3.sim b/tests/script/tsim/dnode/drop_dnode_has_multi_vnode_replica3.sim new file mode 100644 index 0000000000..35a2466297 --- /dev/null +++ b/tests/script/tsim/dnode/drop_dnode_has_multi_vnode_replica3.sim @@ -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 diff --git a/tests/script/tsim/dnode/drop_dnode_has_qnode_snode.sim b/tests/script/tsim/dnode/drop_dnode_has_qnode_snode.sim new file mode 100644 index 0000000000..6641ce053c --- /dev/null +++ b/tests/script/tsim/dnode/drop_dnode_has_qnode_snode.sim @@ -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 diff --git a/tests/script/tsim/dnode/drop_dnode_has_vnode_replica1.sim b/tests/script/tsim/dnode/drop_dnode_has_vnode_replica1.sim new file mode 100644 index 0000000000..63639877ee --- /dev/null +++ b/tests/script/tsim/dnode/drop_dnode_has_vnode_replica1.sim @@ -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 diff --git a/tests/script/tsim/dnode/drop_dnode_has_vnode_replica3.sim b/tests/script/tsim/dnode/drop_dnode_has_vnode_replica3.sim new file mode 100644 index 0000000000..91679a7e81 --- /dev/null +++ b/tests/script/tsim/dnode/drop_dnode_has_vnode_replica3.sim @@ -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 diff --git a/tests/system-test/2-query/json_tag.py b/tests/system-test/2-query/json_tag.py index 957e916e34..052ff923ac 100644 --- a/tests/system-test/2-query/json_tag.py +++ b/tests/system-test/2-query/json_tag.py @@ -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") diff --git a/tests/system-test/2-query/sample.py b/tests/system-test/2-query/sample.py index a84d93404a..33ef7e65db 100644 --- a/tests/system-test/2-query/sample.py +++ b/tests/system-test/2-query/sample.py @@ -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")