Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
057911e
feat: support stmt2
huskar-t Aug 13, 2025
ec756bb
feat: implement stmt2 binding structures and methods
huskar-t Aug 15, 2025
10a84d3
feat: refactor stmt2 binding methods
huskar-t Aug 19, 2025
ec74269
feat: implement WSStmt2 request and response classes
huskar-t Aug 20, 2025
ee7b340
feat: add unit tests for StmtBuilder
huskar-t Aug 21, 2025
fddde0b
feat: implement DoExec method for improved database command execution
huskar-t Aug 21, 2025
35ce427
feat: add TD_3360_TEST environment variable and refactor statement ha…
huskar-t Aug 21, 2025
d480808
feat: enhance statement handling for TDengine 3.3.6.0 compatibility a…
huskar-t Aug 22, 2025
c867c01
feat: update environment variable for TDengine 3.3.6.0 testing and ad…
huskar-t Aug 22, 2025
5b9cb0e
feat: refactor length properties to count for consistency across buil…
huskar-t Aug 22, 2025
bce8c4e
feat: add stmt query tests for native and WebSocket connections
huskar-t Aug 22, 2025
2084e8a
feat: add tests for database change functionality and enhance connect…
huskar-t Aug 22, 2025
9104899
feat: implement connection handling and statement preparation for TDe…
huskar-t Aug 25, 2025
82e73ba
feat: enhance auto-reconnect handling and improve error management in…
huskar-t Aug 26, 2025
c5fde96
feat: remove unused using directives to clean up code
huskar-t Aug 26, 2025
8f4e8ab
feat: fix total length calculation and improve null memory handling i…
huskar-t Aug 27, 2025
32e4f43
feat: update table name handling to use Count property and add tests …
huskar-t Aug 27, 2025
2f511ee
feat: refactor BindColumn method to improve parameter handling and ad…
huskar-t Aug 27, 2025
d02f7b5
feat: rename doStmtTest method to DoStmtTest for consistency and impr…
huskar-t Aug 27, 2025
93baaa2
feat: add support for binding and retrieving DateTime?[] in statement…
huskar-t Aug 27, 2025
b580396
feat: add test for server version and handle TD_3360_TEST environment…
huskar-t Aug 27, 2025
97404fc
feat: replace static DateTime with DateTime.Now
huskar-t Aug 27, 2025
39c727a
fix: return offset in SetBindData
huskar-t Aug 28, 2025
6e17593
fix: add table name to builder when table info is not found
huskar-t Sep 1, 2025
28454bc
feat: implement caching for Stmt2BindTableInfo to improve performance
huskar-t Aug 29, 2025
60d32d0
refactor: update Stmt2BindColInfo and Stmt2BindTableInfo to use class…
huskar-t Sep 1, 2025
861b0b5
refactor: streamline Stmt2TableData initialization and enhance object…
huskar-t Sep 2, 2025
1ed02aa
fix: remove bound data when binding row data fails
huskar-t Sep 2, 2025
6aef663
refactor: optimize data handling in AbstractStmtExec and improve vari…
huskar-t Sep 2, 2025
1d4ea32
fix: correct logic for variable data handling and enhance error messa…
huskar-t Sep 2, 2025
e07f63f
fix: set tag data length error
huskar-t Sep 2, 2025
b73459d
test: add unit tests for StmtBindTags functionality in AbstractStmtEx…
huskar-t Sep 2, 2025
faba2db
ci: add steps to collect and upload code coverage reports to Codecov
huskar-t Sep 2, 2025
cb88b1b
test: add tests for json tag handling in stmt
huskar-t Sep 2, 2025
11b37f5
test: add MockStmt and StmtGenerateBinary for binary data handling tests
huskar-t Sep 3, 2025
117f8ca
fix: add null and empty checks for bind columns, rows, and tags
huskar-t Sep 3, 2025
0fb3fd6
test: add checks for zero row count in BindColumn method
huskar-t Sep 3, 2025
b640ded
fix: update loop index for row count check and improve exception hand…
huskar-t Sep 3, 2025
30f2550
enh: optimize native stmt2 performance
huskar-t Sep 3, 2025
b40136c
refactor: streamline table info retrieval and caching in AbstractStmt
huskar-t Sep 3, 2025
4513a08
feat: implement MockWSServer for WebSocket testing and enhance TDengi…
huskar-t Sep 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .github/workflows/compatibility-3360.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ jobs:
env:
TDENGINE_CLOUD_ENDPOINT: ${{ secrets.TDENGINE_CLOUD_ENDPOINT }}
TDENGINE_CLOUD_TOKEN: ${{ secrets.TDENGINE_CLOUD_TOKEN }}
TD_3360_TEST: 'true'
run: |
dotnet test -f ${{ matrix.tfm }} --logger "console;verbosity=detailed" --collect:"XPlat Code Coverage" --results-directory:./testresults
timeout-minutes: 15
Expand Down Expand Up @@ -193,6 +194,22 @@ jobs:
env:
TDENGINE_CLOUD_ENDPOINT: ${{ secrets.TDENGINE_CLOUD_ENDPOINT }}
TDENGINE_CLOUD_TOKEN: ${{ secrets.TDENGINE_CLOUD_TOKEN }}
TD_3360_TEST: 'true'
run: |
dotnet test -f ${{ matrix.tfm }} --logger "console;verbosity=detailed" --collect:"XPlat Code Coverage" --results-directory:./testresults
timeout-minutes: 15

