diff --git a/.github/workflows/pre-commit-format.yml b/.github/workflows/pre-commit-format.yml new file mode 100644 index 0000000..786a5e5 --- /dev/null +++ b/.github/workflows/pre-commit-format.yml @@ -0,0 +1,48 @@ +name: Formatting + +on: + workflow_dispatch: + pull_request: + branches: + - '**' + merge_group: + branches: [ main ] + schedule: + - cron: "0 0 * * *" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + formatting-checks: + runs-on: ubuntu-20.04 + + steps: + - uses: actions/checkout@v4 + + - name: Setup dotnet + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '9.0.x' + + - name: Setup Python environment (for pre-commit) + uses: actions/setup-python@v5 + with: + python-version: '3.10' + + - name: Clean dotnet temporary folder + run: | + sudo rm -rf /tmp/.dotnet + + - name: Install pre-commit and dependencies + run: | + pip install pre-commit + pre-commit install-hooks + + - name: Run pre-commit checks + env: + TMPDIR: ${{ runner.temp }} + DOTNET_CLI_HOME: ${{ runner.temp }} + run: | + pre-commit run --all-files diff --git a/.licenserc.yaml b/.licenserc.yaml index afe9c0c..4bda2c2 100644 --- a/.licenserc.yaml +++ b/.licenserc.yaml @@ -32,5 +32,6 @@ header: - 'Apache.IoTDB.sln' - '.gitignore' - '.dockerignore' + - '.pre-commit-config.yaml' comment: on-failure diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..630051f --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,33 @@ + + +repos: + - repo: local + hooks: + - id: dotnet-format + name: dotnet format + entry: dotnet format --include + language: system + pass_filenames: true + files: '\.(cs|vb|fs|sln|csproj|fsproj)$' + + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-added-large-files + - id: check-yaml + - id: check-json + - id: check-xml + + - repo: https://github.com/codespell-project/codespell + rev: v2.2.6 + hooks: + - id: codespell + args: ["--ignore-words-list=fo,teh,ba"] + +exclude: | + (?x)^( + src/Apache\.IoTDB/Rpc/| + .*\.md$ + ) diff --git a/Apache-IoTDB-Client-CSharp-UserCase/Program.cs b/Apache-IoTDB-Client-CSharp-UserCase/Program.cs index 345e9a7..281104d 100644 --- a/Apache-IoTDB-Client-CSharp-UserCase/Program.cs +++ b/Apache-IoTDB-Client-CSharp-UserCase/Program.cs @@ -118,4 +118,3 @@ static async Task Main(string[] args) } } - diff --git a/Apache.IoTDB.sln b/Apache.IoTDB.sln index 7ddbed2..b6b5aaf 100644 --- a/Apache.IoTDB.sln +++ b/Apache.IoTDB.sln @@ -26,8 +26,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{DEAC57D3-4 docs\time_profile_zh.pdf = docs\time_profile_zh.pdf EndProjectSection EndProject -Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{4D457769-80CB-401F-9155-C3125C04FACD}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Apache.IoTDB.Data", "src\Apache.IoTDB.Data\Apache.IoTDB.Data.csproj", "{4308656F-D174-49A6-ACE4-15894B017D55}" EndProject Global diff --git a/docker-compose-2c2d.yml b/docker-compose-2c2d.yml index 318e8e8..4772779 100644 --- a/docker-compose-2c2d.yml +++ b/docker-compose-2c2d.yml @@ -130,4 +130,4 @@ services: dockerfile: samples/Apache.IoTDB.Samples/Dockerfile command: ["--multi", "localhost:6667", "localhost:6668"] # command: ["sleep", "infinity"] - network_mode: host \ No newline at end of file + network_mode: host diff --git a/docker-compose.yml b/docker-compose.yml index 3fa34a0..2c379f9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,7 +15,7 @@ services: networks: iotdb-network: ipv4_address: 172.18.0.2 - + iotdb: image: apache/iotdb:2.0.1-beta-datanode restart: always @@ -38,7 +38,7 @@ services: - dn_rpc_address=iotdb - dn_internal_address=iotdb - dn_seed_config_node=iotdb-confignode-1:22277 - + iotdb-confignode-1: image: apache/iotdb:2.0.1-beta-confignode restart: always @@ -58,6 +58,6 @@ services: - cn_seed_config_node=iotdb-confignode-1:22277 -networks: +networks: iotdb-network: external: true diff --git a/launchSettings.json b/launchSettings.json index cd5bd5a..6f2540e 100644 --- a/launchSettings.json +++ b/launchSettings.json @@ -11,4 +11,4 @@ } } } -} \ No newline at end of file +} diff --git a/samples/Apache.IoTDB.Samples/Dockerfile b/samples/Apache.IoTDB.Samples/Dockerfile index 26ee0a9..52b2dcf 100644 --- a/samples/Apache.IoTDB.Samples/Dockerfile +++ b/samples/Apache.IoTDB.Samples/Dockerfile @@ -36,4 +36,4 @@ RUN dotnet publish "Apache.IoTDB.Samples.csproj" -c Release -o /app/publish FROM base AS final WORKDIR /app COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "Apache.IoTDB.Samples.dll"] \ No newline at end of file +ENTRYPOINT ["dotnet", "Apache.IoTDB.Samples.dll"] diff --git a/samples/Apache.IoTDB.Samples/Program.cs b/samples/Apache.IoTDB.Samples/Program.cs index bc557bb..b825063 100644 --- a/samples/Apache.IoTDB.Samples/Program.cs +++ b/samples/Apache.IoTDB.Samples/Program.cs @@ -35,48 +35,48 @@ public static async Task Main(string[] args) () => "localhost", description: "Use single endpoint (e.g. --single localhost)"); - var multiOption = new Option>( - "--multi", - description: "Use multiple endpoints (e.g. --multi localhost:6667 localhost:6668)") - { - AllowMultipleArgumentsPerToken = true - }; + var multiOption = new Option>( + "--multi", + description: "Use multiple endpoints (e.g. --multi localhost:6667 localhost:6668)") + { + AllowMultipleArgumentsPerToken = true + }; - var rootCommand = new RootCommand + var rootCommand = new RootCommand { singleOption, multiOption }; - rootCommand.SetHandler(async (string single, List multi) => - { - var utilsTest = new UtilsTest(); - utilsTest.TestParseEndPoint(); + rootCommand.SetHandler(async (string single, List multi) => + { + var utilsTest = new UtilsTest(); + utilsTest.TestParseEndPoint(); - SessionPoolTest sessionPoolTest; + SessionPoolTest sessionPoolTest; - if (!string.IsNullOrEmpty(single) && (multi == null || multi.Count == 0)) - { - sessionPoolTest = new SessionPoolTest(single); - } - else if (multi != null && multi.Count != 0) - { - sessionPoolTest = new SessionPoolTest(multi); - } - else - { - Console.WriteLine("Please specify either --single or --multi endpoints."); - return; - } + if (!string.IsNullOrEmpty(single) && (multi == null || multi.Count == 0)) + { + sessionPoolTest = new SessionPoolTest(single); + } + else if (multi != null && multi.Count != 0) + { + sessionPoolTest = new SessionPoolTest(multi); + } + else + { + Console.WriteLine("Please specify either --single or --multi endpoints."); + return; + } - await sessionPoolTest.Test(); + await sessionPoolTest.Test(); - var tableSessionPoolTest = new TableSessionPoolTest(sessionPoolTest); - await tableSessionPoolTest.Test(); + var tableSessionPoolTest = new TableSessionPoolTest(sessionPoolTest); + await tableSessionPoolTest.Test(); - }, singleOption, multiOption); + }, singleOption, multiOption); - await rootCommand.InvokeAsync(args); + await rootCommand.InvokeAsync(args); } public static void OpenDebugMode(this SessionPool session) diff --git a/samples/Apache.IoTDB.Samples/Properties/launchSettings.json b/samples/Apache.IoTDB.Samples/Properties/launchSettings.json index 8511cd9..8097449 100644 --- a/samples/Apache.IoTDB.Samples/Properties/launchSettings.json +++ b/samples/Apache.IoTDB.Samples/Properties/launchSettings.json @@ -7,4 +7,4 @@ "commandName": "Docker" } } -} \ No newline at end of file +} diff --git a/samples/Apache.IoTDB.Samples/SessionPoolTest.AlignedRecord.cs b/samples/Apache.IoTDB.Samples/SessionPoolTest.AlignedRecord.cs index e43ef35..cb4d8f6 100644 --- a/samples/Apache.IoTDB.Samples/SessionPoolTest.AlignedRecord.cs +++ b/samples/Apache.IoTDB.Samples/SessionPoolTest.AlignedRecord.cs @@ -496,4 +496,4 @@ public async Task TestInsertAlignedStringRecordsOfOneDevice() Console.WriteLine("TestInsertAlignedStringRecordsOfOneDevice Passed!"); } } -} \ No newline at end of file +} diff --git a/samples/Apache.IoTDB.Samples/SessionPoolTest.AlignedTablet.cs b/samples/Apache.IoTDB.Samples/SessionPoolTest.AlignedTablet.cs index 1b63271..77050ad 100644 --- a/samples/Apache.IoTDB.Samples/SessionPoolTest.AlignedTablet.cs +++ b/samples/Apache.IoTDB.Samples/SessionPoolTest.AlignedTablet.cs @@ -192,4 +192,4 @@ public async Task TestInsertAlignedTablets() Console.WriteLine("TestInsertAlignedTablets Passed!"); } } -} \ No newline at end of file +} diff --git a/samples/Apache.IoTDB.Samples/SessionPoolTest.Record.cs b/samples/Apache.IoTDB.Samples/SessionPoolTest.Record.cs index 3a7f7c3..4cf68f4 100644 --- a/samples/Apache.IoTDB.Samples/SessionPoolTest.Record.cs +++ b/samples/Apache.IoTDB.Samples/SessionPoolTest.Record.cs @@ -305,12 +305,12 @@ public async Task TestInsertRecords() row = res.Next(); break; } - + Console.WriteLine($"{testDatabaseName}.{testDevice}.{row.Measurements[0]} {testMeasurements[3]}"); System.Diagnostics.Debug.Assert($"{testDatabaseName}.{testDevice}.{testMeasurements[3]}" == row.Measurements[0]); System.Diagnostics.Debug.Assert($"{testDatabaseName}.{testDevice}.{testMeasurements[1]}" == row.Measurements[1]); System.Diagnostics.Debug.Assert($"{testDatabaseName}.{testDevice}.{testMeasurements[2]}" == row.Measurements[2]); - + status = await session_pool.DeleteDatabaseAsync(testDatabaseName); System.Diagnostics.Debug.Assert(status == 0); await session_pool.Close(); @@ -641,7 +641,7 @@ public async Task TestInsertRecordsWithAllType() var rowRecord2 = new RowRecord(2, values2, measurements, dataTypes); var rowRecord3 = new RowRecord(3, values3, measurements, dataTypes); - var device_id = new List { string.Format("{0}.{1}", testDatabaseName, testDevice),string.Format("{0}.{1}", testDatabaseName, testDevice),string.Format("{0}.{1}", testDatabaseName, testDevice) }; + var device_id = new List { string.Format("{0}.{1}", testDatabaseName, testDevice), string.Format("{0}.{1}", testDatabaseName, testDevice), string.Format("{0}.{1}", testDatabaseName, testDevice) }; var rowRecords = new List { rowRecord1, rowRecord2, rowRecord3 }; status = await session_pool.InsertRecordsAsync(device_id, rowRecords); @@ -664,4 +664,4 @@ public async Task TestInsertRecordsWithAllType() Console.WriteLine("TestInsertRecordsWithAllType Passed!"); } } -} \ No newline at end of file +} diff --git a/samples/Apache.IoTDB.Samples/SessionPoolTest.Tablet.cs b/samples/Apache.IoTDB.Samples/SessionPoolTest.Tablet.cs index 299050e..bf2ae17 100644 --- a/samples/Apache.IoTDB.Samples/SessionPoolTest.Tablet.cs +++ b/samples/Apache.IoTDB.Samples/SessionPoolTest.Tablet.cs @@ -271,7 +271,7 @@ public async Task TestInsertTabletWithAllType() TSDataType.BLOB, TSDataType.STRING }; - var timestamps = new List {1, 2}; + var timestamps = new List { 1, 2 }; var tablet = new Tablet(device_id, measurements, datatypes, values, timestamps); status = await session_pool.InsertTabletAsync(tablet); System.Diagnostics.Debug.Assert(status == 0); diff --git a/samples/Apache.IoTDB.Samples/SessionPoolTest.Template.cs b/samples/Apache.IoTDB.Samples/SessionPoolTest.Template.cs index 1d1d84d..866a7ab 100644 --- a/samples/Apache.IoTDB.Samples/SessionPoolTest.Template.cs +++ b/samples/Apache.IoTDB.Samples/SessionPoolTest.Template.cs @@ -101,4 +101,4 @@ public async Task TestSetAndUnsetSchemaTemplate() } } -} \ No newline at end of file +} diff --git a/samples/Apache.IoTDB.Samples/SessionPoolTest.TestNetwork.cs b/samples/Apache.IoTDB.Samples/SessionPoolTest.TestNetwork.cs index 8588066..9f2a61c 100644 --- a/samples/Apache.IoTDB.Samples/SessionPoolTest.TestNetwork.cs +++ b/samples/Apache.IoTDB.Samples/SessionPoolTest.TestNetwork.cs @@ -351,4 +351,4 @@ public async Task TestTestInsertTablets() } } -} \ No newline at end of file +} diff --git a/samples/Apache.IoTDB.Samples/SessionPoolTest.TimeSeries.cs b/samples/Apache.IoTDB.Samples/SessionPoolTest.TimeSeries.cs index 32be49a..049407c 100644 --- a/samples/Apache.IoTDB.Samples/SessionPoolTest.TimeSeries.cs +++ b/samples/Apache.IoTDB.Samples/SessionPoolTest.TimeSeries.cs @@ -194,4 +194,4 @@ await session_pool.CreateTimeSeries( } } -} \ No newline at end of file +} diff --git a/samples/Apache.IoTDB.Samples/SessionPoolTest.cs b/samples/Apache.IoTDB.Samples/SessionPoolTest.cs index f24a0a5..a189461 100644 --- a/samples/Apache.IoTDB.Samples/SessionPoolTest.cs +++ b/samples/Apache.IoTDB.Samples/SessionPoolTest.cs @@ -64,7 +64,8 @@ public SessionPoolTest(List _nodeUrls) } public async Task Test() { - if(nodeUrls.Count == 1){ + if (nodeUrls.Count == 1) + { await TestOpenWithNodeUrls(); await TestOpenWith2NodeUrls(); @@ -147,7 +148,8 @@ public async Task Test() await TestNonSqlBy_ADO(); } - else { + else + { await TestMultiNodeDataFetch(); } } @@ -580,7 +582,8 @@ public async Task TestLastDataQuery() Console.WriteLine("LastDataQuery Passed"); } - public async Task TestMultiNodeDataFetch(){ + public async Task TestMultiNodeDataFetch() + { System.Diagnostics.Debug.Assert(nodeUrls.Count > 1, "nodeUrls.Count should be greater than 1 in MultiNode Test"); var session_pool = new SessionPool.Builder() .SetUsername(username) @@ -596,7 +599,7 @@ public async Task TestMultiNodeDataFetch(){ var data_type_lst = new List { TSDataType.BOOLEAN, TSDataType.FLOAT }; var encoding_lst = new List { TSEncoding.PLAIN, TSEncoding.PLAIN }; var compressor_lst = new List { Compressor.SNAPPY, Compressor.SNAPPY }; - var ts_path_lst = new List() { + var ts_path_lst = new List() { string.Format("{0}.{1}.{2}", testDatabaseName, testDevice, testMeasurements[0]), string.Format("{0}.{1}.{2}", testDatabaseName, testDevice, testMeasurements[1]) }; @@ -631,4 +634,4 @@ public async Task TestMultiNodeDataFetch(){ Console.WriteLine("MultiNodeDataFetch Passed"); } } -} \ No newline at end of file +} diff --git a/samples/Apache.IoTDB.Samples/TableSessionPoolTest.cs b/samples/Apache.IoTDB.Samples/TableSessionPoolTest.cs index c0ef0ec..36d2b88 100644 --- a/samples/Apache.IoTDB.Samples/TableSessionPoolTest.cs +++ b/samples/Apache.IoTDB.Samples/TableSessionPoolTest.cs @@ -26,157 +26,157 @@ namespace Apache.IoTDB.Samples; public class TableSessionPoolTest { - private readonly SessionPoolTest sessionPoolTest; + private readonly SessionPoolTest sessionPoolTest; - public TableSessionPoolTest(SessionPoolTest sessionPoolTest) - { - this.sessionPoolTest = sessionPoolTest; - } + public TableSessionPoolTest(SessionPoolTest sessionPoolTest) + { + this.sessionPoolTest = sessionPoolTest; + } - public async Task Test() - { - await TestCleanup(); + public async Task Test() + { + await TestCleanup(); - await TestSelectAndInsert(); - await TestUseDatabase(); - // await TestCleanup(); - } + await TestSelectAndInsert(); + await TestUseDatabase(); + // await TestCleanup(); + } - public async Task TestSelectAndInsert() - { - var tableSessionPool = new TableSessionPool.Builder() - .SetNodeUrls(sessionPoolTest.nodeUrls) - .SetUsername(sessionPoolTest.username) - .SetPassword(sessionPoolTest.password) - .SetFetchSize(1024) - .Build(); + public async Task TestSelectAndInsert() + { + var tableSessionPool = new TableSessionPool.Builder() + .SetNodeUrls(sessionPoolTest.nodeUrls) + .SetUsername(sessionPoolTest.username) + .SetPassword(sessionPoolTest.password) + .SetFetchSize(1024) + .Build(); - await tableSessionPool.Open(false); + await tableSessionPool.Open(false); - if (sessionPoolTest.debug) tableSessionPool.OpenDebugMode(); + if (sessionPoolTest.debug) tableSessionPool.OpenDebugMode(); - await tableSessionPool.ExecuteNonQueryStatementAsync("CREATE DATABASE test1"); - await tableSessionPool.ExecuteNonQueryStatementAsync("CREATE DATABASE test2"); + await tableSessionPool.ExecuteNonQueryStatementAsync("CREATE DATABASE test1"); + await tableSessionPool.ExecuteNonQueryStatementAsync("CREATE DATABASE test2"); - await tableSessionPool.ExecuteNonQueryStatementAsync("use test2"); + await tableSessionPool.ExecuteNonQueryStatementAsync("use test2"); - // or use full qualified table name - await tableSessionPool.ExecuteNonQueryStatementAsync( - "create table test1.table1(region_id STRING TAG, plant_id STRING TAG, device_id STRING TAG, model STRING ATTRIBUTE, temperature FLOAT FIELD, humidity DOUBLE FIELD) with (TTL=3600000)"); + // or use full qualified table name + await tableSessionPool.ExecuteNonQueryStatementAsync( + "create table test1.table1(region_id STRING TAG, plant_id STRING TAG, device_id STRING TAG, model STRING ATTRIBUTE, temperature FLOAT FIELD, humidity DOUBLE FIELD) with (TTL=3600000)"); - await tableSessionPool.ExecuteNonQueryStatementAsync( - "create table table2(region_id STRING TAG, plant_id STRING TAG, color STRING ATTRIBUTE, temperature FLOAT FIELD, speed DOUBLE FIELD) with (TTL=6600000)"); + await tableSessionPool.ExecuteNonQueryStatementAsync( + "create table table2(region_id STRING TAG, plant_id STRING TAG, color STRING ATTRIBUTE, temperature FLOAT FIELD, speed DOUBLE FIELD) with (TTL=6600000)"); - // show tables from current database - var res = await tableSessionPool.ExecuteQueryStatementAsync("SHOW TABLES"); - res.ShowTableNames(); - while (res.HasNext()) Console.WriteLine(res.Next()); - await res.Close(); + // show tables from current database + var res = await tableSessionPool.ExecuteQueryStatementAsync("SHOW TABLES"); + res.ShowTableNames(); + while (res.HasNext()) Console.WriteLine(res.Next()); + await res.Close(); - // show tables by specifying another database - // using SHOW tables FROM - res = await tableSessionPool.ExecuteQueryStatementAsync("SHOW TABLES FROM test1"); - res.ShowTableNames(); - while (res.HasNext()) Console.WriteLine(res.Next()); - await res.Close(); + // show tables by specifying another database + // using SHOW tables FROM + res = await tableSessionPool.ExecuteQueryStatementAsync("SHOW TABLES FROM test1"); + res.ShowTableNames(); + while (res.HasNext()) Console.WriteLine(res.Next()); + await res.Close(); - var tableName = "testTable1"; - List columnNames = - new List { + var tableName = "testTable1"; + List columnNames = + new List { "region_id", "plant_id", "device_id", "model", "temperature", "humidity" }; - List dataTypes = - new List{ + List dataTypes = + new List{ TSDataType.STRING, TSDataType.STRING, TSDataType.STRING, TSDataType.STRING, TSDataType.FLOAT, TSDataType.DOUBLE}; - List columnCategories = - new List{ + List columnCategories = + new List{ ColumnCategory.TAG, ColumnCategory.TAG, ColumnCategory.TAG, ColumnCategory.ATTRIBUTE, ColumnCategory.FIELD, ColumnCategory.FIELD}; - var values = new List> { }; - var timestamps = new List { }; - for (long timestamp = 0; timestamp < 100; timestamp++) - { - timestamps.Add(timestamp); - values.Add(new List { "1", "5", "3", "A", 1.23F + timestamp, 111.1 + timestamp }); - } - var tablet = new Tablet(tableName, columnNames, columnCategories, dataTypes, values, timestamps); + var values = new List> { }; + var timestamps = new List { }; + for (long timestamp = 0; timestamp < 100; timestamp++) + { + timestamps.Add(timestamp); + values.Add(new List { "1", "5", "3", "A", 1.23F + timestamp, 111.1 + timestamp }); + } + var tablet = new Tablet(tableName, columnNames, columnCategories, dataTypes, values, timestamps); - await tableSessionPool.InsertAsync(tablet); + await tableSessionPool.InsertAsync(tablet); - res = await tableSessionPool.ExecuteQueryStatementAsync("select * from testTable1 " - + "where region_id = '1' and plant_id in ('3', '5') and device_id = '3'"); - res.ShowTableNames(); - while (res.HasNext()) Console.WriteLine(res.Next()); - await res.Close(); + res = await tableSessionPool.ExecuteQueryStatementAsync("select * from testTable1 " + + "where region_id = '1' and plant_id in ('3', '5') and device_id = '3'"); + res.ShowTableNames(); + while (res.HasNext()) Console.WriteLine(res.Next()); + await res.Close(); - await tableSessionPool.Close(); - } + await tableSessionPool.Close(); + } - public async Task TestUseDatabase() - { - var tableSessionPool = new TableSessionPool.Builder() - .SetNodeUrls(sessionPoolTest.nodeUrls) - .SetUsername(sessionPoolTest.username) - .SetPassword(sessionPoolTest.password) - .SetDatabase("test1") - .SetFetchSize(1024) - .Build(); + public async Task TestUseDatabase() + { + var tableSessionPool = new TableSessionPool.Builder() + .SetNodeUrls(sessionPoolTest.nodeUrls) + .SetUsername(sessionPoolTest.username) + .SetPassword(sessionPoolTest.password) + .SetDatabase("test1") + .SetFetchSize(1024) + .Build(); - await tableSessionPool.Open(false); + await tableSessionPool.Open(false); - if (sessionPoolTest.debug) tableSessionPool.OpenDebugMode(); + if (sessionPoolTest.debug) tableSessionPool.OpenDebugMode(); - // show tables from current database - var res = await tableSessionPool.ExecuteQueryStatementAsync("SHOW TABLES"); - res.ShowTableNames(); - while (res.HasNext()) Console.WriteLine(res.Next()); - await res.Close(); + // show tables from current database + var res = await tableSessionPool.ExecuteQueryStatementAsync("SHOW TABLES"); + res.ShowTableNames(); + while (res.HasNext()) Console.WriteLine(res.Next()); + await res.Close(); - await tableSessionPool.ExecuteNonQueryStatementAsync("use test2"); + await tableSessionPool.ExecuteNonQueryStatementAsync("use test2"); - // show tables from current database - res = await tableSessionPool.ExecuteQueryStatementAsync("SHOW TABLES"); - res.ShowTableNames(); - while (res.HasNext()) Console.WriteLine(res.Next()); - await res.Close(); + // show tables from current database + res = await tableSessionPool.ExecuteQueryStatementAsync("SHOW TABLES"); + res.ShowTableNames(); + while (res.HasNext()) Console.WriteLine(res.Next()); + await res.Close(); - await tableSessionPool.Close(); - } + await tableSessionPool.Close(); + } - public async Task TestCleanup() - { - var tableSessionPool = new TableSessionPool.Builder() - .SetNodeUrls(sessionPoolTest.nodeUrls) - .SetUsername(sessionPoolTest.username) - .SetPassword(sessionPoolTest.password) - .SetFetchSize(1024) - .Build(); + public async Task TestCleanup() + { + var tableSessionPool = new TableSessionPool.Builder() + .SetNodeUrls(sessionPoolTest.nodeUrls) + .SetUsername(sessionPoolTest.username) + .SetPassword(sessionPoolTest.password) + .SetFetchSize(1024) + .Build(); - await tableSessionPool.Open(false); + await tableSessionPool.Open(false); - if (sessionPoolTest.debug) tableSessionPool.OpenDebugMode(); + if (sessionPoolTest.debug) tableSessionPool.OpenDebugMode(); - await tableSessionPool.ExecuteNonQueryStatementAsync("drop database test1"); - await tableSessionPool.ExecuteNonQueryStatementAsync("drop database test2"); + await tableSessionPool.ExecuteNonQueryStatementAsync("drop database test1"); + await tableSessionPool.ExecuteNonQueryStatementAsync("drop database test2"); - await tableSessionPool.Close(); - } + await tableSessionPool.Close(); + } } diff --git a/src/Apache.IoTDB.Data/DataReaderExtensions.cs b/src/Apache.IoTDB.Data/DataReaderExtensions.cs index 75f1137..afb8eb7 100644 --- a/src/Apache.IoTDB.Data/DataReaderExtensions.cs +++ b/src/Apache.IoTDB.Data/DataReaderExtensions.cs @@ -32,7 +32,7 @@ public static class DataReaderExtensions { public static SessionPool CreateSession(this IoTDBConnectionStringBuilder db) { - return new SessionPool(db.DataSource, db.Port, db.Username, db.Password, db.FetchSize, db.ZoneId, db.PoolSize,db.Compression,db.TimeOut); + return new SessionPool(db.DataSource, db.Port, db.Username, db.Password, db.FetchSize, db.ZoneId, db.PoolSize, db.Compression, db.TimeOut); } public static List ToObject(this IDataReader dataReader) diff --git a/src/Apache.IoTDB.Data/IoTDBCommand.cs b/src/Apache.IoTDB.Data/IoTDBCommand.cs index adc9159..8daf86a 100644 --- a/src/Apache.IoTDB.Data/IoTDBCommand.cs +++ b/src/Apache.IoTDB.Data/IoTDBCommand.cs @@ -314,7 +314,7 @@ public override void Prepare() Debug.WriteLine($"_commandText:{_commandText}"); #endif int _affectRows = 0; - SessionDataSet dataSet=null; + SessionDataSet dataSet = null; bool isok = false; Task taskDataSet = null; if (_parameters.IsValueCreated) @@ -336,9 +336,9 @@ public override void Prepare() } } - if (isok && dataSet != null ) + if (isok && dataSet != null) { - dataReader = new IoTDBDataReader(this, dataSet, closeConnection ); + dataReader = new IoTDBDataReader(this, dataSet, closeConnection); } else if (taskDataSet.Status == TaskStatus.Running || !isok) { @@ -354,7 +354,7 @@ public override void Prepare() } else { - IoTDBException.ThrowExceptionForRC(_commandText, new IoTDBErrorResult() { Code = -10007, Error = $"Unknow Exception" }); + IoTDBException.ThrowExceptionForRC(_commandText, new IoTDBErrorResult() { Code = -10007, Error = $"Unknown Exception" }); } } catch when (unprepared) @@ -367,7 +367,7 @@ public override void Prepare() private RowRecord BindParamters(IoTDBParameterCollection pms) { var measures = new List(); - var values = new List (); + var values = new List(); for (int i = 0; i < pms.Count; i++) @@ -375,11 +375,11 @@ private RowRecord BindParamters(IoTDBParameterCollection pms) var tp = pms[i]; measures.Add(tp.ParameterName); - // _commandText = _commandText.Replace(tp.ParameterName, "?"); + // _commandText = _commandText.Replace(tp.ParameterName, "?"); switch (TypeInfo.GetTypeCode(tp.Value?.GetType())) { case TypeCode.Boolean: - values.Add ((tp.Value as bool?).GetValueOrDefault()); + values.Add((tp.Value as bool?).GetValueOrDefault()); break; case TypeCode.Char: values.Add(tp.Value as string); @@ -431,7 +431,7 @@ private RowRecord BindParamters(IoTDBParameterCollection pms) } } - return new RowRecord(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),values,measures); + return new RowRecord(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), values, measures); } /// @@ -523,8 +523,8 @@ public override int ExecuteNonQuery() throw new InvalidOperationException($"CallRequiresSetCommandText{nameof(ExecuteNonQuery)}"); } var result = Task.Run(() => _IoTDB.ExecuteNonQueryStatementAsync(_commandText)); - var ok = result.Wait(TimeSpan.FromSeconds(CommandTimeout)); - if (!ok) throw new TimeoutException(); + var ok = result.Wait(TimeSpan.FromSeconds(CommandTimeout)); + if (!ok) throw new TimeoutException(); return result.Result; } diff --git a/src/Apache.IoTDB.Data/IoTDBConnection.cs b/src/Apache.IoTDB.Data/IoTDBConnection.cs index 860f25e..96b3154 100644 --- a/src/Apache.IoTDB.Data/IoTDBConnection.cs +++ b/src/Apache.IoTDB.Data/IoTDBConnection.cs @@ -45,7 +45,7 @@ public partial class IoTDBConnection : DbConnection private string _connectionString; private ConnectionState _state; - internal SessionPool _IoTDB; + internal SessionPool _IoTDB; @@ -125,7 +125,7 @@ public override string ServerVersion throw new NotImplementedException(); } } - public string ClientVersion + public string ClientVersion { get { @@ -177,7 +177,7 @@ public override void Open() { OpenAsync().GetAwaiter().GetResult(); } - public override async Task OpenAsync(CancellationToken cancellationToken=default) + public override async Task OpenAsync(CancellationToken cancellationToken = default) { if (State == ConnectionState.Open) @@ -190,7 +190,7 @@ public override async Task OpenAsync(CancellationToken cancellationToken=def } await _IoTDB.Open(ConnectionStringBuilder.Compression, cancellationToken); - if (!_IoTDB.IsOpen()) + if (!_IoTDB.IsOpen()) { IoTDBException.ThrowExceptionForRC(-1, "Can't open IoTDB server."); } @@ -214,7 +214,7 @@ public override async Task CloseAsync() #endif { if (State != ConnectionState.Closed) - await _IoTDB.Close(); + await _IoTDB.Close(); Transaction?.Dispose(); _nowdatabase = string.Empty; foreach (var reference in _commands) @@ -343,9 +343,9 @@ protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLeve } internal string _nowdatabase = string.Empty; - internal bool SelectedDataBase => _nowdatabase != string.Empty ; + internal bool SelectedDataBase => _nowdatabase != string.Empty; - public override string Database => throw new NotSupportedException(); + public override string Database => throw new NotSupportedException(); /// /// Changes the current database. diff --git a/src/Apache.IoTDB.Data/IoTDBConnectionStringBuilder.cs b/src/Apache.IoTDB.Data/IoTDBConnectionStringBuilder.cs index 8c71b5e..c2cac87 100644 --- a/src/Apache.IoTDB.Data/IoTDBConnectionStringBuilder.cs +++ b/src/Apache.IoTDB.Data/IoTDBConnectionStringBuilder.cs @@ -65,24 +65,24 @@ private enum Keywords private string _userName = "root"; private string _password = "root"; private bool _enableRpcCompression = false; - private int _fetchSize = 1800; + private int _fetchSize = 1800; private string _zoneId = "UTC+08:00"; - private int _port = 6667; - private int _poolSize =8; - private int _timeOut=10000; + private int _port = 6667; + private int _poolSize = 8; + private int _timeOut = 10000; static IoTDBConnectionStringBuilder() { var validKeywords = new string[9]; validKeywords[(int)Keywords.DataSource] = DataSourceKeyword; - validKeywords[(int)Keywords.Username] = UserNameKeyword; + validKeywords[(int)Keywords.Username] = UserNameKeyword; validKeywords[(int)Keywords.Password] = PasswordKeyword; validKeywords[(int)Keywords.Port] = PortKeyword; validKeywords[(int)Keywords.FetchSize] = FetchSizeKeyword; validKeywords[(int)Keywords.Compression] = CompressionKeyword; validKeywords[(int)Keywords.PoolSize] = PoolSizeKeyword; validKeywords[(int)Keywords.ZoneId] = ZoneIdKeyword; - validKeywords[(int)Keywords.TimeOut] =TimeOutKeyword; + validKeywords[(int)Keywords.TimeOut] = TimeOutKeyword; _validKeywords = validKeywords; _keywords = new Dictionary(9, StringComparer.OrdinalIgnoreCase) @@ -129,13 +129,13 @@ public virtual string Username get => _userName; set => base[UserNameKeyword] = _userName = value; } - + public virtual string Password { get => _password; set => base[PasswordKeyword] = _password = value; } - public virtual int Port + public virtual int Port { get => _port; set => base[PortKeyword] = _port = value; @@ -163,7 +163,7 @@ public virtual string ZoneId } public virtual int TimeOut - { + { get => _timeOut; set => base[PoolSizeKeyword] = _timeOut = value; } @@ -215,19 +215,19 @@ public override object this[string keyword] return; } - + switch (GetIndex(keyword)) { case Keywords.DataSource: DataSource = Convert.ToString(value, CultureInfo.InvariantCulture); return; case Keywords.Username: - Username= Convert.ToString(value, CultureInfo.InvariantCulture); + Username = Convert.ToString(value, CultureInfo.InvariantCulture); return; case Keywords.Password: Password = Convert.ToString(value, CultureInfo.InvariantCulture); return; - + case Keywords.Port: Port = Convert.ToInt32(value, CultureInfo.InvariantCulture); return; @@ -354,7 +354,7 @@ public override bool TryGetValue(string keyword, out object value) private object GetAt(Keywords index) { - + switch (index) { case Keywords.DataSource: @@ -363,7 +363,7 @@ private object GetAt(Keywords index) return Password; case Keywords.Username: return Username; - + case Keywords.Port: return Port; case Keywords.FetchSize: @@ -401,7 +401,7 @@ private void Reset(Keywords index) _userName = "root"; return; case Keywords.Port: - _port=6667; + _port = 6667; return; case Keywords.FetchSize: _fetchSize = 1800; diff --git a/src/Apache.IoTDB.Data/IoTDBDataReader.cs b/src/Apache.IoTDB.Data/IoTDBDataReader.cs index 88c4de2..da4f107 100644 --- a/src/Apache.IoTDB.Data/IoTDBDataReader.cs +++ b/src/Apache.IoTDB.Data/IoTDBDataReader.cs @@ -41,12 +41,12 @@ public class IoTDBDataReader : DbDataReader private bool _hasRows; private readonly int _recordsAffected; private bool _closed; - private readonly List _metas; + private readonly List _metas; private bool _closeConnection; private int _fieldCount; - RowRecord rowdata= null; + RowRecord rowdata = null; SessionDataSet _dataSet; @@ -57,7 +57,7 @@ internal IoTDBDataReader(IoTDBCommand IoTDBCommand, SessionDataSet dataSet, bool _closeConnection = closeConnection; _fieldCount = dataSet.ColumnNames.Count; _hasRows = dataSet.RowCount > 0; - _recordsAffected =dataSet.RowCount; + _recordsAffected = dataSet.RowCount; _closed = _closeConnection; _metas = dataSet.ColumnNames; _dataSet = dataSet; @@ -73,7 +73,7 @@ internal IoTDBDataReader(IoTDBCommand IoTDBCommand, SessionDataSet dataSet, bool /// Gets the number of columns in the current row. /// /// The number of columns in the current row. - public override int FieldCount => _fieldCount+1; + public override int FieldCount => _fieldCount + 1; /// /// Gets a value indicating whether the data reader contains any rows. @@ -178,7 +178,7 @@ protected override void Dispose(bool disposing) _dataSet.Close().GetAwaiter().GetResult(); _command.DataReader = null; - if (_closeConnection ) + if (_closeConnection) { _command.Connection.Close(); _closed = true; @@ -194,7 +194,7 @@ protected override void Dispose(bool disposing) /// The name of the column. public override string GetName(int ordinal) { - return ordinal==0? "timestamp" : rowdata.Measurements[ordinal-1]; + return ordinal == 0 ? "timestamp" : rowdata.Measurements[ordinal - 1]; } /// @@ -203,7 +203,7 @@ public override string GetName(int ordinal) /// The name of the column. /// The zero-based column ordinal. public override int GetOrdinal(string name) - => "timestamp"==name?0: rowdata.Measurements.IndexOf( name)+1; + => "timestamp" == name ? 0 : rowdata.Measurements.IndexOf(name) + 1; public override string GetDataTypeName(int ordinal) { @@ -218,7 +218,7 @@ public override string GetDataTypeName(int ordinal) public override Type GetFieldType(int ordinal) { - return ordinal==0?typeof(DateTime): rowdata.GetCrlType(ordinal-1); + return ordinal == 0 ? typeof(DateTime) : rowdata.GetCrlType(ordinal - 1); } /// @@ -438,9 +438,9 @@ public override int GetValues(object[] values) for (int i = 0; i < _fieldCount; i++) { var obj = rowdata.Values[i]; - if (obj != null ) + if (obj != null) { - values[i+1] = obj; + values[i + 1] = obj; count++; } } @@ -458,8 +458,8 @@ public override DataTable GetSchemaTable() { rowdata = _dataSet.GetRow(); } - var schemaTable = new DataTable("SchemaTable"); - if (_metas != null && rowdata !=null) + var schemaTable = new DataTable("SchemaTable"); + if (_metas != null && rowdata != null) { var ColumnName = new DataColumn(SchemaTableColumn.ColumnName, typeof(string)); var ColumnOrdinal = new DataColumn(SchemaTableColumn.ColumnOrdinal, typeof(int)); @@ -534,11 +534,11 @@ public override DataTable GetSchemaTable() schemaTable.Rows.Add(schemaRow1); - for (var i = 1; i < rowdata.Measurements.Count+1; i++) + for (var i = 1; i < rowdata.Measurements.Count + 1; i++) { var schemaRow = schemaTable.NewRow(); - var columnName = rowdata.Measurements[i-1] ; + var columnName = rowdata.Measurements[i - 1]; schemaRow[ColumnName] = columnName; schemaRow[ColumnOrdinal] = i; @@ -554,7 +554,7 @@ public override DataTable GetSchemaTable() schemaRow[DataTypeName] = GetDataTypeName(i); schemaRow[IsExpression] = columnName == null; schemaRow[IsLong] = DBNull.Value; - schemaRow[IsKey]= false; + schemaRow[IsKey] = false; schemaRow[AllowDBNull] = true; schemaTable.Rows.Add(schemaRow); } diff --git a/src/Apache.IoTDB.Data/IoTDBException.cs b/src/Apache.IoTDB.Data/IoTDBException.cs index 978c9e8..2f39125 100644 --- a/src/Apache.IoTDB.Data/IoTDBException.cs +++ b/src/Apache.IoTDB.Data/IoTDBException.cs @@ -47,7 +47,7 @@ public IoTDBException(IoTDBErrorResult IoTDBError, Exception ex) : base(IoTDBErr public override string Message => _IoTDBError?.Error; - public override int ErrorCode => (int) _IoTDBError?.Code; + public override int ErrorCode => (int)_IoTDBError?.Code; /// /// Throws an exception with a specific IoTDB error code value. /// @@ -58,29 +58,29 @@ public IoTDBException(IoTDBErrorResult IoTDBError, Exception ex) : base(IoTDBErr /// public static void ThrowExceptionForRC(string _commandText, IoTDBErrorResult IoTDBError) { - var te = new IoTDBException(IoTDBError); - te.Data.Add("commandText", _commandText); - throw te; + var tmp_exception = new IoTDBException(IoTDBError); + tmp_exception.Data.Add("commandText", _commandText); + throw tmp_exception; } - public static void ThrowExceptionForRC( IoTDBErrorResult IoTDBError) + public static void ThrowExceptionForRC(IoTDBErrorResult IoTDBError) { - var te = new IoTDBException(IoTDBError); - throw te; + var tmp_exception = new IoTDBException(IoTDBError); + throw tmp_exception; } public static void ThrowExceptionForRC(IntPtr _IoTDB) { - var te = new IoTDBException(new IoTDBErrorResult() { }); - throw te; + var tmp_exception = new IoTDBException(new IoTDBErrorResult() { }); + throw tmp_exception; } public static void ThrowExceptionForRC(int code, string message, Exception ex) { - var te = new IoTDBException(new IoTDBErrorResult() { Code = code, Error = message }, ex); - throw te; + var tmp_exception = new IoTDBException(new IoTDBErrorResult() { Code = code, Error = message }, ex); + throw tmp_exception; } public static void ThrowExceptionForRC(int code, string message) { - var te = new IoTDBException(new IoTDBErrorResult() { Code = code, Error = message }); - throw te; + var tmp_exception = new IoTDBException(new IoTDBErrorResult() { Code = code, Error = message }); + throw tmp_exception; } } } diff --git a/src/Apache.IoTDB.Data/IoTDBParameter.cs b/src/Apache.IoTDB.Data/IoTDBParameter.cs index 03b7667..f49ea99 100644 --- a/src/Apache.IoTDB.Data/IoTDBParameter.cs +++ b/src/Apache.IoTDB.Data/IoTDBParameter.cs @@ -17,7 +17,7 @@ * under the License. */ - using System; +using System; using System.Data; using System.Data.Common; @@ -42,7 +42,7 @@ public class IoTDBParameter : DbParameter public IoTDBParameter() { } - + /// /// Initializes a new instance of the class. /// @@ -101,7 +101,7 @@ public IoTDBParameter(string name, TSDataType type, int size, string sourceColum /// /// The type of the parameter. /// Due to IoTDB's dynamic type system, parameter values are not converted. - + public override DbType DbType { get; set; } = DbType.String; /// @@ -221,6 +221,6 @@ public virtual void ResetIoTDBType() IoTDBType = TSDataType.NONE; } - + } } diff --git a/src/Apache.IoTDB.Data/IoTDBParameterCollection.cs b/src/Apache.IoTDB.Data/IoTDBParameterCollection.cs index 201448d..830e1e6 100644 --- a/src/Apache.IoTDB.Data/IoTDBParameterCollection.cs +++ b/src/Apache.IoTDB.Data/IoTDBParameterCollection.cs @@ -183,7 +183,7 @@ public virtual IoTDBParameter AddWithValue(string parameterName, object value) /// The name of the parameter. /// The value of the parameter. Can be null. /// The parameter that was added. - public virtual IoTDBParameter AddWithValue( object value) + public virtual IoTDBParameter AddWithValue(object value) { var parameter = new IoTDBParameter(Guid.NewGuid().ToString(), value); Add(parameter); @@ -354,7 +354,7 @@ protected override void SetParameter(int index, DbParameter value) protected override void SetParameter(string parameterName, DbParameter value) => SetParameter(IndexOfChecked(parameterName), value); - + private int IndexOfChecked(string parameterName) { diff --git a/src/Apache.IoTDB.Data/IoTDBResult.cs b/src/Apache.IoTDB.Data/IoTDBResult.cs index 1da73f2..fae9066 100644 --- a/src/Apache.IoTDB.Data/IoTDBResult.cs +++ b/src/Apache.IoTDB.Data/IoTDBResult.cs @@ -26,10 +26,10 @@ namespace Apache.IoTDB.Data public class IoTDBErrorResult { - public int Code { get; set; } + public int Code { get; set; } /// /// /// - public string Error { get; set; } + public string Error { get; set; } } } diff --git a/src/Apache.IoTDB.Data/IoTDBTransaction.cs b/src/Apache.IoTDB.Data/IoTDBTransaction.cs index a0a4c79..34fc547 100644 --- a/src/Apache.IoTDB.Data/IoTDBTransaction.cs +++ b/src/Apache.IoTDB.Data/IoTDBTransaction.cs @@ -62,7 +62,7 @@ internal bool ExternalRollback /// /// The isolation level for the transaction. public override IsolationLevel IsolationLevel => IsolationLevel.Unspecified; - + /// /// Applies the changes made in the transaction. @@ -73,7 +73,7 @@ public override void Commit() //{ // throw new InvalidOperationException(Resources.TransactionCompleted); //} - + //_connection.ExecuteNonQuery("COMMIT;"); Complete(); } @@ -109,7 +109,7 @@ protected override void Dispose(bool disposing) private void Complete() { - if (_connection!=null)_connection.Transaction = null; + if (_connection != null) _connection.Transaction = null; _connection = null; _completed = true; } diff --git a/src/Apache.IoTDB/Client.cs b/src/Apache.IoTDB/Client.cs index dead7b6..03238d2 100644 --- a/src/Apache.IoTDB/Client.cs +++ b/src/Apache.IoTDB/Client.cs @@ -38,4 +38,4 @@ public Client(IClientRPCService.Client client, long sessionId, long statementId, EndPoint = endpoint; } } -} \ No newline at end of file +} diff --git a/src/Apache.IoTDB/ConcurrentClientQueue.cs b/src/Apache.IoTDB/ConcurrentClientQueue.cs index 0c54a12..e53d3f3 100644 --- a/src/Apache.IoTDB/ConcurrentClientQueue.cs +++ b/src/Apache.IoTDB/ConcurrentClientQueue.cs @@ -71,7 +71,8 @@ public Client Take() { Client client = null; Monitor.Enter(ClientQueue); - while(true){ + while (true) + { bool timeout = false; if (ClientQueue.IsEmpty) { @@ -79,7 +80,8 @@ public Client Take() } ClientQueue.TryDequeue(out client); - if(client != null || timeout){ + if (client != null || timeout) + { break; } } @@ -91,4 +93,4 @@ public Client Take() return client; } } -} \ No newline at end of file +} diff --git a/src/Apache.IoTDB/DataStructure/BitMap.cs b/src/Apache.IoTDB/DataStructure/BitMap.cs index d5a66c6..5a1b607 100644 --- a/src/Apache.IoTDB/DataStructure/BitMap.cs +++ b/src/Apache.IoTDB/DataStructure/BitMap.cs @@ -146,4 +146,4 @@ public bool isAllMarked() } return true; } -} \ No newline at end of file +} diff --git a/src/Apache.IoTDB/DataStructure/ByteBuffer.cs b/src/Apache.IoTDB/DataStructure/ByteBuffer.cs index b97583f..a3e1823 100644 --- a/src/Apache.IoTDB/DataStructure/ByteBuffer.cs +++ b/src/Apache.IoTDB/DataStructure/ByteBuffer.cs @@ -135,10 +135,10 @@ public string GetStr() public byte[] GetBinary() { - var length = GetInt(); - var buff = _buffer[_readPos..(_readPos + length)]; - _readPos += length; - return buff; + var length = GetInt(); + var buff = _buffer[_readPos..(_readPos + length)]; + _readPos += length; + return buff; } public byte[] GetBuffer() @@ -225,7 +225,7 @@ public void AddStr(string value) _writePos += strBuf.Length; } - public void AddBinary(byte[] value) + public void AddBinary(byte[] value) { AddInt(value.Length); @@ -251,4 +251,4 @@ public void AddByte(byte value) _writePos += 1; } } -} \ No newline at end of file +} diff --git a/src/Apache.IoTDB/DataStructure/RowRecord.cs b/src/Apache.IoTDB/DataStructure/RowRecord.cs index 9674f49..c5853bf 100644 --- a/src/Apache.IoTDB/DataStructure/RowRecord.cs +++ b/src/Apache.IoTDB/DataStructure/RowRecord.cs @@ -32,18 +32,18 @@ public class RowRecord public List DataTypes { get; } public RowRecord(DateTime timestamp, List values, List measurements, List dataTypes) - :this(new DateTimeOffset(timestamp.ToUniversalTime()).ToUnixTimeMilliseconds(), values,measurements, dataTypes) + : this(new DateTimeOffset(timestamp.ToUniversalTime()).ToUnixTimeMilliseconds(), values, measurements, dataTypes) { } public RowRecord(DateTime timestamp, List values, List measurements, List dataTypes) - :this(new DateTimeOffset(timestamp.ToUniversalTime()).ToUnixTimeMilliseconds(), values,measurements, dataTypes) + : this(new DateTimeOffset(timestamp.ToUniversalTime()).ToUnixTimeMilliseconds(), values, measurements, dataTypes) { } [Obsolete("Use the constructor with List instead")] public RowRecord(DateTime timestamp, List values, List measurements) - :this(new DateTimeOffset(timestamp.ToUniversalTime()).ToUnixTimeMilliseconds(), values,measurements) + : this(new DateTimeOffset(timestamp.ToUniversalTime()).ToUnixTimeMilliseconds(), values, measurements) { } [Obsolete("Use the constructor with List instead")] @@ -53,7 +53,8 @@ public RowRecord(long timestamps, List values, List measurements Values = values; Measurements = measurements; } - public RowRecord(long timestamps, List values, List measurements, List dataTypes){ + public RowRecord(long timestamps, List values, List measurements, List dataTypes) + { Timestamps = timestamps; Values = values; Measurements = measurements; @@ -132,27 +133,27 @@ public override string ToString() foreach (var rowValue in Values) { str += "\t\t"; - if(rowValue is byte[] bytes) + if (rowValue is byte[] bytes) { - str += Utils.ByteArrayToHexString(bytes); + str += Utils.ByteArrayToHexString(bytes); } else { - str += rowValue.ToString(); + str += rowValue.ToString(); } } return str; } - + public Type GetCrlType(int index) { - Type tSDataType = typeof(object); + Type tSDataType = typeof(object); var valueType = Values[index]; switch (valueType) { case bool _: - tSDataType = typeof( bool); + tSDataType = typeof(bool); break; case int _: tSDataType = typeof(int); @@ -190,43 +191,43 @@ public byte[] ToBytes() switch (dataType) { case TSDataType.BOOLEAN: - buffer.AddByte((byte) TSDataType.BOOLEAN); + buffer.AddByte((byte)TSDataType.BOOLEAN); buffer.AddBool((bool)value); break; case TSDataType.INT32: - buffer.AddByte((byte) TSDataType.INT32); + buffer.AddByte((byte)TSDataType.INT32); buffer.AddInt((int)value); break; case TSDataType.INT64: - buffer.AddByte((byte) TSDataType.INT64); + buffer.AddByte((byte)TSDataType.INT64); buffer.AddLong((long)value); break; case TSDataType.FLOAT: - buffer.AddByte((byte) TSDataType.FLOAT); + buffer.AddByte((byte)TSDataType.FLOAT); buffer.AddFloat((float)value); break; case TSDataType.DOUBLE: - buffer.AddByte((byte) TSDataType.DOUBLE); + buffer.AddByte((byte)TSDataType.DOUBLE); buffer.AddDouble((double)value); break; case TSDataType.TEXT: - buffer.AddByte((byte) TSDataType.TEXT); + buffer.AddByte((byte)TSDataType.TEXT); buffer.AddStr((string)value); break; case TSDataType.TIMESTAMP: - buffer.AddByte((byte) TSDataType.TIMESTAMP); + buffer.AddByte((byte)TSDataType.TIMESTAMP); buffer.AddLong((long)value); break; case TSDataType.BLOB: - buffer.AddByte((byte) TSDataType.BLOB); + buffer.AddByte((byte)TSDataType.BLOB); buffer.AddBinary((byte[])value); break; case TSDataType.DATE: - buffer.AddByte((byte) TSDataType.DATE); + buffer.AddByte((byte)TSDataType.DATE); buffer.AddInt(Utils.ParseDateToInt((DateTime)value)); break; case TSDataType.STRING: - buffer.AddByte((byte) TSDataType.STRING); + buffer.AddByte((byte)TSDataType.STRING); buffer.AddStr((string)value); break; default: @@ -262,4 +263,4 @@ private TSDataType GetTSDataType(object value) } } } -} \ No newline at end of file +} diff --git a/src/Apache.IoTDB/DataStructure/SessionDataSet.cs b/src/Apache.IoTDB/DataStructure/SessionDataSet.cs index 7ba49ea..3d606f4 100644 --- a/src/Apache.IoTDB/DataStructure/SessionDataSet.cs +++ b/src/Apache.IoTDB/DataStructure/SessionDataSet.cs @@ -81,18 +81,25 @@ public SessionDataSet(string sql, TSExecuteStatementResp resp, Client client, Co int deduplicateIdx = 0; Dictionary columnToFirstIndexMap = new Dictionary(); - for(var i = 0; i < _columnSize; i++){ + for (var i = 0; i < _columnSize; i++) + { var columnName = _columnNames[i]; - if(_columnNameIndexMap.ContainsKey(columnName)){ + if (_columnNameIndexMap.ContainsKey(columnName)) + { _duplicateLocation[i] = columnToFirstIndexMap[columnName]; - } else { + } + else + { columnToFirstIndexMap[columnName] = i; - if(resp.ColumnNameIndexMap != null) { + if (resp.ColumnNameIndexMap != null) + { int valueIndex = resp.ColumnNameIndexMap[columnName]; _columnNameIndexMap[columnName] = valueIndex; _valueBufferLst.Add(new ByteBuffer(_queryDataset.ValueList[valueIndex])); _bitmapBufferLst.Add(new ByteBuffer(_queryDataset.BitmapList[valueIndex])); - } else { + } + else + { _columnNameIndexMap[columnName] = deduplicateIdx; _valueBufferLst.Add(new ByteBuffer(_queryDataset.ValueList[deduplicateIdx])); _bitmapBufferLst.Add(new ByteBuffer(_queryDataset.BitmapList[deduplicateIdx])); @@ -182,14 +189,14 @@ private TSDataType GetDataTypeFromStr(string str) private void ConstructOneRow() { - List fieldLst = new List(); + List fieldList = new List(); for (int i = 0; i < _columnSize; i++) { if (_duplicateLocation.ContainsKey(i)) { - var field = fieldLst[_duplicateLocation[i]]; - fieldLst.Add(field); + var field = fieldList[_duplicateLocation[i]]; + fieldList.Add(field); } else { @@ -213,7 +220,7 @@ private void ConstructOneRow() localField = columnValueBuffer.GetBool(); break; case TSDataType.INT32: - // case TSDataType.DATE: + // case TSDataType.DATE: localField = columnValueBuffer.GetInt(); break; case TSDataType.DATE: @@ -231,7 +238,7 @@ private void ConstructOneRow() break; case TSDataType.TEXT: case TSDataType.STRING: - // case TSDataType.BLOB: + // case TSDataType.BLOB: localField = columnValueBuffer.GetStr(); break; case TSDataType.BLOB: @@ -243,19 +250,19 @@ private void ConstructOneRow() throw new TException(err_msg, null); } - fieldLst.Add(localField); + fieldList.Add(localField); } else { localField = null; - fieldLst.Add(DBNull.Value); + fieldList.Add(DBNull.Value); } } } long timestamp = _timeBuffer.GetLong(); _rowIndex += 1; - _cachedRowRecord = new RowRecord(timestamp, fieldLst, _columnNames); + _cachedRowRecord = new RowRecord(timestamp, fieldList, _columnNames); } private bool IsNull(int loc, int row_index) @@ -359,4 +366,4 @@ public void Dispose() GC.SuppressFinalize(this); } } -} \ No newline at end of file +} diff --git a/src/Apache.IoTDB/DataStructure/Tablet.cs b/src/Apache.IoTDB/DataStructure/Tablet.cs index b6e2ca1..34007ee 100644 --- a/src/Apache.IoTDB/DataStructure/Tablet.cs +++ b/src/Apache.IoTDB/DataStructure/Tablet.cs @@ -38,7 +38,7 @@ namespace Apache.IoTDB.DataStructure * * @deprecated * Notice: The tablet should not have empty cell - * + * * From 0.13 IoTDB Server, tablet could have empty cell * */ @@ -471,4 +471,4 @@ public byte[] GetBinaryValues() return buffer.GetBuffer(); } } -} \ No newline at end of file +} diff --git a/src/Apache.IoTDB/IoTDBConstants.cs b/src/Apache.IoTDB/IoTDBConstants.cs index 7dddd72..13fe80e 100644 --- a/src/Apache.IoTDB/IoTDBConstants.cs +++ b/src/Apache.IoTDB/IoTDBConstants.cs @@ -96,8 +96,9 @@ public class TsFileConstant private TsFileConstant() { } } - public class IoTDBConstant { + public class IoTDBConstant + { public static string TREE_SQL_DIALECT = "tree"; public static string TABLE_SQL_DIALECT = "table"; } -} \ No newline at end of file +} diff --git a/src/Apache.IoTDB/SessionPool.Builder.cs b/src/Apache.IoTDB/SessionPool.Builder.cs index fcd10ce..69b8e42 100644 --- a/src/Apache.IoTDB/SessionPool.Builder.cs +++ b/src/Apache.IoTDB/SessionPool.Builder.cs @@ -24,116 +24,116 @@ namespace Apache.IoTDB; public partial class SessionPool { - public class Builder - { - private string _host = "localhost"; - private int _port = 6667; - private string _username = "root"; - private string _password = "root"; - private int _fetchSize = 1024; - private string _zoneId = "UTC+08:00"; - private int _poolSize = 8; - private bool _enableRpcCompression = false; - private int _connectionTimeoutInMs = 500; - private string _sqlDialect = IoTDBConstant.TREE_SQL_DIALECT; - private string _database = ""; - private List _nodeUrls = new List(); - - public Builder SetHost(string host) + public class Builder { - _host = host; - return this; + private string _host = "localhost"; + private int _port = 6667; + private string _username = "root"; + private string _password = "root"; + private int _fetchSize = 1024; + private string _zoneId = "UTC+08:00"; + private int _poolSize = 8; + private bool _enableRpcCompression = false; + private int _connectionTimeoutInMs = 500; + private string _sqlDialect = IoTDBConstant.TREE_SQL_DIALECT; + private string _database = ""; + private List _nodeUrls = new List(); + + public Builder SetHost(string host) + { + _host = host; + return this; + } + + public Builder SetPort(int port) + { + _port = port; + return this; + } + + public Builder SetUsername(string username) + { + _username = username; + return this; + } + + public Builder SetPassword(string password) + { + _password = password; + return this; + } + + public Builder SetFetchSize(int fetchSize) + { + _fetchSize = fetchSize; + return this; + } + + public Builder SetZoneId(string zoneId) + { + _zoneId = zoneId; + return this; + } + + public Builder SetPoolSize(int poolSize) + { + _poolSize = poolSize; + return this; + } + + public Builder SetEnableRpcCompression(bool enableRpcCompression) + { + _enableRpcCompression = enableRpcCompression; + return this; + } + + public Builder SetConnectionTimeoutInMs(int timeout) + { + _connectionTimeoutInMs = timeout; + return this; + } + + public Builder SetNodeUrl(List nodeUrls) + { + _nodeUrls = nodeUrls; + return this; + } + + protected internal Builder SetSqlDialect(string sqlDialect) + { + _sqlDialect = sqlDialect; + return this; + } + + protected internal Builder SetDatabase(string database) + { + _database = database; + return this; + } + + public Builder() + { + _host = "localhost"; + _port = 6667; + _username = "root"; + _password = "root"; + _fetchSize = 1024; + _zoneId = "UTC+08:00"; + _poolSize = 8; + _enableRpcCompression = false; + _connectionTimeoutInMs = 500; + _sqlDialect = IoTDBConstant.TREE_SQL_DIALECT; + _database = ""; + } + + public SessionPool Build() + { + // if nodeUrls is not empty, use nodeUrls to create session pool + if (_nodeUrls.Count > 0) + { + return new SessionPool(_nodeUrls, _username, _password, _fetchSize, _zoneId, _poolSize, _enableRpcCompression, _connectionTimeoutInMs, _sqlDialect, _database); + } + return new SessionPool(_host, _port, _username, _password, _fetchSize, _zoneId, _poolSize, _enableRpcCompression, _connectionTimeoutInMs, _sqlDialect, _database); + } } - - public Builder SetPort(int port) - { - _port = port; - return this; - } - - public Builder SetUsername(string username) - { - _username = username; - return this; - } - - public Builder SetPassword(string password) - { - _password = password; - return this; - } - - public Builder SetFetchSize(int fetchSize) - { - _fetchSize = fetchSize; - return this; - } - - public Builder SetZoneId(string zoneId) - { - _zoneId = zoneId; - return this; - } - - public Builder SetPoolSize(int poolSize) - { - _poolSize = poolSize; - return this; - } - - public Builder SetEnableRpcCompression(bool enableRpcCompression) - { - _enableRpcCompression = enableRpcCompression; - return this; - } - - public Builder SetConnectionTimeoutInMs(int timeout) - { - _connectionTimeoutInMs = timeout; - return this; - } - - public Builder SetNodeUrl(List nodeUrls) - { - _nodeUrls = nodeUrls; - return this; - } - - protected internal Builder SetSqlDialect(string sqlDialect) - { - _sqlDialect = sqlDialect; - return this; - } - - protected internal Builder SetDatabase(string database) - { - _database = database; - return this; - } - - public Builder() - { - _host = "localhost"; - _port = 6667; - _username = "root"; - _password = "root"; - _fetchSize = 1024; - _zoneId = "UTC+08:00"; - _poolSize = 8; - _enableRpcCompression = false; - _connectionTimeoutInMs = 500; - _sqlDialect = IoTDBConstant.TREE_SQL_DIALECT; - _database = ""; - } - - public SessionPool Build() - { - // if nodeUrls is not empty, use nodeUrls to create session pool - if (_nodeUrls.Count > 0) - { - return new SessionPool(_nodeUrls, _username, _password, _fetchSize, _zoneId, _poolSize, _enableRpcCompression, _connectionTimeoutInMs, _sqlDialect, _database); - } - return new SessionPool(_host, _port, _username, _password, _fetchSize, _zoneId, _poolSize, _enableRpcCompression, _connectionTimeoutInMs, _sqlDialect, _database); - } - } } diff --git a/src/Apache.IoTDB/SessionPool.cs b/src/Apache.IoTDB/SessionPool.cs index c6bd70f..0fb9089 100644 --- a/src/Apache.IoTDB/SessionPool.cs +++ b/src/Apache.IoTDB/SessionPool.cs @@ -35,1750 +35,1749 @@ namespace Apache.IoTDB { - public partial class SessionPool : IDisposable - { - private static readonly TSProtocolVersion ProtocolVersion = TSProtocolVersion.IOTDB_SERVICE_PROTOCOL_V3; - - private readonly string _username; - private readonly string _password; - private bool _enableRpcCompression; - private string _zoneId; - private readonly List _nodeUrls = new(); - private readonly List _endPoints = new(); - private readonly string _host; - private readonly int _port; - private readonly int _fetchSize; - /// - /// _timeout is the amount of time a Session will wait for a send operation to complete successfully. - /// - private readonly int _timeout; - private readonly int _poolSize = 4; - private readonly string _sqlDialect = IoTDBConstant.TREE_SQL_DIALECT; - private string _database; - private readonly Utils _utilFunctions = new(); - private const int RetryNum = 3; - private bool _debugMode; - private bool _isClose = true; - private ConcurrentClientQueue _clients; - private ILogger _logger; - public delegate Task AsyncOperation(Client client); - - - [Obsolete("This method is deprecated, please use new SessionPool.Builder().")] - public SessionPool(string host, int port, int poolSize) - : this(host, port, "root", "root", 1024, "UTC+08:00", poolSize, true, 60) - { - } - - [Obsolete(" This method is deprecated, please use new SessionPool.Builder().")] - public SessionPool(string host, int port, string username, string password) - : this(host, port, username, password, 1024, "UTC+08:00", 8, true, 60) - { - } - - public SessionPool(string host, int port, string username, string password, int fetchSize) - : this(host, port, username, password, fetchSize, "UTC+08:00", 8, true, 60) - { - - } - - public SessionPool(string host, int port) : this(host, port, "root", "root", 1024, "UTC+08:00", 8, true, 60) - { - } - public SessionPool(string host, int port, string username, string password, int fetchSize, string zoneId, int poolSize, bool enableRpcCompression, int timeout) - : this(host, port, username, password, fetchSize, zoneId, poolSize, enableRpcCompression, timeout, IoTDBConstant.TREE_SQL_DIALECT, "") - { - } - protected internal SessionPool(string host, int port, string username, string password, int fetchSize, string zoneId, int poolSize, bool enableRpcCompression, int timeout, string sqlDialect, string database) - { - _host = host; - _port = port; - _username = username; - _password = password; - _zoneId = zoneId; - _fetchSize = fetchSize; - _debugMode = false; - _poolSize = poolSize; - _enableRpcCompression = enableRpcCompression; - _timeout = timeout; - _sqlDialect = sqlDialect; - _database = database; - } - /// - /// Initializes a new instance of the class. - /// - /// The list of node URLs to connect to, multiple ip:rpcPort eg.127.0.0.1:9001 - /// The size of the session pool. - public SessionPool(List nodeUrls, int poolSize) - : this(nodeUrls, "root", "root", 1024, "UTC+08:00", poolSize, true, 60) - { - } - public SessionPool(List nodeUrls, string username, string password) - : this(nodeUrls, username, password, 1024, "UTC+08:00", 8, true, 60) - { - } - public SessionPool(List nodeUrls, string username, string password, int fetchSize) - : this(nodeUrls, username, password, fetchSize, "UTC+08:00", 8, true, 60) - { - } - public SessionPool(List nodeUrls, string username, string password, int fetchSize, string zoneId) - : this(nodeUrls, username, password, fetchSize, zoneId, 8, true, 60) - { - } - public SessionPool(List nodeUrls, string username, string password, int fetchSize, string zoneId, int poolSize, bool enableRpcCompression, int timeout) - : this(nodeUrls, username, password, fetchSize, zoneId, poolSize, enableRpcCompression, timeout, IoTDBConstant.TREE_SQL_DIALECT, "") - { - - } - protected internal SessionPool(List nodeUrls, string username, string password, int fetchSize, string zoneId, int poolSize, bool enableRpcCompression, int timeout, string sqlDialect, string database) - { - if (nodeUrls.Count == 0) - { - throw new ArgumentException("nodeUrls shouldn't be empty."); - } - _nodeUrls = nodeUrls; - _endPoints = _utilFunctions.ParseSeedNodeUrls(nodeUrls); - _username = username; - _password = password; - _zoneId = zoneId; - _fetchSize = fetchSize; - _debugMode = false; - _poolSize = poolSize; - _enableRpcCompression = enableRpcCompression; - _timeout = timeout; - _sqlDialect = sqlDialect; - _database = database; - } - public async Task ExecuteClientOperationAsync(AsyncOperation operation, string errMsg, bool retryOnFailure = true, bool putClientBack=true) - { - Client client = _clients.Take(); - try - { - var resp = await operation(client); - return resp; - } - catch (TException ex) - { - if (retryOnFailure) - { - try - { - client = await Reconnect(client); - return await operation(client); - } - catch (TException retryEx) - { - throw new TException(errMsg, retryEx); - } - } - else - { - throw new TException(errMsg, ex); - } - } - catch (Exception ex) - { - if (retryOnFailure) - { - try - { - client = await Reconnect(client); - return await operation(client); - } - catch (TException retryEx) - { - throw new TException(errMsg, retryEx); - } - } - else - { - throw new TException(errMsg, ex); - } - } - finally - { - if(putClientBack) - { - _clients.Add(client); - } - } - } - /// - /// Gets or sets the amount of time a Session will wait for a send operation to complete successfully. - /// - /// The send time-out value, in milliseconds. The default is 10000. - public int TimeOut { get; set; } = 10000; - - ILoggerFactory factory; - private bool disposedValue; - - public void OpenDebugMode(Action configure) - { - _debugMode = true; - factory = LoggerFactory.Create(configure); - _logger = factory.CreateLogger(nameof(Apache.IoTDB)); - } - - public void CloseDebugMode() - { - _debugMode = false; - } - - public async Task Open(bool enableRpcCompression, CancellationToken cancellationToken = default) - { - _enableRpcCompression = enableRpcCompression; - await Open(cancellationToken); - } - - public async Task Open(CancellationToken cancellationToken = default) - { - _clients = new ConcurrentClientQueue(); - _clients.Timeout = _timeout * 5; - - if (_nodeUrls.Count == 0) - { - for (var index = 0; index < _poolSize; index++) - { - try - { - _clients.Add(await CreateAndOpen(_host, _port, _enableRpcCompression, _timeout, _sqlDialect, _database, cancellationToken)); - } - catch (Exception e) - { - if (_debugMode) - { - _logger.LogWarning(e, "Currently connecting to {0}:{1} failed", _host, _port); - } - } - } - } - else - { - int startIndex = 0; - for (var index = 0; index < _poolSize; index++) - { - bool isConnected = false; - for (int i = 0; i < _endPoints.Count; i++) - { - var endPointIndex = (startIndex + i) % _endPoints.Count; - var endPoint = _endPoints[endPointIndex]; - try - { - var client = await CreateAndOpen(endPoint.Ip, endPoint.Port, _enableRpcCompression, _timeout, _sqlDialect, _database, cancellationToken); - _clients.Add(client); - isConnected = true; - startIndex = (endPointIndex + 1) % _endPoints.Count; - break; - } - catch (Exception e) - { - if (_debugMode) - { - _logger.LogWarning(e, "Currently connecting to {0}:{1} failed", endPoint.Ip, endPoint.Port); - } - } - } - if (!isConnected) // current client could not connect to any endpoint - { - throw new TException("Error occurs when opening session pool. Could not connect to any server", null); - } - } - } - - if (_clients.ClientQueue.Count != _poolSize) - { - throw new TException(string.Format("Error occurs when opening session pool. Client pool size is not equal to the expected size. Client pool size: {0}, expected size: {1}, Please check the server status", _clients.ClientQueue.Count, _poolSize), null); - } - _isClose = false; - } - - - public async Task Reconnect(Client originalClient = null, CancellationToken cancellationToken = default) - { - originalClient?.Transport.Close(); - - if (_nodeUrls.Count == 0) - { - for (int attempt = 1; attempt <= RetryNum; attempt++) - { - try - { - var client = await CreateAndOpen(_host, _port, _enableRpcCompression, _timeout, _sqlDialect, _database, cancellationToken); - return client; - } - catch (Exception e) - { - if (_debugMode) - { - _logger.LogWarning(e, "Attempt reconnecting to {0}:{1} failed", _host, _port); - } - } - } - } - else - { - int startIndex = _endPoints.FindIndex(x => x.Ip == originalClient.EndPoint.Ip && x.Port == originalClient.EndPoint.Port); - if (startIndex == -1) + public partial class SessionPool : IDisposable + { + private static readonly TSProtocolVersion ProtocolVersion = TSProtocolVersion.IOTDB_SERVICE_PROTOCOL_V3; + + private readonly string _username; + private readonly string _password; + private bool _enableRpcCompression; + private string _zoneId; + private readonly List _nodeUrls = new(); + private readonly List _endPoints = new(); + private readonly string _host; + private readonly int _port; + private readonly int _fetchSize; + /// + /// _timeout is the amount of time a Session will wait for a send operation to complete successfully. + /// + private readonly int _timeout; + private readonly int _poolSize = 4; + private readonly string _sqlDialect = IoTDBConstant.TREE_SQL_DIALECT; + private string _database; + private readonly Utils _utilFunctions = new(); + private const int RetryNum = 3; + private bool _debugMode; + private bool _isClose = true; + private ConcurrentClientQueue _clients; + private ILogger _logger; + public delegate Task AsyncOperation(Client client); + + + [Obsolete("This method is deprecated, please use new SessionPool.Builder().")] + public SessionPool(string host, int port, int poolSize) + : this(host, port, "root", "root", 1024, "UTC+08:00", poolSize, true, 60) { - throw new ArgumentException($"The original client is not in the list of endpoints. Original client: {originalClient.EndPoint.Ip}:{originalClient.EndPoint.Port}"); } - for (int attempt = 1; attempt <= RetryNum; attempt++) + [Obsolete(" This method is deprecated, please use new SessionPool.Builder().")] + public SessionPool(string host, int port, string username, string password) + : this(host, port, username, password, 1024, "UTC+08:00", 8, true, 60) { - for (int i = 0; i < _endPoints.Count; i++) - { - int j = (startIndex + i) % _endPoints.Count; - try - { - var client = await CreateAndOpen(_endPoints[j].Ip, _endPoints[j].Port, _enableRpcCompression, _timeout, _sqlDialect, _database, cancellationToken); - return client; - } - catch (Exception e) - { - if (_debugMode) - { - _logger.LogWarning(e, "Attempt connecting to {0}:{1} failed", _endPoints[j].Ip, _endPoints[j].Port); - } - } - } } - } - - throw new TException("Error occurs when reconnecting session pool. Could not connect to any server", null); - } + public SessionPool(string host, int port, string username, string password, int fetchSize) + : this(host, port, username, password, fetchSize, "UTC+08:00", 8, true, 60) + { - public bool IsOpen() => !_isClose; - - public async Task Close() - { - if (_isClose) - { - return; - } + } - foreach (var client in _clients.ClientQueue.AsEnumerable()) - { - var closeSessionRequest = new TSCloseSessionReq(client.SessionId); - try + public SessionPool(string host, int port) : this(host, port, "root", "root", 1024, "UTC+08:00", 8, true, 60) { - await client.ServiceClient.closeSessionAsync(closeSessionRequest); } - catch (TException e) + public SessionPool(string host, int port, string username, string password, int fetchSize, string zoneId, int poolSize, bool enableRpcCompression, int timeout) + : this(host, port, username, password, fetchSize, zoneId, poolSize, enableRpcCompression, timeout, IoTDBConstant.TREE_SQL_DIALECT, "") { - throw new TException("Error occurs when closing session at server. Maybe server is down", e); } - finally + protected internal SessionPool(string host, int port, string username, string password, int fetchSize, string zoneId, int poolSize, bool enableRpcCompression, int timeout, string sqlDialect, string database) { - _isClose = true; - - client.Transport?.Close(); + _host = host; + _port = port; + _username = username; + _password = password; + _zoneId = zoneId; + _fetchSize = fetchSize; + _debugMode = false; + _poolSize = poolSize; + _enableRpcCompression = enableRpcCompression; + _timeout = timeout; + _sqlDialect = sqlDialect; + _database = database; } - } - } - - public async Task SetTimeZone(string zoneId) - { - _zoneId = zoneId; - - foreach (var client in _clients.ClientQueue.AsEnumerable()) - { - var req = new TSSetTimeZoneReq(client.SessionId, zoneId); - try + /// + /// Initializes a new instance of the class. + /// + /// The list of node URLs to connect to, multiple ip:rpcPort eg.127.0.0.1:9001 + /// The size of the session pool. + public SessionPool(List nodeUrls, int poolSize) + : this(nodeUrls, "root", "root", 1024, "UTC+08:00", poolSize, true, 60) { - var resp = await client.ServiceClient.setTimeZoneAsync(req); - if (_debugMode) - { - _logger.LogInformation("setting time zone_id as {0}, server message:{1}", zoneId, resp.Message); - } } - catch (TException e) + public SessionPool(List nodeUrls, string username, string password) + : this(nodeUrls, username, password, 1024, "UTC+08:00", 8, true, 60) { - throw new TException("could not set time zone", e); } - } - } - - public async Task GetTimeZone() - { - if (_zoneId != "") - { - return _zoneId; - } - - var client = _clients.Take(); - - try - { - var response = await client.ServiceClient.getTimeZoneAsync(client.SessionId); - - return response?.TimeZone; - } - catch (TException e) - { - throw new TException("could not get time zone", e); - } - finally - { - _clients.Add(client); - } - } - - private async Task CreateAndOpen(string host, int port, bool enableRpcCompression, int timeout, string sqlDialect, string database, CancellationToken cancellationToken = default) - { - var tcpClient = new TcpClient(host, port); - tcpClient.SendTimeout = timeout; - tcpClient.ReceiveTimeout = timeout; - var transport = new TFramedTransport(new TSocketTransport(tcpClient, null)); - - if (!transport.IsOpen) - { - await transport.OpenAsync(cancellationToken); - } - - var client = enableRpcCompression ? - new IClientRPCService.Client(new TCompactProtocol(transport)) : - new IClientRPCService.Client(new TBinaryProtocol(transport)); - - var openReq = new TSOpenSessionReq(ProtocolVersion, _zoneId, _username) - { - Password = _password, - }; - if (openReq.Configuration == null) - { - openReq.Configuration = new Dictionary(); - } - openReq.Configuration.Add("sql_dialect", sqlDialect); - if (!String.IsNullOrEmpty(database)) - { - openReq.Configuration.Add("db", database); - } - - try - { - var openResp = await client.openSessionAsync(openReq, cancellationToken); - - if (openResp.ServerProtocolVersion != ProtocolVersion) + public SessionPool(List nodeUrls, string username, string password, int fetchSize) + : this(nodeUrls, username, password, fetchSize, "UTC+08:00", 8, true, 60) { - throw new TException($"Protocol Differ, Client version is {ProtocolVersion} but Server version is {openResp.ServerProtocolVersion}", null); } - - if (openResp.ServerProtocolVersion == 0) + public SessionPool(List nodeUrls, string username, string password, int fetchSize, string zoneId) + : this(nodeUrls, username, password, fetchSize, zoneId, 8, true, 60) { - throw new TException("Protocol not supported", null); } + public SessionPool(List nodeUrls, string username, string password, int fetchSize, string zoneId, int poolSize, bool enableRpcCompression, int timeout) + : this(nodeUrls, username, password, fetchSize, zoneId, poolSize, enableRpcCompression, timeout, IoTDBConstant.TREE_SQL_DIALECT, "") + { - var sessionId = openResp.SessionId; - var statementId = await client.requestStatementIdAsync(sessionId, cancellationToken); - - var endpoint = new TEndPoint(host, port); - - var returnClient = new Client( - client, - sessionId, - statementId, - transport, - endpoint); - - return returnClient; - } - catch (Exception) - { - transport.Close(); - - throw; - } - } - - public async Task CreateDatabase(string dbName) - { - return await ExecuteClientOperationAsync( - async client => - { - var status = await client.ServiceClient.setStorageGroupAsync(client.SessionId, dbName); - - if (_debugMode) + } + protected internal SessionPool(List nodeUrls, string username, string password, int fetchSize, string zoneId, int poolSize, bool enableRpcCompression, int timeout, string sqlDialect, string database) + { + if (nodeUrls.Count == 0) + { + throw new ArgumentException("nodeUrls shouldn't be empty."); + } + _nodeUrls = nodeUrls; + _endPoints = _utilFunctions.ParseSeedNodeUrls(nodeUrls); + _username = username; + _password = password; + _zoneId = zoneId; + _fetchSize = fetchSize; + _debugMode = false; + _poolSize = poolSize; + _enableRpcCompression = enableRpcCompression; + _timeout = timeout; + _sqlDialect = sqlDialect; + _database = database; + } + public async Task ExecuteClientOperationAsync(AsyncOperation operation, string errMsg, bool retryOnFailure = true, bool putClientBack = true) + { + Client client = _clients.Take(); + try { - _logger.LogInformation("create database {0} successfully, server message is {1}", dbName, status.Message); + var resp = await operation(client); + return resp; } - - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when creating database" - ); - } - - [Obsolete("This method is deprecated, please use createDatabase instead.")] - public async Task SetStorageGroup(string groupName) - { - return await ExecuteClientOperationAsync( - async client => - { - var status = await client.ServiceClient.setStorageGroupAsync(client.SessionId, groupName); - if (_debugMode) + catch (TException ex) { - _logger.LogInformation("set storage group {0} successfully, server message is {1}", groupName, status.Message); + if (retryOnFailure) + { + try + { + client = await Reconnect(client); + return await operation(client); + } + catch (TException retryEx) + { + throw new TException(errMsg, retryEx); + } + } + else + { + throw new TException(errMsg, ex); + } } - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when setting storage group" - ); - } - public async Task CreateTimeSeries( - string tsPath, - TSDataType dataType, - TSEncoding encoding, - Compressor compressor) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = new TSCreateTimeseriesReq( - client.SessionId, - tsPath, - (int)dataType, - (int)encoding, - (int)compressor); - - var status = await client.ServiceClient.createTimeseriesAsync(req); - - if (_debugMode) + catch (Exception ex) { - _logger.LogInformation("creating time series {0} successfully, server message is {1}", tsPath, status.Message); + if (retryOnFailure) + { + try + { + client = await Reconnect(client); + return await operation(client); + } + catch (TException retryEx) + { + throw new TException(errMsg, retryEx); + } + } + else + { + throw new TException(errMsg, ex); + } } - - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when creating time series" - ); - } - public async Task CreateAlignedTimeseriesAsync( - string prefixPath, - List measurements, - List dataTypeLst, - List encodingLst, - List compressorLst) - { - return await ExecuteClientOperationAsync( - async client => - { - var dataTypes = dataTypeLst.ConvertAll(x => (int)x); - var encodings = encodingLst.ConvertAll(x => (int)x); - var compressors = compressorLst.ConvertAll(x => (int)x); - - var req = new TSCreateAlignedTimeseriesReq( - client.SessionId, - prefixPath, - measurements, - dataTypes, - encodings, - compressors); - - var status = await client.ServiceClient.createAlignedTimeseriesAsync(req); - - if (_debugMode) + finally { - _logger.LogInformation("creating aligned time series {0} successfully, server message is {1}", prefixPath, status.Message); + if (putClientBack) + { + _clients.Add(client); + } } + } + /// + /// Gets or sets the amount of time a Session will wait for a send operation to complete successfully. + /// + /// The send time-out value, in milliseconds. The default is 10000. + public int TimeOut { get; set; } = 10000; - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when creating aligned time series" - ); - } - public async Task DeleteDatabaseAsync(string dbName) - { - return await ExecuteClientOperationAsync( - async client => - { - var status = await client.ServiceClient.deleteStorageGroupsAsync(client.SessionId, new List { dbName }); + ILoggerFactory factory; + private bool disposedValue; - if (_debugMode) - { - _logger.LogInformation("delete database {0} successfully, server message is {1}", dbName, status.Message); - } + public void OpenDebugMode(Action configure) + { + _debugMode = true; + factory = LoggerFactory.Create(configure); + _logger = factory.CreateLogger(nameof(Apache.IoTDB)); + } - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when deleting database" - ); - } - [Obsolete("This method is deprecated, please use DeleteDatabaseAsync instead.")] - public async Task DeleteStorageGroupAsync(string groupName) - { - return await ExecuteClientOperationAsync( - async client => - { - var status = await client.ServiceClient.deleteStorageGroupsAsync(client.SessionId, new List { groupName }); + public void CloseDebugMode() + { + _debugMode = false; + } - if (_debugMode) - { - _logger.LogInformation("delete storage group {0} successfully, server message is {1}", groupName, status.Message); - } + public async Task Open(bool enableRpcCompression, CancellationToken cancellationToken = default) + { + _enableRpcCompression = enableRpcCompression; + await Open(cancellationToken); + } - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when deleting storage group" - ); - } - public async Task DeleteDatabasesAsync(List dbNames) - { - return await ExecuteClientOperationAsync( - async client => - { - var status = await client.ServiceClient.deleteStorageGroupsAsync(client.SessionId, dbNames); + public async Task Open(CancellationToken cancellationToken = default) + { + _clients = new ConcurrentClientQueue(); + _clients.Timeout = _timeout * 5; - if (_debugMode) + if (_nodeUrls.Count == 0) { - _logger.LogInformation("delete database(s) {0} successfully, server message is {1}", dbNames, status.Message); + for (var index = 0; index < _poolSize; index++) + { + try + { + _clients.Add(await CreateAndOpen(_host, _port, _enableRpcCompression, _timeout, _sqlDialect, _database, cancellationToken)); + } + catch (Exception e) + { + if (_debugMode) + { + _logger.LogWarning(e, "Currently connecting to {0}:{1} failed", _host, _port); + } + } + } } - - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when deleting database(s)" - ); - } - [Obsolete("This method is deprecated, please use DeleteDatabasesAsync instead.")] - public async Task DeleteStorageGroupsAsync(List groupNames) - { - return await ExecuteClientOperationAsync( - async client => - { - var status = await client.ServiceClient.deleteStorageGroupsAsync(client.SessionId, groupNames); - - if (_debugMode) + else { - _logger.LogInformation("delete storage group(s) {0} successfully, server message is {1}", groupNames, status.Message); + int startIndex = 0; + for (var index = 0; index < _poolSize; index++) + { + bool isConnected = false; + for (int i = 0; i < _endPoints.Count; i++) + { + var endPointIndex = (startIndex + i) % _endPoints.Count; + var endPoint = _endPoints[endPointIndex]; + try + { + var client = await CreateAndOpen(endPoint.Ip, endPoint.Port, _enableRpcCompression, _timeout, _sqlDialect, _database, cancellationToken); + _clients.Add(client); + isConnected = true; + startIndex = (endPointIndex + 1) % _endPoints.Count; + break; + } + catch (Exception e) + { + if (_debugMode) + { + _logger.LogWarning(e, "Currently connecting to {0}:{1} failed", endPoint.Ip, endPoint.Port); + } + } + } + if (!isConnected) // current client could not connect to any endpoint + { + throw new TException("Error occurs when opening session pool. Could not connect to any server", null); + } + } } - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when deleting storage group(s)" - ); - } - public async Task CreateMultiTimeSeriesAsync( - List tsPathLst, - List dataTypeLst, - List encodingLst, - List compressorLst) - { - return await ExecuteClientOperationAsync( - async client => - { - var dataTypes = dataTypeLst.ConvertAll(x => (int)x); - var encodings = encodingLst.ConvertAll(x => (int)x); - var compressors = compressorLst.ConvertAll(x => (int)x); - - var req = new TSCreateMultiTimeseriesReq(client.SessionId, tsPathLst, dataTypes, encodings, compressors); - - var status = await client.ServiceClient.createMultiTimeseriesAsync(req); - - if (_debugMode) + if (_clients.ClientQueue.Count != _poolSize) { - _logger.LogInformation("creating multiple time series {0}, server message is {1}", tsPathLst, status.Message); + throw new TException(string.Format("Error occurs when opening session pool. Client pool size is not equal to the expected size. Client pool size: {0}, expected size: {1}, Please check the server status", _clients.ClientQueue.Count, _poolSize), null); } + _isClose = false; + } - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when creating multiple time series" - ); - } - public async Task DeleteTimeSeriesAsync(List pathList) - { - return await ExecuteClientOperationAsync( - async client => - { - var status = await client.ServiceClient.deleteTimeseriesAsync(client.SessionId, pathList); - if (_debugMode) + public async Task Reconnect(Client originalClient = null, CancellationToken cancellationToken = default) + { + originalClient?.Transport.Close(); + + if (_nodeUrls.Count == 0) { - _logger.LogInformation("deleting multiple time series {0}, server message is {1}", pathList, status.Message); + for (int attempt = 1; attempt <= RetryNum; attempt++) + { + try + { + var client = await CreateAndOpen(_host, _port, _enableRpcCompression, _timeout, _sqlDialect, _database, cancellationToken); + return client; + } + catch (Exception e) + { + if (_debugMode) + { + _logger.LogWarning(e, "Attempt reconnecting to {0}:{1} failed", _host, _port); + } + } + } } + else + { + int startIndex = _endPoints.FindIndex(x => x.Ip == originalClient.EndPoint.Ip && x.Port == originalClient.EndPoint.Port); + if (startIndex == -1) + { + throw new ArgumentException($"The original client is not in the list of endpoints. Original client: {originalClient.EndPoint.Ip}:{originalClient.EndPoint.Port}"); + } - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when deleting multiple time series" - ); - } - - public async Task DeleteTimeSeriesAsync(string tsPath) - { - return await DeleteTimeSeriesAsync(new List { tsPath }); - } + for (int attempt = 1; attempt <= RetryNum; attempt++) + { + for (int i = 0; i < _endPoints.Count; i++) + { + int j = (startIndex + i) % _endPoints.Count; + try + { + var client = await CreateAndOpen(_endPoints[j].Ip, _endPoints[j].Port, _enableRpcCompression, _timeout, _sqlDialect, _database, cancellationToken); + return client; + } + catch (Exception e) + { + if (_debugMode) + { + _logger.LogWarning(e, "Attempt connecting to {0}:{1} failed", _endPoints[j].Ip, _endPoints[j].Port); + } + } + } + } + } - public async Task CheckTimeSeriesExistsAsync(string tsPath) - { - try - { - var sql = "SHOW TIMESERIES " + tsPath; - var sessionDataset = await ExecuteQueryStatementAsync(sql); - bool timeSeriesExists = sessionDataset.HasNext(); - await sessionDataset.Close(); // be sure to close the sessionDataset to put the client back to the pool - return timeSeriesExists; - } - catch (TException e) - { - throw new TException("could not check if certain time series exists", e); - } - } - public async Task DeleteDataAsync(List tsPathLst, long startTime, long endTime) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = new TSDeleteDataReq(client.SessionId, tsPathLst, startTime, endTime); + throw new TException("Error occurs when reconnecting session pool. Could not connect to any server", null); + } - var status = await client.ServiceClient.deleteDataAsync(req); + public bool IsOpen() => !_isClose; - if (_debugMode) + public async Task Close() + { + if (_isClose) { - _logger.LogInformation( - "delete data from {0}, server message is {1}", - tsPathLst, - status.Message); + return; } - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when deleting data" - ); - } - public async Task InsertRecordAsync(string deviceId, RowRecord record) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = new TSInsertRecordReq(client.SessionId, deviceId, record.Measurements, record.ToBytes(), record.Timestamps); - - var status = await client.ServiceClient.insertRecordAsync(req); - - if (_debugMode) + foreach (var client in _clients.ClientQueue.AsEnumerable()) { - _logger.LogInformation("insert one record to device {0}, server message: {1}", deviceId, status.Message); - } + var closeSessionRequest = new TSCloseSessionReq(client.SessionId); + try + { + await client.ServiceClient.closeSessionAsync(closeSessionRequest); + } + catch (TException e) + { + throw new TException("Error occurs when closing session at server. Maybe server is down", e); + } + finally + { + _isClose = true; - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when inserting record" - ); - } - public async Task InsertAlignedRecordAsync(string deviceId, RowRecord record) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = new TSInsertRecordReq(client.SessionId, deviceId, record.Measurements, record.ToBytes(), record.Timestamps); - req.IsAligned = true; - // ASSERT that the insert plan is aligned - System.Diagnostics.Debug.Assert(req.IsAligned == true); + client.Transport?.Close(); + } + } + } - var status = await client.ServiceClient.insertRecordAsync(req); + public async Task SetTimeZone(string zoneId) + { + _zoneId = zoneId; - if (_debugMode) + foreach (var client in _clients.ClientQueue.AsEnumerable()) { - _logger.LogInformation("insert one record to device {0}, server message: {1}", deviceId, status.Message); + var req = new TSSetTimeZoneReq(client.SessionId, zoneId); + try + { + var resp = await client.ServiceClient.setTimeZoneAsync(req); + if (_debugMode) + { + _logger.LogInformation("setting time zone_id as {0}, server message:{1}", zoneId, resp.Message); + } + } + catch (TException e) + { + throw new TException("could not set time zone", e); + } } + } - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when inserting record" - ); - } - - public TSInsertStringRecordReq GenInsertStrRecordReq(string deviceId, List measurements, - List values, long timestamp, long sessionId, bool isAligned = false) - { - if (values.Count() != measurements.Count()) - { - throw new ArgumentException("length of data types does not equal to length of values!"); - } - - return new TSInsertStringRecordReq(sessionId, deviceId, measurements, values, timestamp) - { - IsAligned = isAligned - }; - } - public TSInsertStringRecordsReq GenInsertStringRecordsReq(List deviceIds, List> measurementsList, - List> valuesList, List timestamps, long sessionId, bool isAligned = false) - { - if (valuesList.Count() != measurementsList.Count()) - { - throw new ArgumentException("length of data types does not equal to length of values!"); - } - - return new TSInsertStringRecordsReq(sessionId, deviceIds, measurementsList, valuesList, timestamps) - { - IsAligned = isAligned - }; - } - - public TSInsertRecordsReq GenInsertRecordsReq(List deviceId, List rowRecords, - long sessionId) - { - var measurementLst = rowRecords.Select(x => x.Measurements).ToList(); - var timestampLst = rowRecords.Select(x => x.Timestamps).ToList(); - var valuesLstInBytes = rowRecords.Select(row => row.ToBytes()).ToList(); - - return new TSInsertRecordsReq(sessionId, deviceId, measurementLst, valuesLstInBytes, timestampLst); - } - public async Task InsertStringRecordAsync(string deviceId, List measurements, List values, - long timestamp) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = GenInsertStrRecordReq(deviceId, measurements, values, timestamp, client.SessionId); - - var status = await client.ServiceClient.insertStringRecordAsync(req); - - if (_debugMode) + public async Task GetTimeZone() + { + if (_zoneId != "") { - _logger.LogInformation("insert one string record to device {0}, server message: {1}", deviceId, status.Message); + return _zoneId; } - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when inserting a string record" - ); - } - public async Task InsertAlignedStringRecordAsync(string deviceId, List measurements, List values, - long timestamp) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = GenInsertStrRecordReq(deviceId, measurements, values, timestamp, client.SessionId, true); + var client = _clients.Take(); - var status = await client.ServiceClient.insertStringRecordAsync(req); + try + { + var response = await client.ServiceClient.getTimeZoneAsync(client.SessionId); - if (_debugMode) + return response?.TimeZone; + } + catch (TException e) { - _logger.LogInformation("insert one record to device {0}, server message: {1}", deviceId, status.Message); + throw new TException("could not get time zone", e); } - - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when inserting a string record" - ); - } - public async Task InsertStringRecordsAsync(List deviceIds, List> measurements, List> values, - List timestamps) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = GenInsertStringRecordsReq(deviceIds, measurements, values, timestamps, client.SessionId); - - var status = await client.ServiceClient.insertStringRecordsAsync(req); - - if (_debugMode) + finally { - _logger.LogInformation("insert string records to devices {0}, server message: {1}", deviceIds, status.Message); + _clients.Add(client); } + } - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when inserting string records" - ); - } - public async Task InsertAlignedStringRecordsAsync(List deviceIds, List> measurements, List> values, - List timestamps) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = GenInsertStringRecordsReq(deviceIds, measurements, values, timestamps, client.SessionId, true); - - var status = await client.ServiceClient.insertStringRecordsAsync(req); + private async Task CreateAndOpen(string host, int port, bool enableRpcCompression, int timeout, string sqlDialect, string database, CancellationToken cancellationToken = default) + { + var tcpClient = new TcpClient(host, port); + tcpClient.SendTimeout = timeout; + tcpClient.ReceiveTimeout = timeout; + var transport = new TFramedTransport(new TSocketTransport(tcpClient, null)); - if (_debugMode) + if (!transport.IsOpen) { - _logger.LogInformation("insert string records to devices {0}, server message: {1}", deviceIds, status.Message); + await transport.OpenAsync(cancellationToken); } - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when inserting string records" - ); - } - public async Task InsertRecordsAsync(List deviceId, List rowRecords) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = GenInsertRecordsReq(deviceId, rowRecords, client.SessionId); - - var status = await client.ServiceClient.insertRecordsAsync(req); + var client = enableRpcCompression ? + new IClientRPCService.Client(new TCompactProtocol(transport)) : + new IClientRPCService.Client(new TBinaryProtocol(transport)); - if (_debugMode) + var openReq = new TSOpenSessionReq(ProtocolVersion, _zoneId, _username) + { + Password = _password, + }; + if (openReq.Configuration == null) { - _logger.LogInformation("insert multiple records to devices {0}, server message: {1}", deviceId, status.Message); + openReq.Configuration = new Dictionary(); } - - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when inserting records" - ); - } - public async Task InsertAlignedRecordsAsync(List deviceId, List rowRecords) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = GenInsertRecordsReq(deviceId, rowRecords, client.SessionId); - req.IsAligned = true; - // ASSERT that the insert plan is aligned - System.Diagnostics.Debug.Assert(req.IsAligned == true); - - var status = await client.ServiceClient.insertRecordsAsync(req); - - if (_debugMode) + openReq.Configuration.Add("sql_dialect", sqlDialect); + if (!String.IsNullOrEmpty(database)) { - _logger.LogInformation("insert multiple records to devices {0}, server message: {1}", deviceId, status.Message); + openReq.Configuration.Add("db", database); } - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when inserting records" - ); - } - public TSInsertTabletReq GenInsertTabletReq(Tablet tablet, long sessionId) - { - return new TSInsertTabletReq( - sessionId, - tablet.InsertTargetName, - tablet.Measurements, - tablet.GetBinaryValues(), - tablet.GetBinaryTimestamps(), - tablet.GetDataTypes(), - tablet.RowNumber); - } - public async Task InsertTabletAsync(Tablet tablet) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = GenInsertTabletReq(tablet, client.SessionId); + try + { + var openResp = await client.openSessionAsync(openReq, cancellationToken); + + if (openResp.ServerProtocolVersion != ProtocolVersion) + { + throw new TException($"Protocol Differ, Client version is {ProtocolVersion} but Server version is {openResp.ServerProtocolVersion}", null); + } - var status = await client.ServiceClient.insertTabletAsync(req); + if (openResp.ServerProtocolVersion == 0) + { + throw new TException("Protocol not supported", null); + } - if (_debugMode) - { - _logger.LogInformation("insert one tablet to device {0}, server message: {1}", tablet.InsertTargetName, status.Message); - } + var sessionId = openResp.SessionId; + var statementId = await client.requestStatementIdAsync(sessionId, cancellationToken); - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when inserting tablet" - ); - } - public async Task InsertAlignedTabletAsync(Tablet tablet) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = GenInsertTabletReq(tablet, client.SessionId); - req.IsAligned = true; + var endpoint = new TEndPoint(host, port); - var status = await client.ServiceClient.insertTabletAsync(req); + var returnClient = new Client( + client, + sessionId, + statementId, + transport, + endpoint); - if (_debugMode) + return returnClient; + } + catch (Exception) { - _logger.LogInformation("insert one aligned tablet to device {0}, server message: {1}", tablet.InsertTargetName, status.Message); + transport.Close(); + + throw; } + } - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when inserting aligned tablet" - ); - } + public async Task CreateDatabase(string dbName) + { + return await ExecuteClientOperationAsync( + async client => + { + var status = await client.ServiceClient.setStorageGroupAsync(client.SessionId, dbName); - protected internal async Task InsertRelationalTabletAsync(Tablet tablet) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = GenInsertTabletReq(tablet, client.SessionId); - req.ColumnCategories = tablet.GetColumnColumnCategories(); - req.WriteToTable = true; + if (_debugMode) + { + _logger.LogInformation("create database {0} successfully, server message is {1}", dbName, status.Message); + } - var status = await client.ServiceClient.insertTabletAsync(req); + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when creating database" + ); + } - if (_debugMode) - { - _logger.LogInformation("insert one tablet to table {0}, server message: {1}", tablet.InsertTargetName, status.Message); - } + [Obsolete("This method is deprecated, please use createDatabase instead.")] + public async Task SetStorageGroup(string groupName) + { + return await ExecuteClientOperationAsync( + async client => + { + var status = await client.ServiceClient.setStorageGroupAsync(client.SessionId, groupName); + if (_debugMode) + { + _logger.LogInformation("set storage group {0} successfully, server message is {1}", groupName, status.Message); + } + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when setting storage group" + ); + } + public async Task CreateTimeSeries( + string tsPath, + TSDataType dataType, + TSEncoding encoding, + Compressor compressor) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = new TSCreateTimeseriesReq( + client.SessionId, + tsPath, + (int)dataType, + (int)encoding, + (int)compressor); + + var status = await client.ServiceClient.createTimeseriesAsync(req); + + if (_debugMode) + { + _logger.LogInformation("creating time series {0} successfully, server message is {1}", tsPath, status.Message); + } + + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when creating time series" + ); + } + public async Task CreateAlignedTimeseriesAsync( + string prefixPath, + List measurements, + List dataTypeLst, + List encodingLst, + List compressorLst) + { + return await ExecuteClientOperationAsync( + async client => + { + var dataTypes = dataTypeLst.ConvertAll(x => (int)x); + var encodings = encodingLst.ConvertAll(x => (int)x); + var compressors = compressorLst.ConvertAll(x => (int)x); + + var req = new TSCreateAlignedTimeseriesReq( + client.SessionId, + prefixPath, + measurements, + dataTypes, + encodings, + compressors); + + var status = await client.ServiceClient.createAlignedTimeseriesAsync(req); + + if (_debugMode) + { + _logger.LogInformation("creating aligned time series {0} successfully, server message is {1}", prefixPath, status.Message); + } + + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when creating aligned time series" + ); + } + public async Task DeleteDatabaseAsync(string dbName) + { + return await ExecuteClientOperationAsync( + async client => + { + var status = await client.ServiceClient.deleteStorageGroupsAsync(client.SessionId, new List { dbName }); - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when inserting tablet" - ); - } + if (_debugMode) + { + _logger.LogInformation("delete database {0} successfully, server message is {1}", dbName, status.Message); + } - public TSInsertTabletsReq GenInsertTabletsReq(List tabletLst, long sessionId) - { - var deviceIdLst = new List(); - var measurementsLst = new List>(); - var valuesLst = new List(); - var timestampsLst = new List(); - var typeLst = new List>(); - var sizeLst = new List(); - - foreach (var tablet in tabletLst) - { - var dataTypeValues = tablet.GetDataTypes(); - deviceIdLst.Add(tablet.InsertTargetName); - measurementsLst.Add(tablet.Measurements); - valuesLst.Add(tablet.GetBinaryValues()); - timestampsLst.Add(tablet.GetBinaryTimestamps()); - typeLst.Add(dataTypeValues); - sizeLst.Add(tablet.RowNumber); - } - - return new TSInsertTabletsReq( - sessionId, - deviceIdLst, - measurementsLst, - valuesLst, - timestampsLst, - typeLst, - sizeLst); - } + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when deleting database" + ); + } + [Obsolete("This method is deprecated, please use DeleteDatabaseAsync instead.")] + public async Task DeleteStorageGroupAsync(string groupName) + { + return await ExecuteClientOperationAsync( + async client => + { + var status = await client.ServiceClient.deleteStorageGroupsAsync(client.SessionId, new List { groupName }); - public async Task InsertTabletsAsync(List tabletLst) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = GenInsertTabletsReq(tabletLst, client.SessionId); + if (_debugMode) + { + _logger.LogInformation("delete storage group {0} successfully, server message is {1}", groupName, status.Message); + } - var status = await client.ServiceClient.insertTabletsAsync(req); + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when deleting storage group" + ); + } + public async Task DeleteDatabasesAsync(List dbNames) + { + return await ExecuteClientOperationAsync( + async client => + { + var status = await client.ServiceClient.deleteStorageGroupsAsync(client.SessionId, dbNames); - if (_debugMode) - { - _logger.LogInformation("insert multiple tablets, message: {0}", status.Message); - } + if (_debugMode) + { + _logger.LogInformation("delete database(s) {0} successfully, server message is {1}", dbNames, status.Message); + } - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when inserting tablets" - ); - } - public async Task InsertAlignedTabletsAsync(List tabletLst) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = GenInsertTabletsReq(tabletLst, client.SessionId); - req.IsAligned = true; + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when deleting database(s)" + ); + } + [Obsolete("This method is deprecated, please use DeleteDatabasesAsync instead.")] + public async Task DeleteStorageGroupsAsync(List groupNames) + { + return await ExecuteClientOperationAsync( + async client => + { + var status = await client.ServiceClient.deleteStorageGroupsAsync(client.SessionId, groupNames); - var status = await client.ServiceClient.insertTabletsAsync(req); + if (_debugMode) + { + _logger.LogInformation("delete storage group(s) {0} successfully, server message is {1}", groupNames, status.Message); + } - if (_debugMode) - { - _logger.LogInformation("insert multiple aligned tablets, message: {0}", status.Message); - } + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when deleting storage group(s)" + ); + } + public async Task CreateMultiTimeSeriesAsync( + List tsPathLst, + List dataTypeLst, + List encodingLst, + List compressorLst) + { + return await ExecuteClientOperationAsync( + async client => + { + var dataTypes = dataTypeLst.ConvertAll(x => (int)x); + var encodings = encodingLst.ConvertAll(x => (int)x); + var compressors = compressorLst.ConvertAll(x => (int)x); - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when inserting aligned tablets" - ); - } + var req = new TSCreateMultiTimeseriesReq(client.SessionId, tsPathLst, dataTypes, encodings, compressors); - public async Task InsertRecordsOfOneDeviceAsync(string deviceId, List rowRecords) - { - var sortedRowRecords = rowRecords.OrderBy(x => x.Timestamps).ToList(); - return await InsertRecordsOfOneDeviceSortedAsync(deviceId, sortedRowRecords); - } - public async Task InsertAlignedRecordsOfOneDeviceAsync(string deviceId, List rowRecords) - { - var sortedRowRecords = rowRecords.OrderBy(x => x.Timestamps).ToList(); - return await InsertAlignedRecordsOfOneDeviceSortedAsync(deviceId, sortedRowRecords); - } - public async Task InsertStringRecordsOfOneDeviceAsync(string deviceId, List timestamps, - List> measurementsList, List> valuesList) - { - var joined = timestamps.Zip(measurementsList, (t, m) => new { t, m }) - .Zip(valuesList, (tm, v) => new { tm.t, tm.m, v }) - .OrderBy(x => x.t); + var status = await client.ServiceClient.createMultiTimeseriesAsync(req); - var sortedTimestamps = joined.Select(x => x.t).ToList(); - var sortedMeasurementsList = joined.Select(x => x.m).ToList(); - var sortedValuesList = joined.Select(x => x.v).ToList(); + if (_debugMode) + { + _logger.LogInformation("creating multiple time series {0}, server message is {1}", tsPathLst, status.Message); + } - return await InsertStringRecordsOfOneDeviceSortedAsync(deviceId, sortedTimestamps, sortedMeasurementsList, sortedValuesList, false); - } - public async Task InsertAlignedStringRecordsOfOneDeviceAsync(string deviceId, List timestamps, - List> measurementsList, List> valuesList) - { - var joined = timestamps.Zip(measurementsList, (t, m) => new { t, m }) - .Zip(valuesList, (tm, v) => new { tm.t, tm.m, v }) - .OrderBy(x => x.t); + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when creating multiple time series" + ); + } + public async Task DeleteTimeSeriesAsync(List pathList) + { + return await ExecuteClientOperationAsync( + async client => + { + var status = await client.ServiceClient.deleteTimeseriesAsync(client.SessionId, pathList); - var sortedTimestamps = joined.Select(x => x.t).ToList(); - var sortedMeasurementsList = joined.Select(x => x.m).ToList(); - var sortedValuesList = joined.Select(x => x.v).ToList(); + if (_debugMode) + { + _logger.LogInformation("deleting multiple time series {0}, server message is {1}", pathList, status.Message); + } - return await InsertStringRecordsOfOneDeviceSortedAsync(deviceId, sortedTimestamps, sortedMeasurementsList, sortedValuesList, true); - } - public async Task InsertStringRecordsOfOneDeviceSortedAsync(string deviceId, List timestamps, - List> measurementsList, List> valuesList, bool isAligned) - { - return await ExecuteClientOperationAsync( - async client => - { - if (!_utilFunctions.IsSorted(timestamps)) + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when deleting multiple time series" + ); + } + + public async Task DeleteTimeSeriesAsync(string tsPath) + { + return await DeleteTimeSeriesAsync(new List { tsPath }); + } + + public async Task CheckTimeSeriesExistsAsync(string tsPath) + { + try + { + var sql = "SHOW TIMESERIES " + tsPath; + var sessionDataset = await ExecuteQueryStatementAsync(sql); + bool timeSeriesExists = sessionDataset.HasNext(); + await sessionDataset.Close(); // be sure to close the sessionDataset to put the client back to the pool + return timeSeriesExists; + } + catch (TException e) { - throw new ArgumentException("insert string records of one device error: timestamp not sorted"); + throw new TException("could not check if certain time series exists", e); } + } + public async Task DeleteDataAsync(List tsPathLst, long startTime, long endTime) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = new TSDeleteDataReq(client.SessionId, tsPathLst, startTime, endTime); + + var status = await client.ServiceClient.deleteDataAsync(req); + + if (_debugMode) + { + _logger.LogInformation( + "delete data from {0}, server message is {1}", + tsPathLst, + status.Message); + } + + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when deleting data" + ); + } + public async Task InsertRecordAsync(string deviceId, RowRecord record) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = new TSInsertRecordReq(client.SessionId, deviceId, record.Measurements, record.ToBytes(), record.Timestamps); - var req = GenInsertStringRecordsOfOneDeviceReq(deviceId, timestamps, measurementsList, valuesList, client.SessionId, isAligned); + var status = await client.ServiceClient.insertRecordAsync(req); - var status = await client.ServiceClient.insertStringRecordsOfOneDeviceAsync(req); + if (_debugMode) + { + _logger.LogInformation("insert one record to device {0}, server message: {1}", deviceId, status.Message); + } + + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when inserting record" + ); + } + public async Task InsertAlignedRecordAsync(string deviceId, RowRecord record) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = new TSInsertRecordReq(client.SessionId, deviceId, record.Measurements, record.ToBytes(), record.Timestamps); + req.IsAligned = true; + // ASSERT that the insert plan is aligned + System.Diagnostics.Debug.Assert(req.IsAligned == true); + + var status = await client.ServiceClient.insertRecordAsync(req); + + if (_debugMode) + { + _logger.LogInformation("insert one record to device {0}, server message: {1}", deviceId, status.Message); + } + + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when inserting record" + ); + } - if (_debugMode) + public TSInsertStringRecordReq GenInsertStrRecordReq(string deviceId, List measurements, + List values, long timestamp, long sessionId, bool isAligned = false) + { + if (values.Count() != measurements.Count()) { - _logger.LogInformation("insert string records of one device, message: {0}", status.Message); + throw new ArgumentException("length of data types does not equal to length of values!"); } - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when inserting string records of one device" - ); - } - private TSInsertStringRecordsOfOneDeviceReq GenInsertStringRecordsOfOneDeviceReq(string deviceId, - List timestamps, List> measurementsList, List> valuesList, - long sessionId, bool isAligned = false) - { - return new TSInsertStringRecordsOfOneDeviceReq( - sessionId, - deviceId, - measurementsList, - valuesList, - timestamps) - { - IsAligned = isAligned - }; - } - private TSInsertRecordsOfOneDeviceReq GenInsertRecordsOfOneDeviceRequest( - string deviceId, - List records, - long sessionId) - { - var values = records.Select(row => row.ToBytes()); - var measurementsLst = records.Select(x => x.Measurements).ToList(); - var timestampLst = records.Select(x => x.Timestamps).ToList(); - - return new TSInsertRecordsOfOneDeviceReq( - sessionId, - deviceId, - measurementsLst, - values.ToList(), - timestampLst); - } - public async Task InsertRecordsOfOneDeviceSortedAsync(string deviceId, List rowRecords) - { - return await ExecuteClientOperationAsync( - async client => - { - var timestampLst = rowRecords.Select(x => x.Timestamps).ToList(); - - if (!_utilFunctions.IsSorted(timestampLst)) + return new TSInsertStringRecordReq(sessionId, deviceId, measurements, values, timestamp) + { + IsAligned = isAligned + }; + } + public TSInsertStringRecordsReq GenInsertStringRecordsReq(List deviceIds, List> measurementsList, + List> valuesList, List timestamps, long sessionId, bool isAligned = false) + { + if (valuesList.Count() != measurementsList.Count()) { - throw new ArgumentException("insert records of one device error: timestamp not sorted"); + throw new ArgumentException("length of data types does not equal to length of values!"); } - var req = GenInsertRecordsOfOneDeviceRequest(deviceId, rowRecords, client.SessionId); - - var status = await client.ServiceClient.insertRecordsOfOneDeviceAsync(req); - - if (_debugMode) + return new TSInsertStringRecordsReq(sessionId, deviceIds, measurementsList, valuesList, timestamps) { - _logger.LogInformation("insert records of one device, message: {0}", status.Message); - } + IsAligned = isAligned + }; + } - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when inserting records of one device" - ); - } - public async Task InsertAlignedRecordsOfOneDeviceSortedAsync(string deviceId, List rowRecords) - { - return await ExecuteClientOperationAsync( - async client => - { + public TSInsertRecordsReq GenInsertRecordsReq(List deviceId, List rowRecords, + long sessionId) + { + var measurementLst = rowRecords.Select(x => x.Measurements).ToList(); var timestampLst = rowRecords.Select(x => x.Timestamps).ToList(); + var valuesLstInBytes = rowRecords.Select(row => row.ToBytes()).ToList(); - if (!_utilFunctions.IsSorted(timestampLst)) - { - throw new ArgumentException("insert records of one device error: timestamp not sorted"); - } + return new TSInsertRecordsReq(sessionId, deviceId, measurementLst, valuesLstInBytes, timestampLst); + } + public async Task InsertStringRecordAsync(string deviceId, List measurements, List values, + long timestamp) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = GenInsertStrRecordReq(deviceId, measurements, values, timestamp, client.SessionId); - var req = GenInsertRecordsOfOneDeviceRequest(deviceId, rowRecords, client.SessionId); - req.IsAligned = true; + var status = await client.ServiceClient.insertStringRecordAsync(req); - var status = await client.ServiceClient.insertRecordsOfOneDeviceAsync(req); + if (_debugMode) + { + _logger.LogInformation("insert one string record to device {0}, server message: {1}", deviceId, status.Message); + } - if (_debugMode) - { - _logger.LogInformation("insert aligned records of one device, message: {0}", status.Message); - } + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when inserting a string record" + ); + } + public async Task InsertAlignedStringRecordAsync(string deviceId, List measurements, List values, + long timestamp) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = GenInsertStrRecordReq(deviceId, measurements, values, timestamp, client.SessionId, true); - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when inserting aligned records of one device" - ); - } - public async Task TestInsertRecordAsync(string deviceId, RowRecord record) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = new TSInsertRecordReq( - client.SessionId, - deviceId, - record.Measurements, - record.ToBytes(), - record.Timestamps); - - var status = await client.ServiceClient.testInsertRecordAsync(req); - - if (_debugMode) - { - _logger.LogInformation("insert one record to device {0}, server message: {1}", deviceId, status.Message); - } + var status = await client.ServiceClient.insertStringRecordAsync(req); - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when test inserting one record" - ); - } - public async Task TestInsertRecordsAsync(List deviceId, List rowRecords) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = GenInsertRecordsReq(deviceId, rowRecords, client.SessionId); + if (_debugMode) + { + _logger.LogInformation("insert one record to device {0}, server message: {1}", deviceId, status.Message); + } - var status = await client.ServiceClient.testInsertRecordsAsync(req); + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when inserting a string record" + ); + } + public async Task InsertStringRecordsAsync(List deviceIds, List> measurements, List> values, + List timestamps) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = GenInsertStringRecordsReq(deviceIds, measurements, values, timestamps, client.SessionId); - if (_debugMode) - { - _logger.LogInformation("insert multiple records to devices {0}, server message: {1}", deviceId, status.Message); - } + var status = await client.ServiceClient.insertStringRecordsAsync(req); - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when test inserting multiple records" - ); - } - public async Task TestInsertTabletAsync(Tablet tablet) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = GenInsertTabletReq(tablet, client.SessionId); + if (_debugMode) + { + _logger.LogInformation("insert string records to devices {0}, server message: {1}", deviceIds, status.Message); + } - var status = await client.ServiceClient.testInsertTabletAsync(req); + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when inserting string records" + ); + } + public async Task InsertAlignedStringRecordsAsync(List deviceIds, List> measurements, List> values, + List timestamps) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = GenInsertStringRecordsReq(deviceIds, measurements, values, timestamps, client.SessionId, true); - if (_debugMode) - { - _logger.LogInformation("insert one tablet to device {0}, server message: {1}", tablet.InsertTargetName, status.Message); - } + var status = await client.ServiceClient.insertStringRecordsAsync(req); - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when test inserting one tablet" - ); - } - public async Task TestInsertTabletsAsync(List tabletLst) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = GenInsertTabletsReq(tabletLst, client.SessionId); + if (_debugMode) + { + _logger.LogInformation("insert string records to devices {0}, server message: {1}", deviceIds, status.Message); + } - var status = await client.ServiceClient.testInsertTabletsAsync(req); + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when inserting string records" + ); + } + public async Task InsertRecordsAsync(List deviceId, List rowRecords) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = GenInsertRecordsReq(deviceId, rowRecords, client.SessionId); - if (_debugMode) - { - _logger.LogInformation("insert multiple tablets, message: {0}", status.Message); - } + var status = await client.ServiceClient.insertRecordsAsync(req); - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when test inserting multiple tablets" - ); - } + if (_debugMode) + { + _logger.LogInformation("insert multiple records to devices {0}, server message: {1}", deviceId, status.Message); + } - public async Task ExecuteQueryStatementAsync(string sql) - { - // default timeout is 60s - return await ExecuteQueryStatementAsync(sql, 60 * 1000); - } + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when inserting records" + ); + } + public async Task InsertAlignedRecordsAsync(List deviceId, List rowRecords) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = GenInsertRecordsReq(deviceId, rowRecords, client.SessionId); + req.IsAligned = true; + // ASSERT that the insert plan is aligned + System.Diagnostics.Debug.Assert(req.IsAligned == true); + + var status = await client.ServiceClient.insertRecordsAsync(req); + + if (_debugMode) + { + _logger.LogInformation("insert multiple records to devices {0}, server message: {1}", deviceId, status.Message); + } + + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when inserting records" + ); + } + public TSInsertTabletReq GenInsertTabletReq(Tablet tablet, long sessionId) + { + return new TSInsertTabletReq( + sessionId, + tablet.InsertTargetName, + tablet.Measurements, + tablet.GetBinaryValues(), + tablet.GetBinaryTimestamps(), + tablet.GetDataTypes(), + tablet.RowNumber); + } + public async Task InsertTabletAsync(Tablet tablet) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = GenInsertTabletReq(tablet, client.SessionId); - public async Task ExecuteQueryStatementAsync(string sql, long timeoutInMs) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = new TSExecuteStatementReq(client.SessionId, sql, client.StatementId) - { - FetchSize = _fetchSize, - Timeout = timeoutInMs - }; + var status = await client.ServiceClient.insertTabletAsync(req); - var resp = await client.ServiceClient.executeQueryStatementAsync(req); - var status = resp.Status; + if (_debugMode) + { + _logger.LogInformation("insert one tablet to device {0}, server message: {1}", tablet.InsertTargetName, status.Message); + } - if (_utilFunctions.VerifySuccess(status) == -1) - { - throw new Exception(string.Format("execute query failed, sql: {0}, message: {1}", sql, status.Message)); - } + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when inserting tablet" + ); + } + public async Task InsertAlignedTabletAsync(Tablet tablet) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = GenInsertTabletReq(tablet, client.SessionId); + req.IsAligned = true; - return new SessionDataSet(sql, resp, client, _clients, client.StatementId) - { - FetchSize = _fetchSize, - }; - }, - errMsg: "Error occurs when executing query statement", - putClientBack: false - ); - } + var status = await client.ServiceClient.insertTabletAsync(req); - public async Task ExecuteStatementAsync(string sql, long timeout) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = new TSExecuteStatementReq(client.SessionId, sql, client.StatementId) - { - FetchSize = _fetchSize, - Timeout = timeout - }; + if (_debugMode) + { + _logger.LogInformation("insert one aligned tablet to device {0}, server message: {1}", tablet.InsertTargetName, status.Message); + } - var resp = await client.ServiceClient.executeStatementAsync(req); - var status = resp.Status; + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when inserting aligned tablet" + ); + } - if (_utilFunctions.VerifySuccess(status) == -1) - { - throw new Exception(string.Format("execute query failed, sql: {0}, message: {1}", sql, status.Message)); - } + protected internal async Task InsertRelationalTabletAsync(Tablet tablet) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = GenInsertTabletReq(tablet, client.SessionId); + req.ColumnCategories = tablet.GetColumnColumnCategories(); + req.WriteToTable = true; - return new SessionDataSet(sql, resp, client, _clients, client.StatementId) - { - FetchSize = _fetchSize, - }; - }, - errMsg: "Error occurs when executing query statement", - putClientBack: false - ); - } + var status = await client.ServiceClient.insertTabletAsync(req); + if (_debugMode) + { + _logger.LogInformation("insert one tablet to table {0}, server message: {1}", tablet.InsertTargetName, status.Message); + } - public async Task ExecuteNonQueryStatementAsync(string sql) - { - return await ExecuteClientOperationAsync( - async client => - { - String previousDB = _database; - var req = new TSExecuteStatementReq(client.SessionId, sql, client.StatementId); + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when inserting tablet" + ); + } - var resp = await client.ServiceClient.executeUpdateStatementAsync(req); - var status = resp.Status; + public TSInsertTabletsReq GenInsertTabletsReq(List tabletLst, long sessionId) + { + var deviceIdLst = new List(); + var measurementsLst = new List>(); + var valuesLst = new List(); + var timestampsLst = new List(); + var typeLst = new List>(); + var sizeLst = new List(); + + foreach (var tablet in tabletLst) + { + var dataTypeValues = tablet.GetDataTypes(); + deviceIdLst.Add(tablet.InsertTargetName); + measurementsLst.Add(tablet.Measurements); + valuesLst.Add(tablet.GetBinaryValues()); + timestampsLst.Add(tablet.GetBinaryTimestamps()); + typeLst.Add(dataTypeValues); + sizeLst.Add(tablet.RowNumber); + } + + return new TSInsertTabletsReq( + sessionId, + deviceIdLst, + measurementsLst, + valuesLst, + timestampsLst, + typeLst, + sizeLst); + } - if (resp.__isset.database) - { - this._database = resp.Database; - } - if (_database != previousDB) - { - // all client should switch to the same database - foreach (var c in _clients.ClientQueue) - { - try + public async Task InsertTabletsAsync(List tabletLst) + { + return await ExecuteClientOperationAsync( + async client => { - if (c != client) - { - var switchReq = new TSExecuteStatementReq(c.SessionId, sql, c.StatementId); - await c.ServiceClient.executeUpdateStatementAsync(switchReq); - } - } - catch (Exception e) + var req = GenInsertTabletsReq(tabletLst, client.SessionId); + + var status = await client.ServiceClient.insertTabletsAsync(req); + + if (_debugMode) + { + _logger.LogInformation("insert multiple tablets, message: {0}", status.Message); + } + + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when inserting tablets" + ); + } + public async Task InsertAlignedTabletsAsync(List tabletLst) + { + return await ExecuteClientOperationAsync( + async client => { - _logger.LogError("switch database from {0} to {1} failed for {2}, error: {3}", previousDB, _database, c.SessionId, e.Message); - } - } - _logger.LogInformation("switch database from {0} to {1}", previousDB, _database); - } + var req = GenInsertTabletsReq(tabletLst, client.SessionId); + req.IsAligned = true; - if (_debugMode) - { - _logger.LogInformation("execute non-query statement {0} message: {1}", sql, status.Message); - } + var status = await client.ServiceClient.insertTabletsAsync(req); - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when executing non-query statement" - ); - } - public async Task ExecuteRawDataQuery(List paths, long startTime, long endTime) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = new TSRawDataQueryReq(client.SessionId, paths, startTime, endTime, client.StatementId) - { - FetchSize = _fetchSize, - EnableRedirectQuery = false - }; + if (_debugMode) + { + _logger.LogInformation("insert multiple aligned tablets, message: {0}", status.Message); + } - var resp = await client.ServiceClient.executeRawDataQueryAsync(req); - var status = resp.Status; + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when inserting aligned tablets" + ); + } - if (_utilFunctions.VerifySuccess(status) == -1) - { - throw new Exception(string.Format("execute raw data query failed, message: {0}", status.Message)); - } + public async Task InsertRecordsOfOneDeviceAsync(string deviceId, List rowRecords) + { + var sortedRowRecords = rowRecords.OrderBy(x => x.Timestamps).ToList(); + return await InsertRecordsOfOneDeviceSortedAsync(deviceId, sortedRowRecords); + } + public async Task InsertAlignedRecordsOfOneDeviceAsync(string deviceId, List rowRecords) + { + var sortedRowRecords = rowRecords.OrderBy(x => x.Timestamps).ToList(); + return await InsertAlignedRecordsOfOneDeviceSortedAsync(deviceId, sortedRowRecords); + } + public async Task InsertStringRecordsOfOneDeviceAsync(string deviceId, List timestamps, + List> measurementsList, List> valuesList) + { + var joined = timestamps.Zip(measurementsList, (t, m) => new { t, m }) + .Zip(valuesList, (tm, v) => new { tm.t, tm.m, v }) + .OrderBy(x => x.t); - return new SessionDataSet("", resp, client, _clients, client.StatementId) - { - FetchSize = _fetchSize, - }; - }, - errMsg: "Error occurs when executing raw data query", - putClientBack: false - ); - } - public async Task ExecuteLastDataQueryAsync(List paths, long lastTime) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = new TSLastDataQueryReq(client.SessionId, paths, lastTime, client.StatementId) - { - FetchSize = _fetchSize, - EnableRedirectQuery = false - }; + var sortedTimestamps = joined.Select(x => x.t).ToList(); + var sortedMeasurementsList = joined.Select(x => x.m).ToList(); + var sortedValuesList = joined.Select(x => x.v).ToList(); - var resp = await client.ServiceClient.executeLastDataQueryAsync(req); - var status = resp.Status; + return await InsertStringRecordsOfOneDeviceSortedAsync(deviceId, sortedTimestamps, sortedMeasurementsList, sortedValuesList, false); + } + public async Task InsertAlignedStringRecordsOfOneDeviceAsync(string deviceId, List timestamps, + List> measurementsList, List> valuesList) + { + var joined = timestamps.Zip(measurementsList, (t, m) => new { t, m }) + .Zip(valuesList, (tm, v) => new { tm.t, tm.m, v }) + .OrderBy(x => x.t); - if (_utilFunctions.VerifySuccess(status) == -1) - { - throw new Exception(string.Format("execute last data query failed, message: {0}", status.Message)); - } + var sortedTimestamps = joined.Select(x => x.t).ToList(); + var sortedMeasurementsList = joined.Select(x => x.m).ToList(); + var sortedValuesList = joined.Select(x => x.v).ToList(); - return new SessionDataSet("", resp, client, _clients, client.StatementId) - { - FetchSize = _fetchSize, + return await InsertStringRecordsOfOneDeviceSortedAsync(deviceId, sortedTimestamps, sortedMeasurementsList, sortedValuesList, true); + } + public async Task InsertStringRecordsOfOneDeviceSortedAsync(string deviceId, List timestamps, + List> measurementsList, List> valuesList, bool isAligned) + { + return await ExecuteClientOperationAsync( + async client => + { + if (!_utilFunctions.IsSorted(timestamps)) + { + throw new ArgumentException("insert string records of one device error: timestamp not sorted"); + } + + var req = GenInsertStringRecordsOfOneDeviceReq(deviceId, timestamps, measurementsList, valuesList, client.SessionId, isAligned); + + var status = await client.ServiceClient.insertStringRecordsOfOneDeviceAsync(req); + + if (_debugMode) + { + _logger.LogInformation("insert string records of one device, message: {0}", status.Message); + } + + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when inserting string records of one device" + ); + } + private TSInsertStringRecordsOfOneDeviceReq GenInsertStringRecordsOfOneDeviceReq(string deviceId, + List timestamps, List> measurementsList, List> valuesList, + long sessionId, bool isAligned = false) + { + return new TSInsertStringRecordsOfOneDeviceReq( + sessionId, + deviceId, + measurementsList, + valuesList, + timestamps) + { + IsAligned = isAligned }; - }, - errMsg: "Error occurs when executing last data query", - putClientBack: false - ); - } - [Obsolete("This method is obsolete. Use SQL instead.", false)] - public async Task CreateSchemaTemplateAsync(Template template) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = new TSCreateSchemaTemplateReq(client.SessionId, template.Name, template.ToBytes()); + } + private TSInsertRecordsOfOneDeviceReq GenInsertRecordsOfOneDeviceRequest( + string deviceId, + List records, + long sessionId) + { + var values = records.Select(row => row.ToBytes()); + var measurementsLst = records.Select(x => x.Measurements).ToList(); + var timestampLst = records.Select(x => x.Timestamps).ToList(); + + return new TSInsertRecordsOfOneDeviceReq( + sessionId, + deviceId, + measurementsLst, + values.ToList(), + timestampLst); + } + public async Task InsertRecordsOfOneDeviceSortedAsync(string deviceId, List rowRecords) + { + return await ExecuteClientOperationAsync( + async client => + { + var timestampLst = rowRecords.Select(x => x.Timestamps).ToList(); - var status = await client.ServiceClient.createSchemaTemplateAsync(req); + if (!_utilFunctions.IsSorted(timestampLst)) + { + throw new ArgumentException("insert records of one device error: timestamp not sorted"); + } - if (_debugMode) - { - _logger.LogInformation("create schema template {0} message: {1}", template.Name, status.Message); - } + var req = GenInsertRecordsOfOneDeviceRequest(deviceId, rowRecords, client.SessionId); - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when creating schema template" - ); - } + var status = await client.ServiceClient.insertRecordsOfOneDeviceAsync(req); - [Obsolete("This method is obsolete. Use SQL instead.", false)] - public async Task DropSchemaTemplateAsync(string templateName) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = new TSDropSchemaTemplateReq(client.SessionId, templateName); + if (_debugMode) + { + _logger.LogInformation("insert records of one device, message: {0}", status.Message); + } - var status = await client.ServiceClient.dropSchemaTemplateAsync(req); + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when inserting records of one device" + ); + } + public async Task InsertAlignedRecordsOfOneDeviceSortedAsync(string deviceId, List rowRecords) + { + return await ExecuteClientOperationAsync( + async client => + { + var timestampLst = rowRecords.Select(x => x.Timestamps).ToList(); - if (_debugMode) - { - _logger.LogInformation("drop schema template {0} message: {1}", templateName, status.Message); - } + if (!_utilFunctions.IsSorted(timestampLst)) + { + throw new ArgumentException("insert records of one device error: timestamp not sorted"); + } - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when dropping schema template" - ); - } - [Obsolete("This method is obsolete. Use SQL instead.", false)] - public async Task SetSchemaTemplateAsync(string templateName, string prefixPath) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = new TSSetSchemaTemplateReq(client.SessionId, templateName, prefixPath); + var req = GenInsertRecordsOfOneDeviceRequest(deviceId, rowRecords, client.SessionId); + req.IsAligned = true; - var status = await client.ServiceClient.setSchemaTemplateAsync(req); + var status = await client.ServiceClient.insertRecordsOfOneDeviceAsync(req); - if (_debugMode) - { - _logger.LogInformation("set schema template {0} message: {1}", templateName, status.Message); - } + if (_debugMode) + { + _logger.LogInformation("insert aligned records of one device, message: {0}", status.Message); + } - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when setting schema template" - ); - } - [Obsolete("This method is obsolete. Use SQL instead.", false)] - public async Task UnsetSchemaTemplateAsync(string prefixPath, string templateName) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = new TSUnsetSchemaTemplateReq(client.SessionId, prefixPath, templateName); + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when inserting aligned records of one device" + ); + } + public async Task TestInsertRecordAsync(string deviceId, RowRecord record) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = new TSInsertRecordReq( + client.SessionId, + deviceId, + record.Measurements, + record.ToBytes(), + record.Timestamps); + + var status = await client.ServiceClient.testInsertRecordAsync(req); + + if (_debugMode) + { + _logger.LogInformation("insert one record to device {0}, server message: {1}", deviceId, status.Message); + } + + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when test inserting one record" + ); + } + public async Task TestInsertRecordsAsync(List deviceId, List rowRecords) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = GenInsertRecordsReq(deviceId, rowRecords, client.SessionId); - var status = await client.ServiceClient.unsetSchemaTemplateAsync(req); + var status = await client.ServiceClient.testInsertRecordsAsync(req); - if (_debugMode) - { - _logger.LogInformation("unset schema template {0} message: {1}", templateName, status.Message); - } + if (_debugMode) + { + _logger.LogInformation("insert multiple records to devices {0}, server message: {1}", deviceId, status.Message); + } - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when unsetting schema template" - ); - } - [Obsolete("This method is obsolete. Use SQL instead.", false)] - public async Task DeleteNodeInTemplateAsync(string templateName, string path) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = new TSPruneSchemaTemplateReq(client.SessionId, templateName, path); + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when test inserting multiple records" + ); + } + public async Task TestInsertTabletAsync(Tablet tablet) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = GenInsertTabletReq(tablet, client.SessionId); - var status = await client.ServiceClient.pruneSchemaTemplateAsync(req); + var status = await client.ServiceClient.testInsertTabletAsync(req); - if (_debugMode) - { - _logger.LogInformation("delete node in template {0} message: {1}", templateName, status.Message); - } + if (_debugMode) + { + _logger.LogInformation("insert one tablet to device {0}, server message: {1}", tablet.InsertTargetName, status.Message); + } - return _utilFunctions.VerifySuccess(status); - }, - errMsg: "Error occurs when deleting node in template" - ); - } - [Obsolete("This method is obsolete. Use SQL instead.", false)] - public async Task CountMeasurementsInTemplateAsync(string name) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = new TSQueryTemplateReq(client.SessionId, name, (int)TemplateQueryType.COUNT_MEASUREMENTS); + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when test inserting one tablet" + ); + } + public async Task TestInsertTabletsAsync(List tabletLst) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = GenInsertTabletsReq(tabletLst, client.SessionId); - var resp = await client.ServiceClient.querySchemaTemplateAsync(req); - var status = resp.Status; + var status = await client.ServiceClient.testInsertTabletsAsync(req); - if (_debugMode) - { - _logger.LogInformation("count measurements in template {0} message: {1}", name, status.Message); - } + if (_debugMode) + { + _logger.LogInformation("insert multiple tablets, message: {0}", status.Message); + } - if (_utilFunctions.VerifySuccess(status) == -1) - { - throw new Exception(string.Format("count measurements in template failed, template name: {0}, message: {1}", name, status.Message)); - } - return resp.Count; - }, - errMsg: "Error occurs when counting measurements in template" - ); - } - [Obsolete("This method is obsolete. Use SQL instead.", false)] - public async Task IsMeasurementInTemplateAsync(string templateName, string path) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = new TSQueryTemplateReq(client.SessionId, templateName, (int)TemplateQueryType.IS_MEASUREMENT); - req.Measurement = path; + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when test inserting multiple tablets" + ); + } - var resp = await client.ServiceClient.querySchemaTemplateAsync(req); - var status = resp.Status; + public async Task ExecuteQueryStatementAsync(string sql) + { + // default timeout is 60s + return await ExecuteQueryStatementAsync(sql, 60 * 1000); + } - if (_debugMode) - { - _logger.LogInformation("is measurement in template {0} message: {1}", templateName, status.Message); - } + public async Task ExecuteQueryStatementAsync(string sql, long timeoutInMs) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = new TSExecuteStatementReq(client.SessionId, sql, client.StatementId) + { + FetchSize = _fetchSize, + Timeout = timeoutInMs + }; + + var resp = await client.ServiceClient.executeQueryStatementAsync(req); + var status = resp.Status; + + if (_utilFunctions.VerifySuccess(status) == -1) + { + throw new Exception(string.Format("execute query failed, sql: {0}, message: {1}", sql, status.Message)); + } + + return new SessionDataSet(sql, resp, client, _clients, client.StatementId) + { + FetchSize = _fetchSize, + }; + }, + errMsg: "Error occurs when executing query statement", + putClientBack: false + ); + } - if (_utilFunctions.VerifySuccess(status) == -1) - { - throw new Exception(string.Format("is measurement in template failed, template name: {0}, message: {1}", templateName, status.Message)); - } - return resp.Result; - }, - errMsg: "Error occurs when checking measurement in template" - ); - } - [Obsolete("This method is obsolete. Use SQL instead.", false)] - public async Task IsPathExistInTemplateAsync(string templateName, string path) - { - return await ExecuteClientOperationAsync( - async client => - { - var req = new TSQueryTemplateReq(client.SessionId, templateName, (int)TemplateQueryType.PATH_EXIST); - req.Measurement = path; + public async Task ExecuteStatementAsync(string sql, long timeout) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = new TSExecuteStatementReq(client.SessionId, sql, client.StatementId) + { + FetchSize = _fetchSize, + Timeout = timeout + }; + + var resp = await client.ServiceClient.executeStatementAsync(req); + var status = resp.Status; + + if (_utilFunctions.VerifySuccess(status) == -1) + { + throw new Exception(string.Format("execute query failed, sql: {0}, message: {1}", sql, status.Message)); + } + + return new SessionDataSet(sql, resp, client, _clients, client.StatementId) + { + FetchSize = _fetchSize, + }; + }, + errMsg: "Error occurs when executing query statement", + putClientBack: false + ); + } - var resp = await client.ServiceClient.querySchemaTemplateAsync(req); - var status = resp.Status; - if (_debugMode) - { - _logger.LogInformation("is path exist in template {0} message: {1}", templateName, status.Message); - } + public async Task ExecuteNonQueryStatementAsync(string sql) + { + return await ExecuteClientOperationAsync( + async client => + { + String previousDB = _database; + var req = new TSExecuteStatementReq(client.SessionId, sql, client.StatementId); + + var resp = await client.ServiceClient.executeUpdateStatementAsync(req); + var status = resp.Status; + + if (resp.__isset.database) + { + this._database = resp.Database; + } + if (_database != previousDB) + { + // all client should switch to the same database + foreach (var c in _clients.ClientQueue) + { + try + { + if (c != client) + { + var switchReq = new TSExecuteStatementReq(c.SessionId, sql, c.StatementId); + await c.ServiceClient.executeUpdateStatementAsync(switchReq); + } + } + catch (Exception e) + { + _logger.LogError("switch database from {0} to {1} failed for {2}, error: {3}", previousDB, _database, c.SessionId, e.Message); + } + } + _logger.LogInformation("switch database from {0} to {1}", previousDB, _database); + } + + if (_debugMode) + { + _logger.LogInformation("execute non-query statement {0} message: {1}", sql, status.Message); + } + + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when executing non-query statement" + ); + } + public async Task ExecuteRawDataQuery(List paths, long startTime, long endTime) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = new TSRawDataQueryReq(client.SessionId, paths, startTime, endTime, client.StatementId) + { + FetchSize = _fetchSize, + EnableRedirectQuery = false + }; + + var resp = await client.ServiceClient.executeRawDataQueryAsync(req); + var status = resp.Status; + + if (_utilFunctions.VerifySuccess(status) == -1) + { + throw new Exception(string.Format("execute raw data query failed, message: {0}", status.Message)); + } + + return new SessionDataSet("", resp, client, _clients, client.StatementId) + { + FetchSize = _fetchSize, + }; + }, + errMsg: "Error occurs when executing raw data query", + putClientBack: false + ); + } + public async Task ExecuteLastDataQueryAsync(List paths, long lastTime) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = new TSLastDataQueryReq(client.SessionId, paths, lastTime, client.StatementId) + { + FetchSize = _fetchSize, + EnableRedirectQuery = false + }; + + var resp = await client.ServiceClient.executeLastDataQueryAsync(req); + var status = resp.Status; + + if (_utilFunctions.VerifySuccess(status) == -1) + { + throw new Exception(string.Format("execute last data query failed, message: {0}", status.Message)); + } + + return new SessionDataSet("", resp, client, _clients, client.StatementId) + { + FetchSize = _fetchSize, + }; + }, + errMsg: "Error occurs when executing last data query", + putClientBack: false + ); + } + [Obsolete("This method is obsolete. Use SQL instead.", false)] + public async Task CreateSchemaTemplateAsync(Template template) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = new TSCreateSchemaTemplateReq(client.SessionId, template.Name, template.ToBytes()); - if (_utilFunctions.VerifySuccess(status) == -1) - { - throw new Exception(string.Format("is path exist in template failed, template name: {0}, message: {1}", templateName, status.Message)); - } - return resp.Result; - }, - errMsg: "Error occurs when checking path exist in template" - ); - } - [Obsolete("This method is obsolete. Use SQL instead.", false)] - public async Task> ShowMeasurementsInTemplateAsync(string templateName, string pattern = "") - { - return await ExecuteClientOperationAsync>( - async client => - { - var req = new TSQueryTemplateReq(client.SessionId, templateName, (int)TemplateQueryType.SHOW_MEASUREMENTS); - req.Measurement = pattern; + var status = await client.ServiceClient.createSchemaTemplateAsync(req); - var resp = await client.ServiceClient.querySchemaTemplateAsync(req); - var status = resp.Status; + if (_debugMode) + { + _logger.LogInformation("create schema template {0} message: {1}", template.Name, status.Message); + } - if (_debugMode) - { - _logger.LogInformation("get measurements in template {0} message: {1}", templateName, status.Message); - } + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when creating schema template" + ); + } - if (_utilFunctions.VerifySuccess(status) == -1) - { - throw new Exception(string.Format("show measurements in template failed, template name: {0}, pattern: {1}, message: {2}", templateName, pattern, status.Message)); - } - return resp.Measurements; - }, - errMsg: "Error occurs when showing measurements in template" - ); - } - [Obsolete("This method is obsolete. Use SQL instead.", false)] - public async Task> ShowAllTemplatesAsync() - { - return await ExecuteClientOperationAsync>( - async client => - { - var req = new TSQueryTemplateReq(client.SessionId, "", (int)TemplateQueryType.SHOW_TEMPLATES); + [Obsolete("This method is obsolete. Use SQL instead.", false)] + public async Task DropSchemaTemplateAsync(string templateName) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = new TSDropSchemaTemplateReq(client.SessionId, templateName); - var resp = await client.ServiceClient.querySchemaTemplateAsync(req); - var status = resp.Status; + var status = await client.ServiceClient.dropSchemaTemplateAsync(req); - if (_debugMode) - { - _logger.LogInformation("get all templates message: {0}", status.Message); - } + if (_debugMode) + { + _logger.LogInformation("drop schema template {0} message: {1}", templateName, status.Message); + } - if (_utilFunctions.VerifySuccess(status) == -1) - { - throw new Exception(string.Format("show all templates failed, message: {0}", status.Message)); - } - return resp.Measurements; - }, - errMsg: "Error occurs when getting all templates" - ); - } + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when dropping schema template" + ); + } + [Obsolete("This method is obsolete. Use SQL instead.", false)] + public async Task SetSchemaTemplateAsync(string templateName, string prefixPath) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = new TSSetSchemaTemplateReq(client.SessionId, templateName, prefixPath); - [Obsolete("This method is obsolete. Use SQL instead.", false)] - public async Task> ShowPathsTemplateSetOnAsync(string templateName) - { - return await ExecuteClientOperationAsync>( - async client => - { - var req = new TSQueryTemplateReq(client.SessionId, templateName, (int)TemplateQueryType.SHOW_SET_TEMPLATES); + var status = await client.ServiceClient.setSchemaTemplateAsync(req); - var resp = await client.ServiceClient.querySchemaTemplateAsync(req); - var status = resp.Status; + if (_debugMode) + { + _logger.LogInformation("set schema template {0} message: {1}", templateName, status.Message); + } - if (_debugMode) - { - _logger.LogInformation("get paths template set on {0} message: {1}", templateName, status.Message); - } + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when setting schema template" + ); + } + [Obsolete("This method is obsolete. Use SQL instead.", false)] + public async Task UnsetSchemaTemplateAsync(string prefixPath, string templateName) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = new TSUnsetSchemaTemplateReq(client.SessionId, prefixPath, templateName); - if (_utilFunctions.VerifySuccess(status) == -1) - { - throw new Exception(string.Format("show paths template set on failed, template name: {0}, message: {1}", templateName, status.Message)); - } - return resp.Measurements; - }, - errMsg: "Error occurs when getting paths template set on" - ); - } - [Obsolete("This method is obsolete. Use SQL instead.", false)] - public async Task> ShowPathsTemplateUsingOnAsync(string templateName) - { - return await ExecuteClientOperationAsync>( - async client => - { - var req = new TSQueryTemplateReq(client.SessionId, templateName, (int)TemplateQueryType.SHOW_USING_TEMPLATES); + var status = await client.ServiceClient.unsetSchemaTemplateAsync(req); - var resp = await client.ServiceClient.querySchemaTemplateAsync(req); - var status = resp.Status; + if (_debugMode) + { + _logger.LogInformation("unset schema template {0} message: {1}", templateName, status.Message); + } - if (_debugMode) - { - _logger.LogInformation("get paths template using on {0} message: {1}", templateName, status.Message); - } + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when unsetting schema template" + ); + } + [Obsolete("This method is obsolete. Use SQL instead.", false)] + public async Task DeleteNodeInTemplateAsync(string templateName, string path) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = new TSPruneSchemaTemplateReq(client.SessionId, templateName, path); - if (_utilFunctions.VerifySuccess(status) == -1) - { - throw new Exception(string.Format("show paths template using on failed, template name: {0}, message: {1}", templateName, status.Message)); - } - return resp.Measurements; - }, - errMsg: "Error occurs when getting paths template using on" - ); - } + var status = await client.ServiceClient.pruneSchemaTemplateAsync(req); - protected virtual void Dispose(bool disposing) - { - if (!disposedValue) - { - if (disposing) + if (_debugMode) + { + _logger.LogInformation("delete node in template {0} message: {1}", templateName, status.Message); + } + + return _utilFunctions.VerifySuccess(status); + }, + errMsg: "Error occurs when deleting node in template" + ); + } + [Obsolete("This method is obsolete. Use SQL instead.", false)] + public async Task CountMeasurementsInTemplateAsync(string name) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = new TSQueryTemplateReq(client.SessionId, name, (int)TemplateQueryType.COUNT_MEASUREMENTS); + + var resp = await client.ServiceClient.querySchemaTemplateAsync(req); + var status = resp.Status; + + if (_debugMode) + { + _logger.LogInformation("count measurements in template {0} message: {1}", name, status.Message); + } + + if (_utilFunctions.VerifySuccess(status) == -1) + { + throw new Exception(string.Format("count measurements in template failed, template name: {0}, message: {1}", name, status.Message)); + } + return resp.Count; + }, + errMsg: "Error occurs when counting measurements in template" + ); + } + [Obsolete("This method is obsolete. Use SQL instead.", false)] + public async Task IsMeasurementInTemplateAsync(string templateName, string path) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = new TSQueryTemplateReq(client.SessionId, templateName, (int)TemplateQueryType.IS_MEASUREMENT); + req.Measurement = path; + + var resp = await client.ServiceClient.querySchemaTemplateAsync(req); + var status = resp.Status; + + if (_debugMode) + { + _logger.LogInformation("is measurement in template {0} message: {1}", templateName, status.Message); + } + + if (_utilFunctions.VerifySuccess(status) == -1) + { + throw new Exception(string.Format("is measurement in template failed, template name: {0}, message: {1}", templateName, status.Message)); + } + return resp.Result; + }, + errMsg: "Error occurs when checking measurement in template" + ); + } + [Obsolete("This method is obsolete. Use SQL instead.", false)] + public async Task IsPathExistInTemplateAsync(string templateName, string path) + { + return await ExecuteClientOperationAsync( + async client => + { + var req = new TSQueryTemplateReq(client.SessionId, templateName, (int)TemplateQueryType.PATH_EXIST); + req.Measurement = path; + + var resp = await client.ServiceClient.querySchemaTemplateAsync(req); + var status = resp.Status; + + if (_debugMode) + { + _logger.LogInformation("is path exist in template {0} message: {1}", templateName, status.Message); + } + + if (_utilFunctions.VerifySuccess(status) == -1) + { + throw new Exception(string.Format("is path exist in template failed, template name: {0}, message: {1}", templateName, status.Message)); + } + return resp.Result; + }, + errMsg: "Error occurs when checking path exist in template" + ); + } + [Obsolete("This method is obsolete. Use SQL instead.", false)] + public async Task> ShowMeasurementsInTemplateAsync(string templateName, string pattern = "") { + return await ExecuteClientOperationAsync>( + async client => + { + var req = new TSQueryTemplateReq(client.SessionId, templateName, (int)TemplateQueryType.SHOW_MEASUREMENTS); + req.Measurement = pattern; + + var resp = await client.ServiceClient.querySchemaTemplateAsync(req); + var status = resp.Status; + + if (_debugMode) + { + _logger.LogInformation("get measurements in template {0} message: {1}", templateName, status.Message); + } + + if (_utilFunctions.VerifySuccess(status) == -1) + { + throw new Exception(string.Format("show measurements in template failed, template name: {0}, pattern: {1}, message: {2}", templateName, pattern, status.Message)); + } + return resp.Measurements; + }, + errMsg: "Error occurs when showing measurements in template" + ); + } + [Obsolete("This method is obsolete. Use SQL instead.", false)] + public async Task> ShowAllTemplatesAsync() + { + return await ExecuteClientOperationAsync>( + async client => + { + var req = new TSQueryTemplateReq(client.SessionId, "", (int)TemplateQueryType.SHOW_TEMPLATES); + + var resp = await client.ServiceClient.querySchemaTemplateAsync(req); + var status = resp.Status; + + if (_debugMode) + { + _logger.LogInformation("get all templates message: {0}", status.Message); + } + + if (_utilFunctions.VerifySuccess(status) == -1) + { + throw new Exception(string.Format("show all templates failed, message: {0}", status.Message)); + } + return resp.Measurements; + }, + errMsg: "Error occurs when getting all templates" + ); + } + + [Obsolete("This method is obsolete. Use SQL instead.", false)] + public async Task> ShowPathsTemplateSetOnAsync(string templateName) + { + return await ExecuteClientOperationAsync>( + async client => + { + var req = new TSQueryTemplateReq(client.SessionId, templateName, (int)TemplateQueryType.SHOW_SET_TEMPLATES); + + var resp = await client.ServiceClient.querySchemaTemplateAsync(req); + var status = resp.Status; + + if (_debugMode) + { + _logger.LogInformation("get paths template set on {0} message: {1}", templateName, status.Message); + } + + if (_utilFunctions.VerifySuccess(status) == -1) + { + throw new Exception(string.Format("show paths template set on failed, template name: {0}, message: {1}", templateName, status.Message)); + } + return resp.Measurements; + }, + errMsg: "Error occurs when getting paths template set on" + ); + } + [Obsolete("This method is obsolete. Use SQL instead.", false)] + public async Task> ShowPathsTemplateUsingOnAsync(string templateName) + { + return await ExecuteClientOperationAsync>( + async client => + { + var req = new TSQueryTemplateReq(client.SessionId, templateName, (int)TemplateQueryType.SHOW_USING_TEMPLATES); + + var resp = await client.ServiceClient.querySchemaTemplateAsync(req); + var status = resp.Status; + + if (_debugMode) + { + _logger.LogInformation("get paths template using on {0} message: {1}", templateName, status.Message); + } + + if (_utilFunctions.VerifySuccess(status) == -1) + { + throw new Exception(string.Format("show paths template using on failed, template name: {0}, message: {1}", templateName, status.Message)); + } + return resp.Measurements; + }, + errMsg: "Error occurs when getting paths template using on" + ); + } + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { #if NET461_OR_GREATER || NETSTANDARD2_0 #else - _clients.ClientQueue.Clear(); + _clients.ClientQueue.Clear(); #endif + } + _clients = null; + disposedValue = true; + } } - _clients = null; - disposedValue = true; - } - } - public void Dispose() - { - Dispose(disposing: true); - GC.SuppressFinalize(this); + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } } - } -} \ No newline at end of file +} diff --git a/src/Apache.IoTDB/TableSessionPool.Builder.cs b/src/Apache.IoTDB/TableSessionPool.Builder.cs index 0c32f4b..fdeb78e 100644 --- a/src/Apache.IoTDB/TableSessionPool.Builder.cs +++ b/src/Apache.IoTDB/TableSessionPool.Builder.cs @@ -26,121 +26,121 @@ namespace Apache.IoTDB; public partial class TableSessionPool { - public class Builder - { - private string _host = "localhost"; - private int _port = 6667; - private string _username = "root"; - private string _password = "root"; - private int _fetchSize = 1024; - private string _zoneId = "UTC+08:00"; - private int _poolSize = 8; - private bool _enableRpcCompression = false; - private int _connectionTimeoutInMs = 500; - private string _sqlDialect = IoTDBConstant.TREE_SQL_DIALECT; - private string _database = ""; - private List _nodeUrls = new List(); - - public Builder SetHost(string host) + public class Builder { - _host = host; - return this; + private string _host = "localhost"; + private int _port = 6667; + private string _username = "root"; + private string _password = "root"; + private int _fetchSize = 1024; + private string _zoneId = "UTC+08:00"; + private int _poolSize = 8; + private bool _enableRpcCompression = false; + private int _connectionTimeoutInMs = 500; + private string _sqlDialect = IoTDBConstant.TREE_SQL_DIALECT; + private string _database = ""; + private List _nodeUrls = new List(); + + public Builder SetHost(string host) + { + _host = host; + return this; + } + + public Builder SetPort(int port) + { + _port = port; + return this; + } + + public Builder SetUsername(string username) + { + _username = username; + return this; + } + + public Builder SetPassword(string password) + { + _password = password; + return this; + } + + public Builder SetFetchSize(int fetchSize) + { + _fetchSize = fetchSize; + return this; + } + + public Builder SetZoneId(string zoneId) + { + _zoneId = zoneId; + return this; + } + + public Builder SetPoolSize(int poolSize) + { + _poolSize = poolSize; + return this; + } + + public Builder SetEnableRpcCompression(bool enableRpcCompression) + { + _enableRpcCompression = enableRpcCompression; + return this; + } + + public Builder SetConnectionTimeoutInMs(int timeout) + { + _connectionTimeoutInMs = timeout; + return this; + } + + public Builder SetNodeUrls(List nodeUrls) + { + _nodeUrls = nodeUrls; + return this; + } + + protected internal Builder SetSqlDialect(string sqlDialect) + { + _sqlDialect = sqlDialect; + return this; + } + + public Builder SetDatabase(string database) + { + _database = database; + return this; + } + + public Builder() + { + _host = "localhost"; + _port = 6667; + _username = "root"; + _password = "root"; + _fetchSize = 1024; + _zoneId = "UTC+08:00"; + _poolSize = 8; + _enableRpcCompression = false; + _connectionTimeoutInMs = 500; + _sqlDialect = IoTDBConstant.TABLE_SQL_DIALECT; + _database = ""; + } + + public TableSessionPool Build() + { + SessionPool sessionPool; + // if nodeUrls is not empty, use nodeUrls to create session pool + if (_nodeUrls.Count > 0) + { + sessionPool = new SessionPool(_nodeUrls, _username, _password, _fetchSize, _zoneId, _poolSize, _enableRpcCompression, _connectionTimeoutInMs, _sqlDialect, _database); + } + else + { + sessionPool = new SessionPool(_host, _port, _username, _password, _fetchSize, _zoneId, _poolSize, _enableRpcCompression, _connectionTimeoutInMs, _sqlDialect, _database); + } + return new TableSessionPool(sessionPool); + } } - - public Builder SetPort(int port) - { - _port = port; - return this; - } - - public Builder SetUsername(string username) - { - _username = username; - return this; - } - - public Builder SetPassword(string password) - { - _password = password; - return this; - } - - public Builder SetFetchSize(int fetchSize) - { - _fetchSize = fetchSize; - return this; - } - - public Builder SetZoneId(string zoneId) - { - _zoneId = zoneId; - return this; - } - - public Builder SetPoolSize(int poolSize) - { - _poolSize = poolSize; - return this; - } - - public Builder SetEnableRpcCompression(bool enableRpcCompression) - { - _enableRpcCompression = enableRpcCompression; - return this; - } - - public Builder SetConnectionTimeoutInMs(int timeout) - { - _connectionTimeoutInMs = timeout; - return this; - } - - public Builder SetNodeUrls(List nodeUrls) - { - _nodeUrls = nodeUrls; - return this; - } - - protected internal Builder SetSqlDialect(string sqlDialect) - { - _sqlDialect = sqlDialect; - return this; - } - - public Builder SetDatabase(string database) - { - _database = database; - return this; - } - - public Builder() - { - _host = "localhost"; - _port = 6667; - _username = "root"; - _password = "root"; - _fetchSize = 1024; - _zoneId = "UTC+08:00"; - _poolSize = 8; - _enableRpcCompression = false; - _connectionTimeoutInMs = 500; - _sqlDialect = IoTDBConstant.TABLE_SQL_DIALECT; - _database = ""; - } - - public TableSessionPool Build() - { - SessionPool sessionPool; - // if nodeUrls is not empty, use nodeUrls to create session pool - if (_nodeUrls.Count > 0) - { - sessionPool = new SessionPool(_nodeUrls, _username, _password, _fetchSize, _zoneId, _poolSize, _enableRpcCompression, _connectionTimeoutInMs, _sqlDialect, _database); - } - else - { - sessionPool = new SessionPool(_host, _port, _username, _password, _fetchSize, _zoneId, _poolSize, _enableRpcCompression, _connectionTimeoutInMs, _sqlDialect, _database); - } - return new TableSessionPool(sessionPool); - } - } } diff --git a/src/Apache.IoTDB/TableSessionPool.cs b/src/Apache.IoTDB/TableSessionPool.cs index ddc977f..921aba1 100644 --- a/src/Apache.IoTDB/TableSessionPool.cs +++ b/src/Apache.IoTDB/TableSessionPool.cs @@ -28,50 +28,50 @@ namespace Apache.IoTDB; public partial class TableSessionPool { - private SessionPool sessionPool; + private SessionPool sessionPool; - TableSessionPool(SessionPool sessionPool) - { - this.sessionPool = sessionPool; - } + TableSessionPool(SessionPool sessionPool) + { + this.sessionPool = sessionPool; + } - public async Task Open(bool enableRpcCompression, CancellationToken cancellationToken = default) - { - await sessionPool.Open(enableRpcCompression, cancellationToken); - } + public async Task Open(bool enableRpcCompression, CancellationToken cancellationToken = default) + { + await sessionPool.Open(enableRpcCompression, cancellationToken); + } - public async Task Open(CancellationToken cancellationToken = default) - { - await sessionPool.Open(cancellationToken); - } + public async Task Open(CancellationToken cancellationToken = default) + { + await sessionPool.Open(cancellationToken); + } - public async Task InsertAsync(Tablet tablet) - { - return await sessionPool.InsertRelationalTabletAsync(tablet); - } + public async Task InsertAsync(Tablet tablet) + { + return await sessionPool.InsertRelationalTabletAsync(tablet); + } - public async Task ExecuteNonQueryStatementAsync(string sql) - { - return await sessionPool.ExecuteNonQueryStatementAsync(sql); - } + public async Task ExecuteNonQueryStatementAsync(string sql) + { + return await sessionPool.ExecuteNonQueryStatementAsync(sql); + } - public async Task ExecuteQueryStatementAsync(string sql) - { - return await sessionPool.ExecuteQueryStatementAsync(sql); - } + public async Task ExecuteQueryStatementAsync(string sql) + { + return await sessionPool.ExecuteQueryStatementAsync(sql); + } - public async Task ExecuteQueryStatementAsync(string sql, long timeoutInMs) - { - return await sessionPool.ExecuteQueryStatementAsync(sql, timeoutInMs); - } + public async Task ExecuteQueryStatementAsync(string sql, long timeoutInMs) + { + return await sessionPool.ExecuteQueryStatementAsync(sql, timeoutInMs); + } - public void OpenDebugMode(Action configure) - { - sessionPool.OpenDebugMode(configure); - } + public void OpenDebugMode(Action configure) + { + sessionPool.OpenDebugMode(configure); + } - public async Task Close() - { - await sessionPool.Close(); - } + public async Task Close() + { + await sessionPool.Close(); + } } diff --git a/src/Apache.IoTDB/Template/InternalNode.cs b/src/Apache.IoTDB/Template/InternalNode.cs index f08ecf6..50a4cc4 100644 --- a/src/Apache.IoTDB/Template/InternalNode.cs +++ b/src/Apache.IoTDB/Template/InternalNode.cs @@ -58,4 +58,4 @@ public override bool isShareTime() return this.shareTime; } } -} \ No newline at end of file +} diff --git a/src/Apache.IoTDB/Template/MeasurementNode.cs b/src/Apache.IoTDB/Template/MeasurementNode.cs index 790ca0f..bed6604 100644 --- a/src/Apache.IoTDB/Template/MeasurementNode.cs +++ b/src/Apache.IoTDB/Template/MeasurementNode.cs @@ -73,4 +73,4 @@ public override byte[] ToBytes() } -} \ No newline at end of file +} diff --git a/src/Apache.IoTDB/Template/Template.cs b/src/Apache.IoTDB/Template/Template.cs index 74830a2..b14e51f 100644 --- a/src/Apache.IoTDB/Template/Template.cs +++ b/src/Apache.IoTDB/Template/Template.cs @@ -141,4 +141,4 @@ public byte[] ToBytes() } } -} \ No newline at end of file +} diff --git a/src/Apache.IoTDB/Template/TemplateNode.cs b/src/Apache.IoTDB/Template/TemplateNode.cs index 325e43c..c2614e5 100644 --- a/src/Apache.IoTDB/Template/TemplateNode.cs +++ b/src/Apache.IoTDB/Template/TemplateNode.cs @@ -57,4 +57,4 @@ public virtual byte[] ToBytes() return null; } } -} \ No newline at end of file +} diff --git a/src/Apache.IoTDB/Utils.cs b/src/Apache.IoTDB/Utils.cs index d50a08d..627314c 100644 --- a/src/Apache.IoTDB/Utils.cs +++ b/src/Apache.IoTDB/Utils.cs @@ -106,15 +106,15 @@ public static DateTime ParseIntToDate(int dateInt) public static int ParseDateToInt(DateTime? dateTime) { - if (dateTime == null) - { - throw new ArgumentException("Date expression is none or empty."); - } - if(dateTime.Value.Year<1000) - { - throw new ArgumentException("Year must be between 1000 and 9999."); - } - return dateTime.Value.Year * 10000 + dateTime.Value.Month * 100 + dateTime.Value.Day; + if (dateTime == null) + { + throw new ArgumentException("Date expression is none or empty."); + } + if (dateTime.Value.Year < 1000) + { + throw new ArgumentException("Year must be between 1000 and 9999."); + } + return dateTime.Value.Year * 10000 + dateTime.Value.Month * 100 + dateTime.Value.Day; } public static string ByteArrayToHexString(byte[] bytes) @@ -122,4 +122,4 @@ public static string ByteArrayToHexString(byte[] bytes) return "0x" + BitConverter.ToString(bytes).Replace("-", "").ToLowerInvariant(); } } -} \ No newline at end of file +} diff --git a/tests/Apache.IoTDB.Integration.Tests/Tests.cs b/tests/Apache.IoTDB.Integration.Tests/Tests.cs index 19b3dec..b180ab6 100644 --- a/tests/Apache.IoTDB.Integration.Tests/Tests.cs +++ b/tests/Apache.IoTDB.Integration.Tests/Tests.cs @@ -34,4 +34,4 @@ public void Test1() Assert.Pass(); } } -} \ No newline at end of file +} diff --git a/tests/Apache.IoTDB.Tests/Tests.cs b/tests/Apache.IoTDB.Tests/Tests.cs index 6a78663..d796fa7 100644 --- a/tests/Apache.IoTDB.Tests/Tests.cs +++ b/tests/Apache.IoTDB.Tests/Tests.cs @@ -34,4 +34,4 @@ public void Test1() Assert.Pass(); } } -} \ No newline at end of file +}