提交 e75dfd46 编写于 作者: H Hui Li

Merge branch 'develop' into hotfix/test

......@@ -286,7 +286,7 @@ Connection conn = DriverManager.getConnection(jdbcUrl);
> `6030` is the default port and `log` is the default database for system monitor.
A normal JDBC URL looks as follows:
`jdbc:TSDB://{host_ip}:{port}/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]`
`jdbc:TAOS://{host_ip}:{port}/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]`
values in `{}` are necessary while values in `[]` are optional。Each option in the above URL denotes:
......
......@@ -281,7 +281,7 @@ Connection conn = DriverManager.getConnection(jdbcUrl);
> 端口 6030 为默认连接端口,JDBC URL 中的 log 为系统本身的监控数据库。
TDengine 的 JDBC URL 规范格式为:
`jdbc:TSDB://{host_ip}:{port}/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]`
`jdbc:TAOS://{host_ip}:{port}/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]`
其中,`{}` 中的内容必须,`[]` 中为可选。配置参数说明如下:
......
......@@ -281,103 +281,100 @@ For the time being, TDengine supports subscription on one or multiple tables. It
## Java Connector
TDengine 为了方便 Java 应用使用,提供了遵循 JDBC 标准(3.0)API 规范的 `taos-jdbcdriver` 实现。目前可以通过 [Sonatype Repository][1] 搜索并下载。
To Java delevopers, TDengine provides `taos-jdbcdriver` according to the JDBC(3.0) API. Users can find and download it through [Sonatype Repository][1].
由于 TDengine 是使用 c 语言开发的,使用 taos-jdbcdriver 驱动包时需要依赖系统对应的本地函数库。
Since the native language of TDengine is C, the necessary TDengine library should be checked before using the taos-jdbcdriver:
* libtaos.so
在 linux 系统中成功安装 TDengine 后,依赖的本地函数库 libtaos.so 文件会被自动拷贝至 /usr/lib/libtaos.so,该目录包含在 Linux 自动扫描路径上,无需单独指定。
* libtaos.so (Linux)
After TDengine is installed successfully, the library `libtaos.so` will be automatically copied to the `/usr/lib/`, which is the system's default search path.
* taos.dll
在 windows 系统中安装完客户端之后,驱动包依赖的 taos.dll 文件会自动拷贝到系统默认搜索路径 C:/Windows/System32 下,同样无需要单独指定。
* taos.dll (Windows)
After TDengine client is installed, the library `taos.dll` will be automatically copied to the `C:/Windows/System32`, which is the system's default search path.
> 注意:在 windows 环境开发时需要安装 TDengine 对应的 [windows 客户端][14],Linux 服务器安装完 TDengine 之后默认已安装 client,也可以单独安装 [Linux 客户端][15] 连接远程 TDengine Server。
> Note: Please make sure that [TDengine Windows client][14] has been installed if developing on Windows. Now although TDengine client would be defaultly installed together with TDengine server, it can also be installed [alone][15].
TDengine 的 JDBC 驱动实现尽可能的与关系型数据库驱动保持一致,但时序空间数据库与关系对象型数据库服务的对象和技术特征的差异导致 taos-jdbcdriver 并未完全实现 JDBC 标准规范。在使用时需要注意以下几点:
Since TDengine is time-series database, there are still some differences compared with traditional databases in using TDengine JDBC driver:
* TDengine doesn't allow to delete/modify a single record, and thus JDBC driver also has no such method.
* No support for transaction
* No support for union between tables
* No support for nested query,`There is at most one open ResultSet for each Connection. Thus, TSDB JDBC Driver will close current ResultSet if it is not closed and a new query begins`.
* TDengine 不提供针对单条数据记录的删除和修改的操作,驱动中也没有支持相关方法。
* 由于不支持删除和修改,所以也不支持事务操作。
* 目前不支持表间的 union 操作。
* 目前不支持嵌套查询(nested query),对每个 Connection 的实例,至多只能有一个打开的 ResultSet 实例;如果在 ResultSet还没关闭的情况下执行了新的查询,TSDBJDBCDriver 则会自动关闭上一个 ResultSet。
## Version list of TAOS-JDBCDriver and required TDengine and JDK
## TAOS-JDBCDriver 版本以及支持的 TDengine 版本和 JDK 版本
| taos-jdbcdriver 版本 | TDengine 版本 | JDK 版本 |
| taos-jdbcdriver | TDengine | JDK |
| --- | --- | --- |
| 1.0.3 | 1.6.1.x 及以上 | 1.8.x |
| 1.0.2 | 1.6.1.x 及以上 | 1.8.x |
| 1.0.1 | 1.6.1.x 及以上 | 1.8.x |
| 2.0.0 | 2.0.0.x 及以上 | 1.8.x |
## TDengine DataType 和 Java DataType
TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对应类型转换如下:
| TDengine DataType | Java DataType |
| --- | --- |
| TIMESTAMP | java.sql.Timestamp |
| INT | java.lang.Integer |
| BIGINT | java.lang.Long |
| FLOAT | java.lang.Float |
| DOUBLE | java.lang.Double |
| 2.0.2 | 2.0.0.x or higher | 1.8.x |
| 1.0.3 | 1.6.1.x or higher | 1.8.x |
| 1.0.2 | 1.6.1.x or higher | 1.8.x |
| 1.0.1 | 1.6.1.x or higher | 1.8.x |
## DataType in TDengine and Java
The datatypes in TDengine include timestamp, number, string and boolean, which are converted as follows in Java:
| TDengine | Java |
| --- | --- |
| TIMESTAMP | java.sql.Timestamp |
| INT | java.lang.Integer |
| BIGINT | java.lang.Long |
| FLOAT | java.lang.Float |
| DOUBLE | java.lang.Double |
| SMALLINT, TINYINT |java.lang.Short |
| BOOL | java.lang.Boolean |
| BINARY, NCHAR | java.lang.String |
| BOOL | java.lang.Boolean |
| BINARY, NCHAR | java.lang.String |
## 如何获取 TAOS-JDBCDriver
## How to get TAOS-JDBC Driver
### maven 仓库
### maven repository
目前 taos-jdbcdriver 已经发布到 [Sonatype Repository][1] 仓库,且各大仓库都已同步。
taos-jdbcdriver has been published to [Sonatype Repository][1]:
* [sonatype][8]
* [mvnrepository][9]
* [maven.aliyun][10]
maven 项目中使用如下 pom.xml 配置即可:
Using the following pom.xml for maven projects
```xml
<dependencies>
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>2.0.0</version>
<version>2.0.2</version>
</dependency>
</dependencies>
```
### 源码编译打包
### JAR file from the source code
下载 [TDengine][3] 源码之后,进入 taos-jdbcdriver 源码目录 `src/connector/jdbc` 执行 `mvn clean package` 即可生成相应 jar 包。
After downloading the [TDengine][3] source code, execute `mvn clean package` in the directory `src/connector/jdbc` and then the corresponding jar file is generated.
## Usage
## 使用说明
### get the connection
### 获取连接
如下所示配置即可获取 TDengine Connection:
```java
Class.forName("com.taosdata.jdbc.TSDBDriver");
String jdbcUrl = "jdbc:TAOS://127.0.0.1:6030/log?user=root&password=taosdata";
Connection conn = DriverManager.getConnection(jdbcUrl);
```
> 端口 6030 为默认连接端口,JDBC URL 中的 log 为系统本身的监控数据库。
> `6030` is the default port and `log` is the default database for system monitor.
A normal JDBC URL looks as follows:
`jdbc:TAOS://{host_ip}:{port}/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]`
TDengine 的 JDBC URL 规范格式为:
`jdbc:TSDB://{host_ip}:{port}/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]`
values in `{}` are necessary while values in `[]` are optional。Each option in the above URL denotes:
其中,`{}` 中的内容必须,`[]` 中为可选。配置参数说明如下:
* user:user name for login, defaultly root。
* password:password for login,defaultly taosdata。
* charset:charset for client,defaultly system charset
* cfgdir:log directory for client, defaultly _/etc/taos/_ on Linux and _C:/TDengine/cfg_ on Windows。
* locale:language for client,defaultly system locale。
* timezone:timezone for client,defaultly system timezone。
* user:登录 TDengine 用户名,默认值 root。
* password:用户登录密码,默认值 taosdata。
* charset:客户端使用的字符集,默认值为系统字符集。
* cfgdir:客户端配置文件目录路径,Linux OS 上默认值 /etc/taos ,Windows OS 上默认值 C:/TDengine/cfg。
* locale:客户端语言环境,默认值系统当前 locale。
* timezone:客户端使用的时区,默认值为系统当前时区。
The options above can be configures (`ordered by priority`):
1. JDBC URL
以上参数可以在 3 处配置,`优先级由高到低`分别如下:
1. JDBC URL 参数
如上所述,可以在 JDBC URL 的参数中指定。
As explained above.
2. java.sql.DriverManager.getConnection(String jdbcUrl, Properties connProps)
```java
public Connection getConn() throws Exception{
......@@ -395,9 +392,9 @@ public Connection getConn() throws Exception{
}
```
3. 客户端配置文件 taos.cfg
3. Configuration file (taos.cfg)
linux 系统默认配置文件为 /var/lib/taos/taos.cfg,windows 系统默认配置文件路径为 C:\TDengine\cfg\taos.cfg。
Default configuration file is _/var/lib/taos/taos.cfg_ On Linux and _C:\TDengine\cfg\taos.cfg_ on Windows
```properties
# client default username
# defaultUser root
......@@ -411,9 +408,9 @@ public Connection getConn() throws Exception{
# system locale
# locale en_US.UTF-8
```
> 更多详细配置请参考[客户端配置][13]
> More options can refer to [client configuration][13]
### 创建数据库和表
### Create databases and tables
```java
Statement stmt = conn.createStatement();
......@@ -427,9 +424,9 @@ stmt.executeUpdate("use db");
// create table
stmt.executeUpdate("create table if not exists tb (ts timestamp, temperature int, humidity float)");
```
> 注意:如果不使用 `use db` 指定数据库,则后续对表的操作都需要增加数据库名称作为前缀,如 db.tb。
> Note: if no step like `use db`, the name of database must be added as prefix like _db.tb_ when operating on tables
### 插入数据
### Insert data
```java
// insert data
......@@ -437,10 +434,10 @@ int affectedRows = stmt.executeUpdate("insert into tb values(now, 23, 10.3) (now
System.out.println("insert " + affectedRows + " rows.");
```
> now 为系统内部函数,默认为服务器当前时间。
> `now + 1s` 代表服务器当前时间往后加 1 秒,数字后面代表时间单位:a(毫秒), s(秒), m(分), h(小时), d(天),w(周), n(月), y(年)。
> _now_ is the server time.
> _now+1s_ is 1 second later than current server time. The time unit includes: _a_(millisecond), _s_(second), _m_(minute), _h_(hour), _d_(day), _w_(week), _n_(month), _y_(year).
### 查询数据
### Query database
```java
// query data
......@@ -458,22 +455,22 @@ while(resultSet.next()){
System.out.printf("%s, %d, %s\n", ts, temperature, humidity);
}
```
> 查询和操作关系型数据库一致,使用下标获取返回字段内容时从 1 开始,建议使用字段名称获取。
> query is consistent with relational database. The subscript start with 1 when retrieving return results. It is recommended to use the column name to retrieve results.
### 关闭资源
### Close all
```java
resultSet.close();
stmt.close();
conn.close();
```
> `注意务必要将 connection 进行关闭`,否则会出现连接泄露。
## 与连接池使用
> `please make sure the connection is closed to avoid the error like connection leakage`
## Using connection pool
**HikariCP**
* 引入相应 HikariCP maven 依赖
* dependence in pom.xml
```xml
<dependency>
<groupId>com.zaxxer</groupId>
......@@ -482,7 +479,7 @@ conn.close();
</dependency>
```
* 使用示例如下
* Examples
```java
public static void main(String[] args) throws SQLException {
HikariConfig config = new HikariConfig();
......@@ -508,8 +505,69 @@ conn.close();
connection.close(); // put back to conneciton pool
}
```
> 通过 HikariDataSource.getConnection() 获取连接后,使用完成后需要调用 close() 方法,实际上它并不会关闭连接,只是放回连接池中。
> 更多 HikariCP 使用问题请查看[官方说明][5]
> The close() method will not close the connection from HikariDataSource.getConnection(). Instead, the connection is put back to the connection pool.
> More instructions can refer to [User Guide][5]
**Druid**
* dependency in pom.xml:
```xml
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.20</version>
</dependency>
```
* Examples:
```java
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.put("driverClassName","com.taosdata.jdbc.TSDBDriver");
properties.put("url","jdbc:TAOS://127.0.0.1:6030/log");
properties.put("username","root");
properties.put("password","taosdata");
properties.put("maxActive","10"); //maximum number of connection in the pool
properties.put("initialSize","3");//initial number of connection
properties.put("maxWait","10000");//maximum wait milliseconds for get connection from pool
properties.put("minIdle","3");//minimum number of connection in the pool
properties.put("timeBetweenEvictionRunsMillis","3000");// the interval milliseconds to test connection
properties.put("minEvictableIdleTimeMillis","60000");//the minimum milliseconds to keep idle
properties.put("maxEvictableIdleTimeMillis","90000");//the maximum milliseconds to keep idle
properties.put("validationQuery","describe log.dn"); //validation query
properties.put("testWhileIdle","true"); // test connection while idle
properties.put("testOnBorrow","false"); // don't need while testWhileIdle is true
properties.put("testOnReturn","false"); // don't need while testWhileIdle is true
//create druid datasource
DataSource ds = DruidDataSourceFactory.createDataSource(properties);
Connection connection = ds.getConnection(); // get connection
Statement statement = connection.createStatement(); // get statement
//query or insert
// ...
connection.close(); // put back to conneciton pool
}
```
> More instructions can refer to [User Guide][6]
**Notice**
* TDengine `v1.6.4.1` provides a function `select server_status()` to check heartbeat. It is highly recommended to use this function for `Validation Query`.
As follows,`1` will be returned if `select server_status()` is successfully executed。
```shell
taos> select server_status();
server_status()|
================
1 |
Query OK, 1 row(s) in set (0.000141s)
```
## Python Connector
......@@ -821,3 +879,18 @@ An example of using the NodeJS connector to create a table with weather data and
An example of using the NodeJS connector to achieve the same things but without all the object wrappers that wrap around the data returned to achieve higher functionality can be found [here](https://github.com/taosdata/TDengine/tree/master/tests/examples/nodejs/node-example-raw.js)
[1]: https://search.maven.org/artifact/com.taosdata.jdbc/taos-jdbcdriver
[2]: https://mvnrepository.com/artifact/com.taosdata.jdbc/taos-jdbcdriver
[3]: https://github.com/taosdata/TDengine
[4]: https://www.taosdata.com/blog/2019/12/03/jdbcdriver%e6%89%be%e4%b8%8d%e5%88%b0%e5%8a%a8%e6%80%81%e9%93%be%e6%8e%a5%e5%ba%93/
[5]: https://github.com/brettwooldridge/HikariCP
[6]: https://github.com/alibaba/druid
[7]: https://github.com/taosdata/TDengine/issues
[8]: https://search.maven.org/artifact/com.taosdata.jdbc/taos-jdbcdriver
[9]: https://mvnrepository.com/artifact/com.taosdata.jdbc/taos-jdbcdriver
[10]: https://maven.aliyun.com/mvn/search
[11]: https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC/SpringJdbcTemplate
[12]: https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC/springbootdemo
[13]: https://www.taosdata.com/cn/documentation20/administrator/#%E5%AE%A2%E6%88%B7%E7%AB%AF%E9%85%8D%E7%BD%AE
[14]: https://www.taosdata.com/cn/documentation20/connector/#Windows
[15]: https://www.taosdata.com/cn/getting-started/#%E5%BF%AB%E9%80%9F%E4%B8%8A%E6%89%8B
\ No newline at end of file
......@@ -306,7 +306,7 @@ TDengine 的 JDBC 驱动实现尽可能的与关系型数据库驱动保持一
| taos-jdbcdriver 版本 | TDengine 版本 | JDK 版本 |
| --- | --- | --- |
| 2.0.0 | 2.0.0.x 及以上 | 1.8.x |
| 2.0.2 | 2.0.0.x 及以上 | 1.8.x |
| 1.0.3 | 1.6.1.x 及以上 | 1.8.x |
| 1.0.2 | 1.6.1.x 及以上 | 1.8.x |
| 1.0.1 | 1.6.1.x 及以上 | 1.8.x |
......@@ -341,7 +341,7 @@ maven 项目中使用如下 pom.xml 配置即可:
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>2.0.1</version>
<version>2.0.2</version>
</dependency>
```
......@@ -363,7 +363,7 @@ Connection conn = DriverManager.getConnection(jdbcUrl);
> 端口 6030 为默认连接端口,JDBC URL 中的 log 为系统本身的监控数据库。
TDengine 的 JDBC URL 规范格式为:
`jdbc:TSDB://{host_ip}:{port}/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]`
`jdbc:TAOS://{host_ip}:{port}/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]`
其中,`{}` 中的内容必须,`[]` 中为可选。配置参数说明如下:
......
......@@ -19,7 +19,7 @@
#### 4. 如何让TDengine crash时生成core文件?
请看为此问题撰写的<a href='blog/2019/12/06/tdengine-crash时生成core文件的方法/'>技术博客</a>
#### 5. 遇到错误"failed to connect to server", 我怎么办?
#### 5. 遇到错误"Unable to establish connection", 我怎么办?
客户端遇到链接故障,请按照下面的步骤进行检查:
......
......@@ -10,7 +10,7 @@ Version 2.X is a complete refactoring of the previous version, and configuration
4. Enjoy the latest stable version of TDengine
5. If the data needs to be migrated or the data file is corrupted, please contact the official technical support team for assistance
#### 2. When encoutered with the error "failed to connect to server", what can I do?
#### 2. When encoutered with the error "Unable to establish connection", what can I do?
The client may encounter connection errors. Please follow the steps below for troubleshooting:
......
......@@ -1349,7 +1349,6 @@ static bool doHandleLastRemainData(SSqlObj *pSql) {
((pRes->numOfRowsGroup < pQueryInfo->limit.limit && pQueryInfo->limit.limit > 0) || (pQueryInfo->limit.limit < 0))) {
int64_t etime = (pQueryInfo->window.skey < pQueryInfo->window.ekey) ? pQueryInfo->window.ekey : pQueryInfo->window.skey;
assert(pFillInfo->numOfRows == 0);
int32_t rows = (int32_t)getFilledNumOfRes(pFillInfo, etime, pLocalReducer->resColModel->capacity);
if (rows > 0) { // do interpo
doFillResult(pSql, pLocalReducer, true);
......
......@@ -1125,7 +1125,7 @@ static int32_t handleArithmeticExpr(SSqlCmd* pCmd, int32_t clauseIndex, int32_t
int32_t tableIndex = columnList.ids[0].tableIndex;
// todo potential data overflow
char arithmeticExprStr[1024*12];
char* arithmeticExprStr = malloc(1024*1024);
char* p = arithmeticExprStr;
if (arithmeticType == NORMAL_ARITHMETIC) {
......@@ -1134,11 +1134,13 @@ static int32_t handleArithmeticExpr(SSqlCmd* pCmd, int32_t clauseIndex, int32_t
// all columns in arithmetic expression must belong to the same table
for (int32_t f = 1; f < columnList.num; ++f) {
if (columnList.ids[f].tableIndex != tableIndex) {
taosTFree(arithmeticExprStr);
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
}
}
if (arithmeticExprToString(pItem->pNode, &p) != TSDB_CODE_SUCCESS) {
taosTFree(arithmeticExprStr);
return TSDB_CODE_TSC_INVALID_SQL;
}
......@@ -1157,6 +1159,7 @@ static int32_t handleArithmeticExpr(SSqlCmd* pCmd, int32_t clauseIndex, int32_t
int32_t ret = exprTreeFromSqlExpr(pCmd, &pNode, pItem->pNode, pQueryInfo->exprList, pQueryInfo, colList);
if (ret != TSDB_CODE_SUCCESS) {
tExprTreeDestroy(&pNode, NULL);
taosTFree(arithmeticExprStr);
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
......@@ -1164,6 +1167,7 @@ static int32_t handleArithmeticExpr(SSqlCmd* pCmd, int32_t clauseIndex, int32_t
for(int32_t k = 0; k < numOfNode; ++k) {
SColIndex* pIndex = taosArrayGet(colList, k);
if (pIndex->flag == 1) {
taosTFree(arithmeticExprStr);
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
}
......@@ -1190,6 +1194,7 @@ static int32_t handleArithmeticExpr(SSqlCmd* pCmd, int32_t clauseIndex, int32_t
tExprTreeDestroy(&pNode, NULL);
} else {
if (arithmeticExprToString(pItem->pNode, &p) != TSDB_CODE_SUCCESS) {
taosTFree(arithmeticExprStr);
return TSDB_CODE_TSC_INVALID_SQL;
}
......@@ -1213,6 +1218,7 @@ static int32_t handleArithmeticExpr(SSqlCmd* pCmd, int32_t clauseIndex, int32_t
int32_t ret = exprTreeFromSqlExpr(pCmd, &pArithExprInfo->pExpr, pItem->pNode, pQueryInfo->exprList, pQueryInfo, NULL);
if (ret != TSDB_CODE_SUCCESS) {
tExprTreeDestroy(&pArithExprInfo->pExpr, NULL);
taosTFree(arithmeticExprStr);
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), "invalid expression in select clause");
}
......@@ -1220,6 +1226,7 @@ static int32_t handleArithmeticExpr(SSqlCmd* pCmd, int32_t clauseIndex, int32_t
}
}
taosTFree(arithmeticExprStr);
return TSDB_CODE_SUCCESS;
}
......@@ -1902,6 +1909,8 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
if (changeFunctionID(optr, &functionId) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_SQL;
}
tscInsertPrimaryTSSourceColumn(pQueryInfo, &index);
colIndex += 1; // the first column is ts
pExpr = tscSqlExprAppend(pQueryInfo, functionId, &index, resultType, resultSize, resultSize, false);
addExprParams(pExpr, val, TSDB_DATA_TYPE_DOUBLE, sizeof(double), 0);
......
......@@ -135,6 +135,10 @@ static void tscProcessStreamTimer(void *handle, void *tmrId) {
etime = pStream->stime + (etime - pStream->stime) / pStream->interval * pStream->interval;
}
pQueryInfo->window.ekey = etime;
if (pQueryInfo->window.skey >= pQueryInfo->window.ekey) {
tscSetRetryTimer(pStream, pSql, pStream->slidingTime);
return;
}
}
// launch stream computing in a new thread
......
......@@ -158,9 +158,9 @@ public class TSDBStatement implements Statement {
throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
} else if (resultSetPointer == TSDBConstants.JNI_NULL_POINTER) {
// no result set is retrieved
this.connecter.freeResultSet(pSql);
res = false;
}
this.connecter.freeResultSet(pSql);
return res;
}
......
......@@ -42,12 +42,14 @@ public class TestAsyncTSDBSubscribe {
long subscribId = 0;
try {
Class.forName("com.taosdata.jdbc.TSDBDriver");
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_HOST, host);
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_HOST, host);
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/" + dbName + "?user=root&password=taosdata", properties);
String rawSql = "select * from " + tName + ";";
TSDBSubscribe subscribe = ((TSDBConnection) connection).createSubscribe();
......
......@@ -242,6 +242,7 @@ void tsDataSwap(void *pLeft, void *pRight, int32_t type, int32_t size);
#define TSDB_MAX_BYTES_PER_ROW 16384
#define TSDB_MAX_TAGS_LEN 16384
#define TSDB_MAX_TAGS 128
#define TSDB_MAX_TAG_CONDITIONS 1024
#define TSDB_AUTH_LEN 16
#define TSDB_KEY_LEN 16
......
......@@ -128,6 +128,9 @@ static int32_t shellRunSingleCommand(TAOS *con, char *command) {
if (regex_match(command, "^[ \t]*(quit|q|exit)[ \t;]*$", REG_EXTENDED | REG_ICASE)) {
taos_close(con);
write_history();
#ifdef WINDOWS
exit(EXIT_SUCCESS);
#endif
return -1;
}
......@@ -368,6 +371,18 @@ static char* formatTimestamp(char* buf, int64_t val, int precision) {
tt = (time_t)(val / 1000);
}
/* comment out as it make testcases like select_with_tags.sim fail.
but in windows, this may cause the call to localtime crash if tt < 0,
need to find a better solution.
if (tt < 0) {
tt = 0;
}
*/
#ifdef WINDOWS
if (tt < 0) tt = 0;
#endif
struct tm* ptm = localtime(&tt);
size_t pos = strftime(buf, 32, "%Y-%m-%d %H:%M:%S", ptm);
......@@ -736,7 +751,7 @@ void read_history() {
FILE *f = fopen(f_history, "r");
if (f == NULL) {
fprintf(stderr, "Opening file %s\n", f_history);
fprintf(stderr, "Failed to open file %s\n", f_history);
return;
}
......@@ -761,7 +776,7 @@ void write_history() {
FILE *f = fopen(f_history, "w");
if (f == NULL) {
fprintf(stderr, "Opening file %s\n", f_history);
fprintf(stderr, "Failed to open file %s for write\n", f_history);
return;
}
......
......@@ -222,6 +222,6 @@ void *shellLoopQuery(void *arg) {
return NULL;
}
void get_history_path(char *history) { sprintf(history, "%s/%s", ".", HISTORY_FILE); }
void get_history_path(char *history) { sprintf(history, "C:/TDengine/%s", HISTORY_FILE); }
void exitShell() { exit(EXIT_SUCCESS); }
......@@ -306,7 +306,7 @@ typedef struct DemoArguments {
printf("%s%s\n", indent, "-R");
printf("%s%s%s\n", indent, indent, "rate, Out of order data's rate--if order=1 Default 10, min: 0, max: 50.");
printf("%s%s\n", indent, "-D");
printf("%s%s%s\n", indent, indent, "Delete data methods——0: don't delete, 1: delete by table, 2: delete by stable, 3: delete by database.");
printf("%s%s%s\n", indent, indent, "Delete data methods 0: don't delete, 1: delete by table, 2: delete by stable, 3: delete by database.");
}
void parse_args(int argc, char *argv[], SDemoArguments *arguments) {
......
......@@ -43,7 +43,11 @@ long interlocked_add_fetch_32(long volatile* ptr, long val) {
}
__int64 interlocked_add_fetch_64(__int64 volatile* ptr, __int64 val) {
#ifdef _WIN64
return _InterlockedExchangeAdd64(ptr, val) + val;
#else
return _InterlockedExchangeAdd(ptr, val) + val;
#endif
}
// and
......
......@@ -23,7 +23,7 @@ void taosRemoveDir(char *rootDir) {
int taosMkDir(const char *path, mode_t mode) {
uError("%s not implemented yet", __FUNCTION__);
return -1;
return 0;
}
void taosMvDir(char* destDir, char *srcDir) {
......
......@@ -21,9 +21,29 @@
#include "tulog.h"
#include "tutil.h"
unsigned char _MyBitScanForward64(unsigned long *ret, uint64_t x) {
unsigned long x0 = (unsigned long)x, top, bottom;
_BitScanForward(&top, (unsigned long)(x >> 32));
_BitScanForward(&bottom, x0);
*ret = x0 ? bottom : 32 + top;
return x != 0;
}
unsigned char _MyBitScanReverse64(unsigned long *ret, uint64_t x) {
unsigned long x1 = (unsigned long)(x >> 32), top, bottom;
_BitScanReverse(&top, x1);
_BitScanReverse(&bottom, (unsigned long)x);
*ret = x1 ? top + 32 : bottom;
return x != 0;
}
int32_t BUILDIN_CLZL(uint64_t val) {
unsigned long r = 0;
#ifdef _WIN64
_BitScanReverse64(&r, val);
#else
_MyBitScanReverse64(&r, val);
#endif
return (int)(r >> 3);
}
......@@ -35,7 +55,11 @@ int32_t BUILDIN_CLZ(uint32_t val) {
int32_t BUILDIN_CTZL(uint64_t val) {
unsigned long r = 0;
#ifdef _WIN64
_BitScanForward64(&r, val);
#else
_MyBitScanForward64(&r, val);
#endif
return (int)(r >> 3);
}
......@@ -43,4 +67,4 @@ int32_t BUILDIN_CTZ(uint32_t val) {
unsigned long r = 0;
_BitScanForward(&r, val);
return (int)(r >> 3);
}
}
\ No newline at end of file
......@@ -21,6 +21,15 @@
#include "ttimer.h"
#include "tulog.h"
#include "tutil.h"
#if (_WIN64)
#include <windows.h>
#include <iphlpapi.h>
#include <psapi.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <mswsock.h>
#pragma comment(lib, "Mswsock.lib ")
#endif
static void taosGetSystemTimezone() {
// get and set default timezone
......@@ -69,11 +78,64 @@ void taosGetSystemInfo() {
taosGetSystemLocale();
}
bool taosGetDisk() { return true; }
bool taosGetDisk() {
const double unit = 1024 * 1024 * 1024;
BOOL fResult;
unsigned _int64 i64FreeBytesToCaller;
unsigned _int64 i64TotalBytes;
unsigned _int64 i64FreeBytes;
char dir[4] = {'C', ':', '\\', '\0'};
int drive_type;
if (tscEmbedded) {
drive_type = GetDriveTypeA(dir);
if (drive_type == DRIVE_FIXED) {
fResult = GetDiskFreeSpaceExA(dir, (PULARGE_INTEGER)&i64FreeBytesToCaller, (PULARGE_INTEGER)&i64TotalBytes,
(PULARGE_INTEGER)&i64FreeBytes);
if (fResult) {
tsTotalDataDirGB = tsTotalLogDirGB = tsTotalTmpDirGB = (float)(i64TotalBytes / unit);
tsAvailDataDirGB = tsAvailLogDirGB = tsAvailTmpDirectorySpace = (float)(i64FreeBytes / unit);
}
}
}
return true;
}
bool taosReadProcIO(int64_t *readbyte, int64_t *writebyte) {
IO_COUNTERS io_counter;
if (GetProcessIoCounters(GetCurrentProcess(), &io_counter)) {
if (readbyte) *readbyte = io_counter.ReadTransferCount;
if (writebyte) *writebyte = io_counter.WriteTransferCount;
return true;
}
return false;
}
bool taosGetProcIO(float *readKB, float *writeKB) {
*readKB = 0;
*writeKB = 0;
static int64_t lastReadbyte = -1;
static int64_t lastWritebyte = -1;
int64_t curReadbyte = 0;
int64_t curWritebyte = 0;
if (!taosReadProcIO(&curReadbyte, &curWritebyte)) {
return false;
}
if (lastReadbyte == -1 || lastWritebyte == -1) {
lastReadbyte = curReadbyte;
lastWritebyte = curWritebyte;
return false;
}
*readKB = (float)((double)(curReadbyte - lastReadbyte) / 1024);
*writeKB = (float)((double)(curWritebyte - lastWritebyte) / 1024);
if (*readKB < 0) *readKB = 0;
if (*writeKB < 0) *writeKB = 0;
lastReadbyte = curReadbyte;
lastWritebyte = curWritebyte;
return true;
}
......@@ -89,12 +151,31 @@ bool taosGetCpuUsage(float *sysCpuUsage, float *procCpuUsage) {
}
bool taosGetProcMemory(float *memoryUsedMB) {
*memoryUsedMB = 0;
unsigned bytes_used = 0;
#if defined(_WIN32) && defined(_MSC_VER)
PROCESS_MEMORY_COUNTERS pmc;
HANDLE cur_proc = GetCurrentProcess();
if (GetProcessMemoryInfo(cur_proc, &pmc, sizeof(pmc))) {
bytes_used = (unsigned)(pmc.WorkingSetSize + pmc.PagefileUsage);
}
#endif
*memoryUsedMB = (float)bytes_used / 1024 / 1024;
return true;
}
bool taosGetSysMemory(float *memoryUsedMB) {
*memoryUsedMB = 0;
MEMORYSTATUSEX memsStat;
float nMemFree;
float nMemTotal;
memsStat.dwLength = sizeof(memsStat);
if (!GlobalMemoryStatusEx(&memsStat)) { return false; }
nMemFree = memsStat.ullAvailPhys / (1024.0f * 1024.0f);
nMemTotal = memsStat.ullTotalPhys / (1024.0f * 1024.0f);
*memoryUsedMB = nMemTotal - nMemFree;
return true;
}
......
......@@ -35,7 +35,7 @@
#define SQL_LENGTH 1024
#define LOG_LEN_STR 100
#define IP_LEN_STR 18
#define IP_LEN_STR TSDB_EP_LEN
#define CHECK_INTERVAL 1000
typedef enum {
......
......@@ -5547,7 +5547,7 @@ static int32_t buildAirthmeticExprFromMsg(SExprInfo *pArithExprInfo, SQueryTable
qDebug("qmsg:%p create arithmetic expr from binary string: %s", pQueryMsg, pArithExprInfo->base.arg[0].argValue.pz);
tExprNode* pExprNode = NULL;
TRY(TSDB_MAX_TAGS) {
TRY(TSDB_MAX_TAG_CONDITIONS) {
pExprNode = exprTreeFromBinary(pArithExprInfo->base.arg[0].argValue.pz, pArithExprInfo->base.arg[0].argBytes);
} CATCH( code ) {
CLEANUP_EXECUTE();
......
......@@ -137,7 +137,7 @@ void taosFillCopyInputDataFromOneFilePage(SFillInfo* pFillInfo, tFilePage* pInpu
char* s = pInput->data + pCol->col.offset * pInput->num;
memcpy(pFillInfo->pData[i], s, pInput->num * pCol->col.bytes);
if (pCol->flag == TSDB_COL_TAG) { // copy the tag value
if (pCol->flag == TSDB_COL_TAG && t < pFillInfo->numOfTags) { // copy the tag value
memcpy(pFillInfo->pTags[t++], pFillInfo->pData[i], pCol->col.bytes);
}
}
......
......@@ -128,7 +128,11 @@ int tsdbOpenFileH(STsdbRepo *pRepo) {
code = regexec(&regex2, dp->d_name, 0, NULL, 0);
if (code == 0) {
tsdbDebug("vgId:%d invalid file %s exists, remove it", REPO_ID(pRepo), dp->d_name);
remove(dp->d_name);
char *fname = malloc(strlen(tDataDir) + strlen(dp->d_name) + 2);
if (fname == NULL) goto _err;
sprintf(fname, "%s/%s", tDataDir, dp->d_name);
remove(fname);
free(fname);
} else if (code == REG_NOMATCH) {
tsdbError("vgId:%d invalid file %s exists, ignore it", REPO_ID(pRepo), dp->d_name);
continue;
......
......@@ -1115,14 +1115,6 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo*
TSKEY* tsArray = pCols->cols[0].pData;
if (ASCENDING_TRAVERSE(pQueryHandle->order)) {
TSKEY s = tsArray[cur->pos];
assert(s >= pQueryHandle->window.skey && s <= pQueryHandle->window.ekey);
} else {
TSKEY s = tsArray[cur->pos];
assert(s <= pQueryHandle->window.skey && s >= pQueryHandle->window.ekey);
}
// for search the endPos, so the order needs to reverse
int32_t order = (pQueryHandle->order == TSDB_ORDER_ASC)? TSDB_ORDER_DESC:TSDB_ORDER_ASC;
......@@ -2381,7 +2373,7 @@ int32_t tsdbQuerySTableByTagCond(TSDB_REPO_T* tsdb, uint64_t uid, TSKEY skey, co
int32_t ret = TSDB_CODE_SUCCESS;
tExprNode* expr = NULL;
TRY(TSDB_MAX_TAGS) {
TRY(TSDB_MAX_TAG_CONDITIONS) {
expr = exprTreeFromTableName(tbnameCond);
if (expr == NULL) {
expr = exprTreeFromBinary(pTagCond, len);
......@@ -2406,6 +2398,8 @@ int32_t tsdbQuerySTableByTagCond(TSDB_REPO_T* tsdb, uint64_t uid, TSKEY skey, co
} CATCH( code ) {
CLEANUP_EXECUTE();
terrno = code;
tsdbUnlockRepoMeta(tsdb); // unlock tsdb in any cases
goto _error;
// TODO: more error handling
} END_TRY
......@@ -2573,4 +2567,4 @@ static int tsdbCheckInfoCompar(const void* key1, const void* key2) {
ASSERT(false);
return 0;
}
}
\ No newline at end of file
}
char version[12] = "2.0.0.0";
char version[12] = "2.0.0.6";
char compatible_version[12] = "2.0.0.0";
char gitinfo[48] = "8df8b7d9930342dd34ba13df160a7d538fad7bc7";
char gitinfoOfInternal[48] = "bad4f040145fba581d1ab0c5dd718a5ede3e209f";
char buildinfo[64] = "Built by root at 2020-08-03 17:23";
char gitinfo[48] = "e9a20fafbe9e3b0b12cbdf55604163b4b9a41b41";
char gitinfoOfInternal[48] = "dd679db0b9edeedad68574c1e031544711a9831f";
char buildinfo[64] = "Built by at 2020-08-12 07:59";
void libtaos_2_0_0_0_Linux_x64() {};
void libtaos_2_0_0_6_Linux_x64() {};
......@@ -27,13 +27,7 @@ class TDTestCase:
ret = tdSql.query('select database()')
tdSql.checkData(0, 0, "db")
ret = tdSql.query('select server_version()')
tdSql.checkData(0, 0, "2.0.0.0")
ret = tdSql.query('select client_version()')
tdSql.checkData(0, 0, "2.0.0.0")
ret = tdSql.query('select server_status()')
tdSql.checkData(0, 0, 1)
......
###################################################################
# Copyright (c) 2016 by TAOS Technologies, Inc.
# All rights reserved.
#
# This file is proprietary and confidential to TAOS Technologies.
# No part of this file may be reproduced, stored, transmitted,
# disclosed or used in any form or by any means other than as
# expressly provided by the written permission from Jianhui Tao
#
###################################################################
# -*- coding: utf-8 -*-
import sys
from util.log import *
from util.cases import *
from util.sql import *
class TDTestCase:
def init(self, conn, logSql):
tdLog.debug("start to execute %s" % __file__)
tdSql.init(conn.cursor(), logSql)
def run(self):
tdSql.prepare()
ret = tdSql.query('select server_version()')
tdSql.checkData(0, 0, "2.0.0.6")
ret = tdSql.query('select client_version()')
tdSql.checkData(0, 0, "2.0.0.6")
def stop(self):
tdSql.close()
tdLog.success("%s successfully executed" % __file__)
tdCases.addWindows(__file__, TDTestCase())
tdCases.addLinux(__file__, TDTestCase())
......@@ -158,6 +158,7 @@ python3 ./test.py -f alter/alter_table_crash.py
# client
python3 ./test.py -f client/client.py
python3 ./test.py -f client/version.py
# Misc
python3 testCompress.py
......
......@@ -152,6 +152,7 @@ python3 ./test.py -f alter/alter_table_crash.py
# client
python3 ./test.py -f client/client.py
python3 ./test.py -f client/version.py
# Misc
python3 testCompress.py
......
......@@ -54,7 +54,7 @@ class TDTestCase:
tdSql.execute("insert into tb%d values(now + %ds, %d, %d)" % (i, j, j, j))
tdLog.info("=============== step5")
tdLog.sleep(30)
tdLog.sleep(40)
tdSql.waitedQuery("select * from st order by ts desc", 1, 120)
v = tdSql.getData(0, 3)
if v <= 51:
......
......@@ -51,3 +51,14 @@ if $data09 != NCHAR then
return -1
endi
# regression test case 1
sql select count(*) from lr_tb1 where ts>'2018-09-18 08:45:00.1' and ts<'2018-09-18 08:45:00.2'
if $row != 0 then
return -1
endi
# regression test case 2
sql select count(*) from lr_db0.lr_stb0 where ts>'2018-9-18 8:00:00' and ts<'2018-9-18 14:00:00' interval(1s) fill(NULL);
if $row != 21600 then
return -1
endi
\ No newline at end of file
......@@ -97,6 +97,8 @@ run general/parser/topbot.sim
sleep 2000
run general/parser/union.sim
sleep 2000
run general/parser/bug.sim
sleep 2000
run general/parser/sliding.sim
#sleep 2000
......
......@@ -321,6 +321,63 @@ if $data00 != $totalNum then
goto show5
endi
print ========== step6
sleep 3000
sql alter database db replica 1
$x = 0
show6:
$x = $x + 1
sleep 3000
if $x == 10 then
return -1
endi
sql show dnodes
print dnode1 freeVnodes $data2_1
print dnode4 freeVnodes $data2_4
if $data2_1 != 2 then
goto show6
endi
if $data2_4 != 2 then
goto show6
endi
sql reset query cache
sleep 1000
sql select count(*) from t10
print select count(*) from t10 $data00 expect $rowNum
if $data00 != $rowNum then
goto show5
endi
sql select count(*) from t1010
print select count(*) from t1010 $data00 expect $rowNum
if $data00 != $rowNum then
goto show5
endi
sql select count(*) from t2010
print select count(*) from t2010 $data00 expect $rowNum
if $data00 != $rowNum then
goto show5
endi
sql select count(*) from t3010
print select count(*) from t3010 $data00 expect $rowNum
if $data00 != $rowNum then
goto show5
endi
sql select count(*) from mt
print select count(*) from mt $data00 expect $rowNum
if $data00 != $totalNum then
goto show5
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
......
......@@ -69,12 +69,14 @@ if $data00 != @{slop:1.000000, intercept:1.000000}@ then
endi
print =============== step5
print select leastsquares(tbcol, 1, 1) as b from $tb interval(1d)
sql select leastsquares(tbcol, 1, 1) as b from $tb interval(1m)
print ===> $data01
if $data01 != @{slop:1.000000, intercept:1.000000}@ then
return -1
endi
print select leastsquares(tbcol, 1, 1) as b from $tb interval(1d)
sql select leastsquares(tbcol, 1, 1) as b from $tb interval(1d)
print ===> $data01
if $data01 != @{slop:1.000000, intercept:1.000000}@ then
......
......@@ -783,10 +783,23 @@ bool simExecuteNativeSqlCommand(SScript *script, char *rest, bool isSlow) {
break;
case TSDB_DATA_TYPE_TIMESTAMP:
tt = *(int64_t *)row[i] / 1000;
/* comment out as it make testcases like select_with_tags.sim fail.
but in windows, this may cause the call to localtime crash if tt < 0,
need to find a better solution.
if (tt < 0) {
tt = 0;
}
*/
#ifdef WINDOWS
if (tt < 0) tt = 0;
#endif
tp = localtime(&tt);
strftime(timeStr, 64, "%y-%m-%d %H:%M:%S", tp);
sprintf(value, "%s.%03d", timeStr,
(int)(*((int64_t *)row[i]) % 1000));
(int)(*((int64_t *)row[i]) % 1000));
break;
default:
break;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册