- name: get coverage files
id: get_coverage_files
run: |
$coverageFiles = Get-ChildItem -Path ./testresults -Recurse -Filter "coverage.cobertura.xml" | ForEach-Object { $_.FullName }
$coverageFilesString = $coverageFiles -join ";"
echo "files=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
echo "files=${COVERAGE_FILES}" >> $Env:GITHUB_OUTPUT

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
files: ${{ steps.get_coverage_files.outputs.files }}
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_ORG_TOKEN }}
2 changes: 1 addition & 1 deletion examples/NativeADO/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public static void Main(string[] args)
"VALUES " +
"(?,?,?,?)";
var parameters = command.Parameters;
parameters.Add(new TDengineParameter("@0", new DateTime(2023,10,03,14,38,05,000)));
parameters.Add(new TDengineParameter("@0", DateTime.Now));
parameters.Add(new TDengineParameter("@1", (float)10.30000));
parameters.Add(new TDengineParameter("@2", (int)219));
parameters.Add(new TDengineParameter("@3", (float)0.31000));
Expand Down
2 changes: 1 addition & 1 deletion examples/NativeStmt/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public static void Main(string[] args)
{
stmt.Prepare(
"Insert into power.d1001 using power.meters tags(2,'California.SanFrancisco') values(?,?,?,?)");
var ts = new DateTime(2023, 10, 03, 14, 38, 05, 000);
var ts = DateTime.Now;
stmt.BindRow(new object[] { ts, (float)10.30000, (int)219, (float)0.31000 });
stmt.AddBatch();
stmt.Exec();
Expand Down
2 changes: 1 addition & 1 deletion examples/WSADO/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public static void Main(string[] args)
"VALUES " +
"(?,?,?,?)";
var parameters = command.Parameters;
parameters.Add(new TDengineParameter("@0", new DateTime(2023,10,03,14,38,05,000)));
parameters.Add(new TDengineParameter("@0", DateTime.Now));
parameters.Add(new TDengineParameter("@1", (float)10.30000));
parameters.Add(new TDengineParameter("@2", (int)219));
parameters.Add(new TDengineParameter("@3", (float)0.31000));
Expand Down
2 changes: 1 addition & 1 deletion examples/WSStmt/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public static void Main(string[] args)
{
stmt.Prepare(
"Insert into power.d1001 using power.meters tags(2,'California.SanFrancisco') values(?,?,?,?)");
var ts = new DateTime(2023, 10, 03, 14, 38, 05, 000);
var ts = DateTime.Now;
stmt.BindRow(new object[] { ts, (float)10.30000, (int)219, (float)0.31000 });
stmt.AddBatch();
stmt.Exec();
Expand Down
2 changes: 1 addition & 1 deletion examples/WindowsFormsApp4.8/Form1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ private void ShowDatabase(object sender, EventArgs e)
private void Connect(object sender, EventArgs e)
{
var builder = new ConnectionStringBuilder(
"protocol=WebSocket;host=127.0.0.1;port=6041;useSSL=false;username=root;password=taosdata");
"protocol=WebSocket;host=localhost;port=6041;useSSL=false;username=root;password=taosdata");
client = DbDriver.Open(builder);
MessageBox.Show("connected");
button_show.Enabled = true;
Expand Down
6 changes: 3 additions & 3 deletions examples/WindowsFormsApp4.8/WindowsFormsApp4.8.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="TDengine, Version=3.1.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\src\bin\Debug\net451\TDengine.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\TDengine.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="Form1.cs">
Expand Down
29 changes: 23 additions & 6 deletions src/Data/Client/TDengineCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ namespace TDengine.Data.Client
{
public class TDengineCommand : DbCommand
{
private readonly Lazy<TDengineParameterCollection> _parameters = new Lazy<TDengineParameterCollection>(
() => new TDengineParameterCollection());
private readonly Lazy<TDengineParameterCollection> _parameters =
new Lazy<TDengineParameterCollection>(() => new TDengineParameterCollection());

private TDengineConnection _connection;
private string _commandText;
Expand Down Expand Up @@ -101,6 +101,14 @@ public override string CommandText
get => _commandText;
set
{
if (_stmt != null)
{
// if the statement is not null and need to be re-prepared,
// we need to dispose the old statement and create a new one.
// this is a bug workaround for TDengine 3.3.6.0
_stmt.Dispose();
_stmt = null;
}
_isPrepared = false;
_commandText = value;
}
Expand Down Expand Up @@ -146,7 +154,7 @@ protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior)

private IRows Query()
{
return _connection.client.Query(_commandText);
return _connection.Client.Query(_commandText);
}

private IRows Statement()
Expand All @@ -156,17 +164,26 @@ private IRows Statement()
return Query();
}

if (_stmt == null && _connection != null)
if (_connection == null) throw new InvalidOperationException("Connection is null");

if (_stmt == null)
{
_stmt = _connection.Client.StmtInit();
}

else if (!_isPrepared)
{
_stmt = _connection.client.StmtInit();

_stmt.Dispose();
_stmt = _connection.Client.StmtInit();
}

if (_stmt == null) throw new InvalidOperationException("Statement is null");

if (!_isPrepared)
{
_isPrepared = true;
_stmt.Prepare(_commandText);
_isPrepared = true;
}

var isInsert = _stmt.IsInsert();
Expand Down
63 changes: 53 additions & 10 deletions src/Data/Client/TDengineConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ public class TDengineConnection : DbConnection
{
private string _connectionString;
private ConnectionState _state;
internal ITDengineClient client;

internal ITDengineClient Client;

// internal object connection;
public TDengineConnectionStringBuilder ConnectionStringBuilder { get; set; }

Expand All @@ -28,16 +30,16 @@ protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLeve

public override void ChangeDatabase(string databaseName)
{
client.Exec("use `" + databaseName + "`;");
Client.Exec("use `" + databaseName + "`;");
}

public override void Close()
{
if (State == ConnectionState.Closed) return;
if (client != null)
if (Client != null)
{
client.Dispose();
client = null;
Client.Dispose();
Client = null;
}

SetState(ConnectionState.Closed);
Expand All @@ -59,7 +61,7 @@ private void SetState(ConnectionState value)
public override void Open()
{
if (State == ConnectionState.Open) return;
client = DbDriver.Open(ConnectionStringBuilder);
Client = DbDriver.Open(ConnectionStringBuilder);
SetState(ConnectionState.Open);
}

Expand All @@ -78,16 +80,57 @@ public sealed override string ConnectionString
}
}

public override string Database => ConnectionStringBuilder.Database;
public override ConnectionState State => _state;
public override string Database
{
get
{
if (State != ConnectionState.Open) return ConnectionStringBuilder.Database;
try
{
using (var rows = Client.Query("select database();"))
{
return rows.Read() ? rows.GetString(0) : string.Empty;
}
}
catch
{
return string.Empty;
}
}
}

public override ConnectionState State
{
get
{
if (_state != ConnectionState.Open) return _state;
var client = Client;
if (client != null && !client.ConnectionAvailable())
{
SetState(ConnectionState.Broken);
}

return _state;
}
}

public override string DataSource => ConnectionStringBuilder.Host;

public override string ServerVersion
{
get
{
var rows = client.Query("select server_version();");
return Encoding.UTF8.GetString((byte[])rows.GetValue(0));
try
{
using (var rows = Client.Query("select server_version();"))
{
return rows.Read() ? rows.GetString(0) : string.Empty;
}
}
catch
{
return string.Empty;
}
}
}
}
Expand Down
25 changes: 5 additions & 20 deletions src/Driver/BlockReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public void SetBlock(byte[] block)
for (int i = 0; i < _cols - 1; i++)
{
var colLength = BitConverter.ToInt32(block, _lengthOffset + TDengineConstant.Int32Size * i);
if (IsVarDataType(_colType[i]))
if (TDengineConstant.IsVarDataType(_colType[i]))
{
_colHeadOffset[i + 1] = _colHeadOffset[i] + TDengineConstant.Int32Size * _rows + colLength;
}
Expand Down Expand Up @@ -142,21 +142,6 @@ private void InitMeta()
private bool ItemIsNull(int headOffset, int row) =>
TDengineConstant.BitmapIsNull(_block[headOffset + TDengineConstant.CharOffset(row)], row);

private static bool IsVarDataType(byte colType)
{
switch ((TDengineDataType)colType)
{
case TDengineDataType.TSDB_DATA_TYPE_BINARY:
case TDengineDataType.TSDB_DATA_TYPE_NCHAR:
case TDengineDataType.TSDB_DATA_TYPE_JSONTAG:
case TDengineDataType.TSDB_DATA_TYPE_VARBINARY:
case TDengineDataType.TSDB_DATA_TYPE_GEOMETRY:
return true;
default:
return false;
}
}

public object Read(int row, int col)
{
var colType = (TDengineDataType)_colType[col];
Expand Down Expand Up @@ -416,7 +401,7 @@ private byte[] ConvertJson(int row, int col)

public long GetChars(int row, int col, long dataOffset, char[] buffer, int bufferOffset, int length)
{
if (!IsVarDataType(_colType[col]))
if (!TDengineConstant.IsVarDataType(_colType[col]))
{
throw new Exception("GetBytes cannot be used on non-character columns");
}
Expand Down Expand Up @@ -449,7 +434,7 @@ public long GetChars(int row, int col, long dataOffset, char[] buffer, int buffe

public char GetChar(int row, int col)
{
if (!IsVarDataType(_colType[col]))
if (!TDengineConstant.IsVarDataType(_colType[col]))
{
throw new Exception("GetChar cannot be used on non-character columns");
}
Expand All @@ -469,7 +454,7 @@ public char GetChar(int row, int col)

public long GetBytes(int row, int col, long dataOffset, byte[] buffer, int bufferOffset, int length)
{
if (!IsVarDataType(_colType[col]))
if (!TDengineConstant.IsVarDataType(_colType[col]))
{
throw new Exception("GetBytes cannot be used on non-character columns");
}
Expand Down Expand Up @@ -507,7 +492,7 @@ private bool VarDataTypeIsNull(int row, int col)

public bool IsDBNull(int row, int col)
{
return IsVarDataType(_colType[col]) ? VarDataTypeIsNull(row, col) : ItemIsNull(_colHeadOffset[col], row);
return TDengineConstant.IsVarDataType(_colType[col]) ? VarDataTypeIsNull(row, col) : ItemIsNull(_colHeadOffset[col], row);
}

private void CheckNull(int row, int col)
Expand Down
Loading
Loading