TDengine 目前 2.0 版服务器仅能在 Linux 系统上安装和运行,后续会支持 Windows、macOS 等系统。客户端可以在 Windows 或 Linux 上安装和运行。任何 OS 的应用也可以选择 RESTful 接口连接服务器 taosd。CPU 支持 X64/ARM64/MIPS64/Alpha64,后续会支持 ARM32、RISC-V 等 CPU 架构。用户可根据需求选择通过源码或者[安装包](https://docs.taosdata.com/get-started/package/)来安装。本快速指南仅适用于通过源码安装。
TDengine 目前可以在 Linux、 Windows 等平台上安装和运行。任何 OS 的应用也可以选择 taosAdapter 的 RESTful 接口连接服务端 taosd。CPU 支持 X64/ARM64,后续会支持 MIPS64、Alpha64、ARM32、RISC-V 等 CPU 架构。
@@ -20,7 +20,7 @@ English | [简体中文](README-CN.md) | We are hiring, check [here](https://tde
# What is TDengine?
TDengine is an open source, cloud native time-series database optimized for Internet of Things (IoT), Connected Cars, and Industrial IoT. It enables efficient, real-time data ingestion, processing, and monitoring of TB and even PB scale data per day, generated by billions of sensors and data collectors. Below are the most outstanding advantages of TDengine:
TDengine is an open source, cloud native time-series database optimized for Internet of Things (IoT), Connected Cars, and Industrial IoT. It enables efficient, real-time data ingestion, processing, and monitoring of TB and even PB scale data per day, generated by billions of sensors and data collectors. TDengine differentiates itself from other TSDBs with the following advantages.:
- High-Performance: TDengine is the only time-series database to solve the high cardinality issue to support billions of data collection points while out performing other time-series databases for data ingestion, querying and data compression.
...
...
@@ -28,7 +28,7 @@ TDengine is an open source, cloud native time-series database optimized for Inte
- Cloud Native: Through native distributed design, sharding and partitioning, separation of compute and storage, RAFT, support for kubernetes deployment and full observability, TDengine can be deployed on public, private or hybrid clouds.
- Open Source: TDengine’s core modules, including cluster feature, are all available under open source licenses. It has gathered 18.7k stars on GitHub, an active developer community, and over 137k running instances worldwide.
- Open Source: TDengine’s core modules, including cluster feature, are all available under open source licenses. It has gathered 18.8k stars on GitHub, an active developer community, and over 137k running instances worldwide.
- Ease of Use: For administrators, TDengine significantly reduces the effort to deploy and maintain. For developers, it provides a simple interface, simplified solution and seamless integrations for third party tools. For data users, it gives easy data access.
...
...
@@ -52,20 +52,6 @@ To build TDengine, use [CMake](https://cmake.org/) 3.0.2 or higher versions in t
To compile and package the JDBC driver source code, you should have a Java jdk-8 or higher and Apache Maven 2.7 or higher installed.
To install openjdk-8:
```bash
sudo apt-get install-y openjdk-8-jdk
```
To install Apache Maven:
```bash
sudo apt-get install-y maven
```
#### Install build dependencies for taosTools
We provide a few useful tools such as taosBenchmark (was named taosdemo) and taosdump. They were part of TDengine. From TDengine 2.4.0.0, taosBenchmark and taosdump were not released together with TDengine.
Note: Since snappy lacks pkg-config support (refer to [link](https://github.com/google/snappy/pull/86)), it lead a cmake prompt libsnappy not found. But snappy will works well.
Note: Since snappy lacks pkg-config support (refer to [link](https://github.com/google/snappy/pull/86)), it leads a cmake prompt libsnappy not found. But snappy will works well.
### Setup golang environment
TDengine includes few components developed by Go language. Please refer to golang.org official documentation for golang environment setup.
TDengine includes a few components developed by Go language. Please refer to golang.org official documentation for golang environment setup.
Please use version 1.14+. For the user in China, we recommend using a proxy to accelerate package downloading.
...
...
@@ -139,7 +101,7 @@ go env -w GOPROXY=https://goproxy.cn,direct
### Setup rust environment
TDengine includees few compoments developed by Rust language. Please refer to rust-lang.org official documentation for rust environment setup.
TDengine includees a few compoments developed by Rust language. Please refer to rust-lang.org official documentation for rust environment setup.
## Get the source codes
...
...
@@ -304,24 +266,6 @@ After building successfully, TDengine can be installed by:
sudo make install
```
To start the service after installation, config `.plist` file first, in a terminal, use:
If you don't want to run TDengine as a service, you can run it in current shell. For example, to quickly start a TDengine server after building, run the command below in terminal: (We take Linux as an example, command on Windows will be `taosd.exe`)
...
...
@@ -371,15 +315,6 @@ TDengine provides abundant developing tools for users to develop on TDengine. Fo
@@ -10,16 +10,14 @@ import TabItem from '@theme/TabItem';
import Preparation from "./_preparation.mdx"
import RustInsert from "../../07-develop/03-insert-data/_rust_sql.mdx"
import RustInfluxLine from "../../07-develop/03-insert-data/_rust_line.mdx"
import RustOpenTSDBTelnet from "../../07-develop/03-insert-data/_rust_opts_telnet.mdx"
import RustOpenTSDBJson from "../../07-develop/03-insert-data/_rust_opts_json.mdx"
import RustBind from "../../07-develop/03-insert-data/_rust_stmt.mdx"
import RustQuery from "../../07-develop/04-query-data/_rust.mdx"
`libtaos` is the official Rust language connector for TDengine. Rust developers can develop applications to access the TDengine instance data.
[`taos`][taos] is the official Rust language connector for TDengine. Rust developers can develop applications to access the TDengine instance data.
`libtaos` provides two ways to establish connections. One is the **Native Connection**, which connects to TDengine instances via the TDengine client driver (taosc). The other is **REST connection**, which connects to TDengine instances via taosAdapter's REST interface.
Rust connector provides two ways to establish connections. One is the **Native Connection**, which connects to TDengine instances via the TDengine client driver (taosc). The other is **Websocket connection**, which connects to TDengine instances via taosAdapter service.
The source code for `libtaos` is hosted on [GitHub](https://github.com/taosdata/libtaos-rs).
The source code is hosted on [taosdata/taos-connector-rust](https://github.com/taosdata/taos-connector-rust).
## Supported platforms
...
...
@@ -30,241 +28,333 @@ REST connections are supported on all platforms that can run Rust.
Please refer to [version support list](/reference/connector#version-support).
The Rust Connector is still under rapid development and is not guaranteed to be backward compatible before 1.0. We recommend using TDengine version 2.4 or higher to avoid known issues.
The Rust Connector is still under rapid development and is not guaranteed to be backward compatible before 1.0. We recommend using TDengine version 3.0 or higher to avoid known issues.
## Installation
### Pre-installation
* Install the Rust development toolchain
* If using the native connection, please install the TDengine client driver. Please refer to [install client driver](/reference/connector#install-client-driver)
### Adding libtaos dependencies
### Add dependencies
Add the [libtaos][libtaos] dependency to the [Rust](https://rust-lang.org) project as follows, depending on the connection method selected.
Add the dependency to the [Rust](https://rust-lang.org) project as follows, depending on the connection method selected.
Add [libtaos][libtaos] to the `Cargo.toml` file and enable the `rest` feature.
Add [taos] to the `Cargo.toml` file.
```toml
[dependencies]
# use rest feature
libtaos = { version = "*", features = ["rest"]}
taos = { version = "*", default-features = false, features = ["native"] }
```
</TabItem>
</Tabs>
<TabItem value="rest" label="Websocket only">
### Using connection pools
Please enable the `r2d2` feature in `Cargo.toml`.
Add [taos] to the `Cargo.toml` file and enable the `ws` feature.
```toml
[dependencies]
# with taosc
libtaos = { version = "*", features = ["r2d2"] }
# or rest
libtaos = { version = "*", features = ["rest", "r2d2"] }
taos = { version = "*", default-features = false, features = ["ws"] }
```
</TabItem>
</Tabs>
## Create a connection
The [TaosCfgBuilder] provides the user with an API in the form of a constructor for the subsequent creation of connections or use of connection pools.
In rust connector, we use a DSN connection string as a connection builder. For example,
```rust
let cfg: TaosCfg = TaosCfgBuilder::default()
.ip("127.0.0.1")
.user("root")
.pass("taosdata")
.db("log") // do not set if not require a default database.
.port(6030u16)
.build()
.expect("TaosCfg builder error");
}
let builder = TaosBuilder::from_dsn("taos://")?;
```
You can now use this object to create the connection.
You can now use connection client to create the connection.
```rust
let conn = cfg.connect()? ;
let conn = builder.build()?;
```
The connection object can create more than one.
```rust
let conn = cfg.connect()? ;
let conn2 = cfg.connect()? ;
let conn1 = builder.build()?;
let conn2 = builder.build()?;
```
DSN is short for **D**ata **S**ource **N**ame string - [a data structure used to describe a connection to a data source](https://en.wikipedia.org/wiki/Data_source_name).
- **Driver**: the main entrypoint to a processer. **Required**. In Rust connector, the supported driver names are listed here:
- **taos**: the legacy TDengine connection data source.
- **tmq**: subscription data source from TDengine.
- **http/ws**: use websocket protocol via `ws://` scheme.
- **https/wss**: use websocket protocol via `wss://` scheme.
- **Protocol**: the additional information appended to driver, which can be be used to support different kind of data sources. By default, leave it empty for native driver(only under feature "native"), and `ws/wss` for websocket driver (only under feature "ws"). **Optional**.
- **Username**: as its definition, is the username to the connection. **Optional**.
- **Password**: the password of the username. **Optional**.
- **Host**: address host to the datasource. **Optional**.
- **Port**: address port to the datasource. **Optional**.
- **Database**: database name or collection name in the datasource. **Optional**.
- **Params**: a key-value map for any other informations to the datasource. **Optional**.
Here is a simple DSN connection string example:
```text
taos+ws://localhost:6041/test
```
which means connect `localhost` with port `6041` via `ws` protocol, and make `test` as the default database.
So that you can use DSN to specify connection protocol at runtime:
```rust
let pool = r2d2::Pool::builder()
.max_size(10000) // max connections
.build(cfg)? ;
use taos::*; // use it like a `prelude` mod, we need some traits at next.
// ...
// Use pool to get connection
let conn = pool.get()? ;
// use native protocol.
let builder = TaosBuilder::from_dsn("taos://localhost:6030")?;
let conn1 = builder.build();
// use websocket protocol.
let conn2 = TaosBuilder::from_dsn("taos+ws://localhost:6041")?;
```
After that, you can perform the following operations on the database.
After connected, you can perform the following operations on the database.
```rust
async fn demo() -> Result<(), Error> {
// get connection ...
// create database
conn.exec("create database if not exists demo").await?
// change database context
conn.exec("use demo").await?
// create table
conn.exec("create table if not exists tb1 (ts timestamp, v int)").await?
// insert
conn.exec("insert into tb1 values(now, 1)").await?
| [bailongma-rs] | Using TDengine as the Prometheus remote storage API adapter for the storage backend, using the r2d2 connection pool |
<RustQuery />|
## API Reference
### Connection constructor API
The [Builder Pattern](https://doc.rust-lang.org/1.0.0/style/ownership/builders.html) constructor pattern is Rust's solution for handling complex data types or optional configuration types. The [libtaos] implementation uses the connection constructor [TaosCfgBuilder] as the entry point for the TDengine Rust connector. The [TaosCfgBuilder] provides optional configuration of servers, ports, databases, usernames, passwords, etc.
Using the `default()` method, you can construct a [TaosCfg] with default parameters for subsequent connections to the database or establishing connection pools.
### Connector builder
```rust
let cfg = TaosCfgBuilder::default().build()? ;
```
Using the constructor pattern, the user can set on-demand.
Use DSN to directly construct a TaosBuilder object.
```rust
let cfg = TaosCfgBuilder::default()
.ip("127.0.0.1")
.user("root")
.pass("taosdata")
.db("log")
.port(6030u16)
.build()? ;
let builder = TaosBuilder::from_dsn("")? ;
```
Create TDengine connection using [TaosCfg] object.
Use `builder` to create many connections:
```rust
let conn: Taos = cfg.connect();
let conn: Taos = cfg.build();
```
### Connection pooling
### Connection pool
In complex applications, we recommend enabling connection pools. Connection pool for [libtaos] is implemented using [r2d2].
In complex applications, we recommend enabling connection pools. Connection pool for [taos] is implemented using [r2d2] by enabling "r2d2" feature.
As follows, a connection pool with default parameters can be generated.
Basically, a connection pool with default parameters can be generated as:
```rust
let pool = r2d2::Pool::new(cfg)? ;
let pool = TaosBuilder::from_dsn(dsn)?.pool()?;
```
You can set the same connection pool parameters using the connection pool's constructor.
You can set the connection pool parameters using the `PoolBuilder`.
```rust
use std::time::Duration;
let pool = r2d2::Pool::builder()
.max_size(5000) // max connections
.max_lifetime(Some(Duration::from_minutes(100))) // lifetime of each connection
.min_idle(Some(1000)) // minimal idle connections
.connection_timeout(Duration::from_minutes(2))
.build(cfg);
let dsn = "taos://localhost:6030";
let opts = PoolBuilder::new()
.max_size(5000) // max connections
.max_lifetime(Some(Duration::from_secs(60 * 60))) // lifetime of each connection
.min_idle(Some(1000)) // minimal idle connections
.connection_timeout(Duration::from_secs(2));
let pool = TaosBuilder::from_dsn(dsn)?.with_pool_builder(opts)?;
```
In the application code, use `pool.get()?` to get a connection object [Taos].
In the application code, use `pool.get()?` to get a connection object [Taos].
```rust
let taos = pool.get()? ;
```
The [Taos] structure is the connection manager in [libtaos] and provides two main APIs.
### Connection methods
1. `exec`: Execute some non-query SQL statements, such as `CREATE`, `ALTER`, `INSERT`, etc.
The [Taos] connection struct provides several APIs for convenient use.
1. `exec`: Execute some non-query SQL statements, such as `CREATE`, `ALTER`, `INSERT` etc. and return affected rows (only meaningful to `INSERT`).
```rust
let affected_rows = taos.exec("INSERT INTO tb1 VALUES(now, NULL)").await?;
```
2. `exec_many`: You can execute many SQL statements in order with `exec_many` method.
```rust
taos.exec().await?
taos.exec_many([
"CREATE DATABASE test",
"USE test",
"CREATE TABLE `tb1` (`ts` TIMESTAMP, `val` INT)",
]).await?;
```
2. `query`: Execute the query statement and return the [TaosQueryData] object.
3. `query`: Execute the query statement and return the [ResultSet] object.
```rust
let q = taos.query("select * from log.logs").await?
let mut q = taos.query("select * from log.logs").await?
```
The [TaosQueryData] object stores the query result data and basic information about the returned columns (column name, type, length).
The [ResultSet] object stores the query result data and basic information about the returned columns (column name, type, length).
Or use it with [serde](https://serde.rs) deserialization.
```rust
#[derive(Debug, Deserialize)]
struct Record {
// deserialize timestamp to chrono::DateTime<Local>
ts: DateTime<Local>,
// float to f32
current: Option<f32>,
// int to i32
voltage: Option<i32>,
phase: Option<f32>,
groupid: i32,
// binary/varchar to String
location: String,
}
let records: Vec<Record> = taos
.query("select * from `meters`")
.await?
.deserialize()
.try_collect()
.await?;
```
Note that Rust asynchronous functions and an asynchronous runtime are required.
...
...
@@ -275,110 +365,152 @@ Note that Rust asynchronous functions and an asynchronous runtime are required.
- `.create_database(database: &str)`: Executes the `CREATE DATABASE` statement.
- `.use_database(database: &str)`: Executes the `USE` statement.
In addition, this structure is also the entry point for [Parameter Binding](#Parameter Binding Interface) and [Line Protocol Interface](#Line Protocol Interface). Please refer to the specific API descriptions for usage.
### Bind Interface
### Bind API
Similar to the C interface, Rust provides the bind interface's wrapping. First, create a bind object [Stmt] for a SQL command from the [Taos] object.
Similar to the C interface, Rust provides the bind interface's wrapping. First, create a bind object [Stmt] for a SQL command with the [Taos] object.
```rust
let mut stmt: Stmt = taos.stmt("insert into ? values(? ,?)") ? ;
let mut stmt = Stmt::init(&taos).await?;
stmt.prepare("INSERT INTO ? USING meters TAGS(?, ?) VALUES(?, ?, ?, ?)")?;
```
The bind object provides a set of interfaces for implementing parameter binding.
let rows = stmt.bind(¶ms)?.add_batch()?.execute()?;
```
##### `.execute()`
#### `.execute()`
Execute SQL.[Stmt] objects can be reused, re-binded, and executed after execution.
Execute to insert all bind records. [Stmt] objects can be reused, re-bind, and executed after execution. Remember to call `add_batch` before `execute`.
```rust
stmt.execute()? ;
stmt.add_batch()?.execute()?;
// next bind cycle.
// stmt.set_tbname()? ;
//stmt.bind()? ;
//stmt.execute()? ;
//stmt.add_batch().execute()? ;
```
### Line protocol interface
A runnable example for bind can be found [here](https://github.com/taosdata/taos-connector-rust/blob/main/examples/bind.rs).
The line protocol interface supports multiple modes and different precision and requires the introduction of constants in the schemaless module to set.
### Subscription API
Users can subscribe a [TOPIC](../../../taos-sql/tmq/) with TMQ(the TDengine Message Queue) API.
Start from a TMQ builder:
```rust
use libtaos::*;
use libtaos::schemaless::*;
let tmq = TmqBuilder::from_dsn("taos://localhost:6030/?group.id=test")?;
In TMQ DSN, you must choose to subscribe with a group id. Also, there's several options could be set:
- `group.id`: **Required**, a group id is any visible string you set.
- `client.id`: a optional client description string.
- `auto.offset.reset`: choose to subscribe from *earliest* or *latest*, default is *none* which means 'earliest'.
- `enable.auto.commit`: automatically commit with specified time interval. By default - in the recommended way _ you must use `commit` to ensure that you've consumed the messages correctly, otherwise, consumers will received repeated messages when re-subscribe.
- `auto.commit.interval.ms`: the auto commit interval in milliseconds.
Check the whole subscription example at [GitHub](https://github.com/taosdata/taos-connector-rust/blob/main/examples/subscribe.rs).
Please move to the Rust documentation hosting page for other related structure API usage instructions: <https://docs.rs/libtaos>.
Please move to the Rust documentation hosting page for other related structure API usage instructions: <https://docs.rs/taos>.
In IoT applications, data is collected for many purposes such as intelligent control, business analysis, device monitoring and so on. Due to changes in business or functional requirements or changes in device hardware, the application logic and even the data collected may change. To provide the flexibility needed in such cases and in a rapidly changing IoT landscape, TDengine starting from version 2.2.0.0, provides a series of interfaces for the schemaless writing method. These interfaces eliminate the need to create super tables and subtables in advance by automatically creating the storage structure corresponding to the data as the data is written to the interface. When necessary, schemaless writing will automatically add the required columns to ensure that the data written by the user is stored correctly.
In IoT applications, data is collected for many purposes such as intelligent control, business analysis, device monitoring and so on. Due to changes in business or functional requirements or changes in device hardware, the application logic and even the data collected may change. To provide the flexibility needed in such cases and in a rapidly changing IoT landscape, TDengine provides a series of interfaces for the schemaless writing method. These interfaces eliminate the need to create super tables and subtables in advance by automatically creating the storage structure corresponding to the data as the data is written to the interface. When necessary, schemaless writing will automatically add the required columns to ensure that the data written by the user is stored correctly.
The schemaless writing method creates super tables and their corresponding subtables. These are completely indistinguishable from the super tables and subtables created directly via SQL. You can write data directly to them via SQL statements. Note that the names of tables created by schemaless writing are based on fixed mapping rules for tag values, so they are not explicitly ideographic and they lack readability.
...
...
@@ -39,10 +39,10 @@ In the schemaless writing data line protocol, each data item in the field_set ne
-`t`, `T`, `true`, `True`, `TRUE`, `f`, `F`, `false`, and `False` will be handled directly as BOOL types.
...
...
@@ -72,11 +72,11 @@ If the subtable obtained by the parse line protocol does not exist, Schemaless c
4. If the specified tag or regular column in the data row does not exist, the corresponding tag or regular column is added to the super table (only incremental).
5. If there are some tag columns or regular columns in the super table that are not specified to take values in a data row, then the values of these columns are set to NULL.
6. For BINARY or NCHAR columns, if the length of the value provided in a data row exceeds the column type limit, the maximum length of characters allowed to be stored in the column is automatically increased (only incremented and not decremented) to ensure complete preservation of the data.
7.If the specified data subtable already exists, and the specified tag column takes a value different from the saved value this time, the value in the latest data row overwrites the old tag column take value.
8.Errors encountered throughout the processing will interrupt the writing process and return an error code.
7.Errors encountered throughout the processing will interrupt the writing process and return an error code.
8.In order to improve the efficiency of writing, it is assumed by default that the order of the fields in the same Super is the same (the first data contains all fields, and the following data is in this order). If the order is different, the parameter smlDataFormat needs to be configured to be false. Otherwise, the data is written in the same order, and the data in the library will be abnormal.
:::tip
All processing logic of schemaless will still follow TDengine's underlying restrictions on data structures, such as the total length of each row of data cannot exceed 48k bytes. See [TAOS SQL Boundary Limits](/taos-sql/limit) for specific constraints in this area.
All processing logic of schemaless will still follow TDengine's underlying restrictions on data structures, such as the total length of each row of data cannot exceed 16k bytes. See [TAOS SQL Boundary Limits](/taos-sql/limit) for specific constraints in this area.
taos.exec("CREATE STABLE meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (location BINARY(64), groupId INT)").await?;
letmutstmt=taos.stmt("INSERT INTO ? USING meters TAGS(?, ?) VALUES(?, ?, ?, ?)")?;
taos.exec("CREATE STABLE IF NOT EXISTS meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (location BINARY(64), groupId INT)").await?;
letmutstmt=Stmt::init(&taos)?;
stmt.prepare("INSERT INTO ? USING meters TAGS(?, ?) VALUES(?, ?, ?, ?)")?;
tdSql.execute('insert into ntb values(now,1,1.55,100.555555,today())("2020-1-1 00:00:00",10,11.11,99.999999,now())(today(),3,3.333,333.333333,now())')
tdSql.execute('insert into stb_1 values(now,1,1.55,100.555555,today())("2020-1-1 00:00:00",10,11.11,99.999999,now())(today(),3,3.333,333.333333,now())')
tdSql.query("select to_iso8601(ts) from ntb")
tdSql.execute('create table if not exists db.ntb(ts timestamp, c1 int, c2 float,c3 double,c4 timestamp)')
tdSql.execute('create table if not exists db.stb(ts timestamp, c1 int, c2 float,c3 double,c4 timestamp) tags(t0 int)')
tdSql.execute('create table if not exists db.stb_1 using db.stb tags(100)')
tdSql.execute('insert into db.ntb values(now,1,1.55,100.555555,today())("2020-1-1 00:00:00",10,11.11,99.999999,now())(today(),3,3.333,333.333333,now())')
tdSql.execute('insert into db.stb_1 values(now,1,1.55,100.555555,today())("2020-1-1 00:00:00",10,11.11,99.999999,now())(today(),3,3.333,333.333333,now())')
tdSql.query("select to_iso8601(ts) from db.ntb")
tdSql.checkRows(3)
tdSql.query("select c1 from ntb where ts = to_iso8601(1577808000000)")
tdSql.query("select c1 from db.ntb where ts = to_iso8601(1577808000000)")
tdSql.checkRows(1)
tdSql.checkData(0,0,10)
tdSql.query("select * from ntb where ts = to_iso8601(1577808000000)")
tdSql.query("select * from db.ntb where ts = to_iso8601(1577808000000)")
tdSql.checkRows(1)
tdSql.query("select to_iso8601(ts) from ntb where ts=today()")
tdSql.query("select to_iso8601(ts) from db.ntb where ts=today()")
tdSql.checkRows(1)
foriinrange(0,3):
tdSql.query("select to_iso8601(1) from ntb")
tdSql.query("select to_iso8601(1) from db.ntb")
tdSql.checkData(i,0,"1970-01-01T08:00:01+0800")
tdSql.checkRows(3)
tdSql.query("select to_iso8601(ts) from ntb")
tdSql.checkRows(3)
tdSql.query("select to_iso8601(ts) from db.ntb")
tdSql.query("select to_iso8601(today()) from ntb")
tdSql.checkRows(3)
tdSql.query("select to_iso8601(now()) from ntb")
tdSql.query("select to_iso8601(today()) from db.ntb")
tdSql.checkRows(3)
tdSql.error("select to_iso8601(timezone()) from ntb")
tdSql.error("select to_iso8601('abc') from ntb")
tdSql.query("select to_iso8601(now()) from db.ntb")
tdSql.checkRows(3)
tdSql.error("select to_iso8601(timezone()) from db.ntb")
tdSql.error("select to_iso8601('abc') from db.ntb")
foriin['+','-','*','/']:
tdSql.query(f"select to_iso8601(today()) {i}null from ntb")
tdSql.checkRows(3)
tdSql.checkData(0,0,None)
tdSql.query(f"select to_iso8601(today()) {i}null from db.ntb")
tdSql.checkRows(3)
tdSql.checkData(0,0,None)
tdSql.query("select to_iso8601(9223372036854775807) from ntb")
tdSql.query("select to_iso8601(9223372036854775807) from db.ntb")
tdSql.checkRows(3)
# bug TD-15207
# tdSql.query("select to_iso8601(10000000000) from ntb")
...
...
@@ -102,27 +90,22 @@ class TDTestCase:
# tdSql.checkData(0,0,None)
err_param=[1.5,'a','c2']
foriinerr_param:
tdSql.error(f"select to_iso8601({i}) from ntb")
tdSql.error(f"select to_iso8601({i}) from db.ntb")
tdSql.query("select to_iso8601(now) from stb")
tdSql.query("select to_iso8601(now) from db.stb")
tdSql.checkRows(3)
tdSql.query("select to_iso8601(now()) from stb")
tdSql.query("select to_iso8601(now()) from db.stb")
tdSql.checkRows(3)
tdSql.query("select to_iso8601(1) from stb")
tdSql.query("select to_iso8601(1) from db.stb")
foriinrange(0,3):
tdSql.checkData(i,0,"1970-01-01T08:00:01+0800")
tdSql.checkRows(3)
tdSql.query("select to_iso8601(ts) from stb")
tdSql.query("select to_iso8601(ts) from db.stb")
tdSql.checkRows(3)
tdSql.query("select to_iso8601(ts)+1 from stb")
tdSql.query("select to_iso8601(ts)+1 from db.stb")
tdSql.checkRows(3)
tdSql.query("select to_iso8601(ts)+'a' from stb ")
tdSql.query("select to_iso8601(ts)+'a' from db.stb ")
tdSql.checkRows(3)
foriin['+','-','*','/']:
tdSql.query(f"select to_iso8601(today()) {i}null from stb")
tdSql.checkRows(3)
tdSql.checkData(0,0,None)
tdSql.query(f"select to_iso8601(today()) {i}null from db.stb")