From cfdb79e7e7a8496ba2c39b5c2309eb1c4aba31d2 Mon Sep 17 00:00:00 2001
From: "coderabbitai[bot]"
<136622811+coderabbitai[bot]@users.noreply.github.com>
Date: Fri, 17 Oct 2025 14:32:45 +0000
Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=93=9D=20Add=20docstrings=20to=20`rd?=
=?UTF-8?q?=5Fdecimal`?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Docstrings generation was requested by @RaphDal.
* https://github.com/questdb/net-questdb-client/pull/52#issuecomment-3415850079
The following files were modified:
* `src/dummy-http-server/DummyHttpServer.cs`
* `src/net-questdb-client-tests/DecimalTestHelpers.cs`
* `src/net-questdb-client-tests/DummyIlpServer.cs`
* `src/net-questdb-client-tests/JsonSpecTestRunner.cs`
* `src/net-questdb-client/Buffers/Buffer.cs`
* `src/net-questdb-client/Buffers/BufferV1.cs`
* `src/net-questdb-client/Buffers/BufferV2.cs`
* `src/net-questdb-client/Buffers/BufferV3.cs`
* `src/net-questdb-client/Buffers/IBuffer.cs`
* `src/net-questdb-client/Senders/AbstractSender.cs`
* `src/net-questdb-client/Senders/HttpSender.cs`
* `src/net-questdb-client/Senders/ISender.cs`
---
src/dummy-http-server/DummyHttpServer.cs | 44 +++++-
.../DecimalTestHelpers.cs | 21 +++
.../DummyIlpServer.cs | 51 +++++++
.../JsonSpecTestRunner.cs | 18 +++
src/net-questdb-client/Buffers/Buffer.cs | 12 +-
src/net-questdb-client/Buffers/BufferV1.cs | 64 +++++++-
src/net-questdb-client/Buffers/BufferV2.cs | 29 +++-
src/net-questdb-client/Buffers/BufferV3.cs | 16 +-
src/net-questdb-client/Buffers/IBuffer.cs | 22 ++-
.../Senders/AbstractSender.cs | 16 +-
src/net-questdb-client/Senders/HttpSender.cs | 46 +++++-
src/net-questdb-client/Senders/ISender.cs | 140 +++++++++++++++---
12 files changed, 437 insertions(+), 42 deletions(-)
diff --git a/src/dummy-http-server/DummyHttpServer.cs b/src/dummy-http-server/DummyHttpServer.cs
index d2d5080..fa2109f 100644
--- a/src/dummy-http-server/DummyHttpServer.cs
+++ b/src/dummy-http-server/DummyHttpServer.cs
@@ -42,6 +42,15 @@ public class DummyHttpServer : IDisposable
private int _port = 29743;
private readonly TimeSpan? _withStartDelay;
+ ///
+ /// Initializes a configurable in-process dummy HTTP server used for testing endpoints.
+ ///
+ /// If true, enable JWT bearer authentication and authorization.
+ /// If true, enable basic authentication behavior in the test endpoint.
+ /// If true, configure the test endpoint to produce retriable error responses.
+ /// If true, include error messages in test error responses.
+ /// Optional delay applied when starting the server.
+ /// If true, require client TLS certificates for HTTPS connections.
public DummyHttpServer(bool withTokenAuth = false, bool withBasicAuth = false, bool withRetriableError = false,
bool withErrorMessage = false, TimeSpan? withStartDelay = null, bool requireClientCert = false)
{
@@ -108,6 +117,13 @@ public void Dispose()
_app.StopAsync().Wait();
}
+ ///
+ /// Clears the in-memory receive buffers and resets the endpoint error state and counter.
+ ///
+ ///
+ /// Empties IlpEndpoint.ReceiveBuffer and IlpEndpoint.ReceiveBytes, sets IlpEndpoint.LastError to null,
+ /// and sets IlpEndpoint.Counter to zero.
+ ///
public void Clear()
{
IlpEndpoint.ReceiveBuffer.Clear();
@@ -116,6 +132,12 @@ public void Clear()
IlpEndpoint.Counter = 0;
}
+ ///
+ /// Starts the HTTP server on the specified port and configures the supported protocol versions.
+ ///
+ /// Port to listen on (defaults to 29743).
+ /// Array of supported protocol versions; defaults to {1, 2, 3} when null.
+ /// A task that completes after any configured startup delay has elapsed and the server's background run task has been initiated.
public async Task StartAsync(int port = 29743, int[]? versions = null)
{
if (_withStartDelay.HasValue)
@@ -128,6 +150,9 @@ public async Task StartAsync(int port = 29743, int[]? versions = null)
_ = _app.RunAsync($"http://localhost:{port}");
}
+ ///
+ /// Starts the web application and listens for HTTP requests on http://localhost:{_port}.
+ ///
public async Task RunAsync()
{
await _app.RunAsync($"http://localhost:{_port}");
@@ -138,11 +163,19 @@ public async Task StopAsync()
await _app.StopAsync();
}
+ ///
+ /// Gets the server's in-memory text buffer of received data.
+ ///
+ /// The mutable containing the accumulated received text; modifying it updates the server's buffer.
public StringBuilder GetReceiveBuffer()
{
return IlpEndpoint.ReceiveBuffer;
}
+ ///
+ /// Gets the in-memory list of bytes received by the ILP endpoint.
+ ///
+ /// The mutable list of bytes received by the endpoint.
public List GetReceivedBytes()
{
return IlpEndpoint.ReceiveBytes;
@@ -160,6 +193,10 @@ public async Task Healthcheck()
}
+ ///
+ /// Generates a JWT for the test server when the provided credentials match the server's static username and password.
+ ///
+ /// The JWT string when credentials are valid; null otherwise. The issued token is valid for one day.
public string? GetJwtToken(string username, string password)
{
if (username == Username && password == Password)
@@ -180,6 +217,11 @@ public int GetCounter()
return IlpEndpoint.Counter;
}
+ ///
+ /// Produces a human-readable string representation of the server's received-bytes buffer, interpreting embedded markers and formatting arrays and numeric values.
+ ///
+ /// The formatted textual representation of the received bytes buffer.
+ /// Thrown when the buffer contains an unsupported type code.
public string PrintBuffer()
{
var bytes = GetReceivedBytes().ToArray();
@@ -263,4 +305,4 @@ public string PrintBuffer()
sb.Append(Encoding.UTF8.GetString(bytes, lastAppend, i - lastAppend));
return sb.ToString();
}
-}
+}
\ No newline at end of file
diff --git a/src/net-questdb-client-tests/DecimalTestHelpers.cs b/src/net-questdb-client-tests/DecimalTestHelpers.cs
index 2f16fcd..77142e4 100644
--- a/src/net-questdb-client-tests/DecimalTestHelpers.cs
+++ b/src/net-questdb-client-tests/DecimalTestHelpers.cs
@@ -30,6 +30,13 @@ namespace net_questdb_client_tests;
internal static class DecimalTestHelpers
{
+ ///
+ /// Asserts that the buffer contains a decimal field for the specified column with the given scale and mantissa bytes.
+ ///
+ /// The encoded row payload to search for the column's decimal field.
+ /// The name of the column whose decimal payload is expected in the buffer.
+ /// The expected scale byte of the decimal field.
+ /// The expected mantissa bytes of the decimal field.
internal static void AssertDecimalField(ReadOnlySpan buffer,
string columnName,
byte expectedScale,
@@ -49,6 +56,14 @@ internal static void AssertDecimalField(ReadOnlySpan buffer,
$"Mantissa bytes for `{columnName}` did not match expectation.");
}
+ ///
+ /// Asserts that the buffer contains a null decimal field payload for the specified column.
+ ///
+ /// Buffer containing the encoded record(s) to inspect.
+ /// Name of the column whose decimal payload should be null.
+ ///
+ /// Verifies the payload starts with '=' then the DECIMAL type marker, and that both scale and mantissa length are zero.
+ ///
internal static void AssertDecimalNullField(ReadOnlySpan buffer, string columnName)
{
var payload = ExtractDecimalPayload(buffer, columnName);
@@ -61,6 +76,12 @@ internal static void AssertDecimalNullField(ReadOnlySpan buffer, string co
Assert.That(payload[3], Is.EqualTo(0), $"Unexpected mantissa length for `{columnName}`.");
}
+ ///
+ /// Locate and return the payload bytes for a decimal column identified by name.
+ ///
+ /// The byte span containing the encoded record payload to search.
+ /// The column name whose payload prefix ("columnName=") will be located.
+ /// The slice of immediately after the found "columnName=" prefix.
private static ReadOnlySpan ExtractDecimalPayload(ReadOnlySpan buffer, string columnName)
{
var prefix = Encoding.ASCII.GetBytes($"{columnName}=");
diff --git a/src/net-questdb-client-tests/DummyIlpServer.cs b/src/net-questdb-client-tests/DummyIlpServer.cs
index f145836..a108f74 100644
--- a/src/net-questdb-client-tests/DummyIlpServer.cs
+++ b/src/net-questdb-client-tests/DummyIlpServer.cs
@@ -49,6 +49,11 @@ public class DummyIlpServer : IDisposable
private string? _publicKeyY;
private volatile int _totalReceived;
+ ///
+ /// Initializes the dummy ILP server and starts a TCP listener bound to the loopback interface.
+ ///
+ /// TCP port to listen on.
+ /// If true, enables TLS for incoming connections.
public DummyIlpServer(int port, bool tls)
{
_tls = tls;
@@ -69,6 +74,12 @@ public void AcceptAsync()
Task.Run(AcceptConnections);
}
+ ///
+ /// Accepts a single incoming connection, optionally negotiates TLS and performs server authentication, then reads and saves data from the client.
+ ///
+ ///
+ /// Handles one client socket from the listener, wraps the connection with TLS if configured, invokes server-auth when credentials are set, and delegates continuous data receipt to the save routine. Socket errors are caught and the client socket is disposed on exit.
+ ///
private async Task AcceptConnections()
{
Socket? clientSocket = null;
@@ -107,6 +118,11 @@ private X509Certificate GetCertificate()
return X509Certificate.CreateFromCertFile("certificate.pfx");
}
+ ///
+ /// Performs the server-side authentication handshake over the given stream using a challenge-response ECDSA verification.
+ ///
+ /// Stream used for the authentication handshake; the method may write to it and will close it if the requested key id mismatches or the signature verification fails.
+ /// Thrown when the configured public key coordinates are not set.
private async Task RunServerAuth(Stream connection)
{
var receivedLen = await ReceiveUntilEol(connection);
@@ -165,6 +181,11 @@ private static string Pad(string text)
return text + new string('=', padding);
}
+ ///
+ /// Decode a Base64 string that may use URL-safe characters and missing padding into its raw byte representation.
+ ///
+ /// A Base64-encoded string which may use '-' and '_' instead of '+' and '/' and may omit padding.
+ /// The decoded bytes represented by the normalized Base64 input.
public static byte[] FromBase64String(string encodedPrivateKey)
{
var replace = encodedPrivateKey
@@ -173,6 +194,11 @@ public static byte[] FromBase64String(string encodedPrivateKey)
return Convert.FromBase64String(Pad(replace));
}
+ ///
+ /// Reads bytes from the provided stream until a newline ('\n') byte is encountered, storing any bytes that follow the newline from the final read into the server's receive buffer.
+ ///
+ /// The stream to read incoming bytes from.
+ /// The index position of the newline byte within the internal read buffer.
private async Task ReceiveUntilEol(Stream connection)
{
var len = 0;
@@ -223,16 +249,35 @@ private async Task SaveData(Stream connection, Socket socket)
}
}
+ ///
+ /// Produces a human-readable representation of the data received from the connected client.
+ ///
+ /// A formatted string containing the contents of the server's received buffer.
public string GetTextReceived()
{
return PrintBuffer();
}
+ ///
+ /// Gets a copy of all bytes received so far.
+ ///
+ /// A byte array containing the raw bytes received up to this point.
public byte[] GetReceivedBytes()
{
return _received.ToArray();
}
+ ///
+ /// Converts the server's accumulated receive buffer into a human-readable string by decoding UTF-8 text and expanding embedded binary markers into readable representations.
+ ///
+ ///
+ /// The method scans the internal receive buffer for the marker sequence "==". After the marker a type byte determines how the following bytes are interpreted:
+ /// - type 14: formats a multi-dimensional array of doubles as "ARRAY<dim1,dim2,...>[v1,v2,...]".
+ /// - type 16: formats a single double value.
+ /// All bytes outside these marked sections are decoded as UTF-8 text and included verbatim.
+ ///
+ /// A formatted string containing the decoded UTF-8 text and expanded representations of any detected binary markers.
+ /// Thrown when an unknown type marker is encountered after the marker sequence.
public string PrintBuffer()
{
var bytes = _received.ToArray();
@@ -317,6 +362,12 @@ public string PrintBuffer()
return sb.ToString();
}
+ ///
+ /// Enables server-side authentication by configuring the expected key identifier and the ECDSA public key coordinates.
+ ///
+ /// The key identifier expected from the client during authentication.
+ /// Base64-encoded X coordinate of the ECDSA public key (secp256r1).
+ /// Base64-encoded Y coordinate of the ECDSA public key (secp256r1).
public void WithAuth(string keyId, string publicKeyX, string publicKeyY)
{
_keyId = keyId;
diff --git a/src/net-questdb-client-tests/JsonSpecTestRunner.cs b/src/net-questdb-client-tests/JsonSpecTestRunner.cs
index 382a536..0fd46e4 100644
--- a/src/net-questdb-client-tests/JsonSpecTestRunner.cs
+++ b/src/net-questdb-client-tests/JsonSpecTestRunner.cs
@@ -43,6 +43,12 @@ public class JsonSpecTestRunner
private const int HttpPort = 29473;
private static readonly TestCase[]? TestCases = ReadTestCases();
+ ///
+ /// Populate the provided sender with the test case's table, symbols, and columns, then send the prepared row.
+ ///
+ /// The ISender to configure and use for sending the test case row.
+ /// The test case containing table name, symbols, and typed columns to write.
+ /// A task that completes when the prepared row has been sent.
private static async Task ExecuteTestCase(ISender sender, TestCase testCase)
{
sender.Table(testCase.Table);
@@ -87,6 +93,10 @@ private static async Task ExecuteTestCase(ISender sender, TestCase testCase)
await sender.SendAsync();
}
+ ///
+ /// Executes the provided test case by sending its configured table, symbols, and columns to a local TCP listener and asserting the listener's received output against the test case's expected result.
+ ///
+ /// The test case to run; provides table, symbols, columns to send and a Result describing the expected validation (Status, Line, AnyLines, or BinaryBase64).
[TestCaseSource(nameof(TestCases))]
public async Task RunTcp(TestCase testCase)
{
@@ -143,6 +153,10 @@ public async Task RunTcp(TestCase testCase)
}
}
+ ///
+ /// Executes the provided test case by sending data over HTTP to a dummy server using a QuestDB sender and validates the server's response according to the test case result.
+ ///
+ /// The test case describing table, symbols, columns, and expected result (status, line(s), or base64 binary) to execute and validate.
[TestCaseSource(nameof(TestCases))]
public async Task RunHttp(TestCase testCase)
{
@@ -259,6 +273,10 @@ public class TestCase
[JsonPropertyName("columns")] public TestCaseColumn[] Columns { get; set; } = null!;
[JsonPropertyName("result")] public TestCaseResult Result { get; set; } = null!;
+ ///
+ /// Provides the test case name for display and logging.
+ ///
+ /// The TestName of the test case.
public override string ToString()
{
return TestName;
diff --git a/src/net-questdb-client/Buffers/Buffer.cs b/src/net-questdb-client/Buffers/Buffer.cs
index b4d8644..5ea5e2e 100644
--- a/src/net-questdb-client/Buffers/Buffer.cs
+++ b/src/net-questdb-client/Buffers/Buffer.cs
@@ -39,7 +39,15 @@ public static class Buffer
///
///
///
- ///
+ ///
+ /// Creates a concrete IBuffer implementation configured for the specified protocol version.
+ ///
+ /// Size in bytes of each buffer segment.
+ /// Maximum allowed length for names stored in the buffer.
+ /// Maximum total buffer capacity.
+ /// Protocol version that determines which concrete buffer implementation to create.
+ /// An instance corresponding to the specified protocol version.
+ /// Thrown when an unsupported protocol version is provided.
public static IBuffer Create(int bufferSize, int maxNameLen, int maxBufSize, ProtocolVersion version)
{
return version switch
@@ -51,4 +59,4 @@ public static IBuffer Create(int bufferSize, int maxNameLen, int maxBufSize, Pro
_ => throw new NotImplementedException(),
};
}
-}
+}
\ No newline at end of file
diff --git a/src/net-questdb-client/Buffers/BufferV1.cs b/src/net-questdb-client/Buffers/BufferV1.cs
index 922ecd4..7cde1cf 100644
--- a/src/net-questdb-client/Buffers/BufferV1.cs
+++ b/src/net-questdb-client/Buffers/BufferV1.cs
@@ -132,7 +132,13 @@ public void AtNanos(long timestampNanos)
FinishLine();
}
- ///
+ ///
+ /// Resets the buffer to its initial empty state and clears all written data.
+ ///
+ ///
+ /// Clears lengths of all allocated chunks, resets the active chunk and write position,
+ /// resets row and total-length counters, exits any transaction state, and clears the current table and line start markers.
+ ///
public void Clear()
{
_currentBufferIndex = 0;
@@ -161,7 +167,13 @@ public void TrimExcessBuffers()
}
}
- ///
+ ///
+ /// Reverts the current (in-progress) row to its start position, removing any bytes written for that row.
+ ///
+ ///
+ /// Restores the active buffer index, adjusts the total Length and current Position to the saved line start,
+ /// and clears the table-set flag for the cancelled row.
+ ///
public void CancelRow()
{
_currentBufferIndex = _lineStartBufferIndex;
@@ -223,7 +235,15 @@ public void WriteToStream(Stream stream, CancellationToken ct = default)
stream.Flush();
}
- ///
+ ///
+ /// Sets the table name for the current row and encodes it into the buffer, beginning a new line context.
+ ///
+ /// The table name to write; must meet filesystem length limits and protocol naming rules.
+ /// This buffer instance to support fluent calls.
+ ///
+ /// Thrown with ErrorCode.InvalidApiCall if a transaction is active for a different table or if a table has already been set for the current line.
+ /// Thrown with ErrorCode.InvalidName if the provided name violates length or character restrictions.
+ ///
public IBuffer Table(ReadOnlySpan name)
{
GuardFsFileNameLimit(name);
@@ -385,7 +405,11 @@ public void Put(ReadOnlySpan chars)
EncodeUtf8(chars);
}
- ///
+ ///
+ /// Appends the decimal ASCII representation of the specified 64-bit integer to the buffer.
+ ///
+ /// The current buffer instance.
+ /// Thrown when the value is , which cannot be represented by this method; the error contains an inner .
public IBuffer Put(long value)
{
if (value == long.MinValue)
@@ -453,6 +477,10 @@ public IBuffer Put(byte value)
}
+ ///
+ /// Advance the current buffer write position and the overall length by a given number of bytes.
+ ///
+ /// The number of bytes to add to both and .
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void Advance(int by)
{
@@ -460,6 +488,12 @@ internal void Advance(int by)
Length += by;
}
+ ///
+ /// Sets the buffer's current table to the stored table name when a transaction is active and no table has been set for the current row.
+ ///
+ ///
+ /// Has no effect if not within a transaction or if a table has already been set for the current row.
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void SetTableIfAppropriate()
{
@@ -469,6 +503,9 @@ internal void SetTableIfAppropriate()
}
}
+ ///
+ /// Finalizes the current row: terminates it with a newline, increments the completed row counter, resets per-row flags, and enforces the buffer size limit.
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void FinishLine()
{
@@ -533,6 +570,12 @@ internal void EnsureCapacity(int additional)
}
}
+ ///
+ /// Encodes the specified character as UTF-8 into the current chunk and advances the write position by the number of bytes written.
+ ///
+ ///
+ /// If the current chunk has fewer than four bytes free, switches to the next buffer before writing.
+ ///
private void PutUtf8(char c)
{
if (Position + 4 >= Chunk.Length)
@@ -780,7 +823,11 @@ private static void GuardInvalidColumnName(ReadOnlySpan columnName)
/// Check that the file name is not too long.
///
///
- ///
+ ///
+ /// Validates that the UTF-8 encoded byte length of the given name is within the configured maximum.
+ ///
+ /// The name to validate (measured in UTF-8 bytes).
+ /// Thrown with if the name exceeds the maximum allowed byte length.
private void GuardFsFileNameLimit(ReadOnlySpan name)
{
if (Encoding.UTF8.GetBytes(name.ToString()).Length > _maxNameLen)
@@ -790,6 +837,13 @@ private void GuardFsFileNameLimit(ReadOnlySpan name)
}
}
+ ///
+ /// Attempts to add a DECIMAL column to the current row; DECIMAL types are not supported by Protocol Version V1.
+ ///
+ /// The column name to write.
+ /// The decimal value to write, or null to indicate absence.
+ /// The buffer instance for fluent chaining.
+ /// Always thrown with to indicate DECIMAL is unsupported.
public virtual IBuffer Column(ReadOnlySpan name, decimal? value)
{
throw new IngressError(ErrorCode.ProtocolVersionError, "Protocol Version does not support DECIMAL types");
diff --git a/src/net-questdb-client/Buffers/BufferV2.cs b/src/net-questdb-client/Buffers/BufferV2.cs
index 3a3734b..c0c5db2 100644
--- a/src/net-questdb-client/Buffers/BufferV2.cs
+++ b/src/net-questdb-client/Buffers/BufferV2.cs
@@ -90,7 +90,10 @@ private void GuardAgainstNonDoubleTypes(Type t)
}
}
- // ReSharper disable once InconsistentNaming
+ ///
+ /// Writes the provided value into the buffer as little-endian raw bytes and advances the buffer position by the value's size.
+ ///
+ /// A value whose raw bytes will be written into the buffer in little-endian order.
private void PutBinaryLE(T value) where T : struct
{
var size = Marshal.SizeOf();
@@ -110,7 +113,10 @@ private void PutBinaryBE(T value) where T : struct
MemoryMarshal.Cast(slot).Reverse();
}
- // ReSharper disable once InconsistentNaming
+ ///
+ /// Writes a sequence of values into the buffer in little-endian binary form, handling chunk boundaries and advancing the buffer position.
+ ///
+ /// A span of values whose raw bytes will be written as little-endian binary (elements are written whole; partial element writes are not performed).
private void PutBinaryManyLE(ReadOnlySpan value) where T : struct
{
var srcSpan = MemoryMarshal.Cast(value);
@@ -172,13 +178,22 @@ private void PutBinary(T value) where T : struct
}
}
- ///
+ ///
+ /// Writes a column whose value is the provided span of doubles encoded as a binary double array.
+ ///
+ /// The current buffer instance.
public override IBuffer Column(ReadOnlySpan name, ReadOnlySpan value) where T : struct
{
GuardAgainstNonDoubleTypes(typeof(T));
return PutDoubleArray(name, value);
}
+ ///
+ /// Writes a one-dimensional double array column encoded in the buffer's binary double-array format.
+ ///
+ /// The column name.
+ /// A span of elements representing the array; elements must be of type `double`.
+ /// The current buffer instance.
private IBuffer PutDoubleArray(ReadOnlySpan name, ReadOnlySpan value) where T : struct
{
SetTableIfAppropriate();
@@ -190,7 +205,13 @@ private IBuffer PutDoubleArray(ReadOnlySpan name, ReadOnlySpan value
return this;
}
- ///
+ ///
+ /// Add a column with the given name whose value is provided by the specified double array (1D or multi-dimensional).
+ ///
+ /// The column name to write.
+ /// An array of doubles to write. If null the column is omitted. For a 1D array the values are written as a single-dimension double array; for multi-dimensional arrays the rank and each dimension length are written followed by the elements in row-major order.
+ /// This buffer instance.
+ /// Thrown when the array's element type cannot be determined.
public override IBuffer Column(ReadOnlySpan name, Array? value)
{
if (value == null)
diff --git a/src/net-questdb-client/Buffers/BufferV3.cs b/src/net-questdb-client/Buffers/BufferV3.cs
index 3609637..729e66e 100644
--- a/src/net-questdb-client/Buffers/BufferV3.cs
+++ b/src/net-questdb-client/Buffers/BufferV3.cs
@@ -31,7 +31,12 @@ namespace QuestDB.Buffers;
///
public class BufferV3 : BufferV2
{
- ///
+ ///
+ /// Initializes a new instance of BufferV3 with the specified buffer and name length limits.
+ ///
+ /// Initial size of the internal write buffer, in bytes.
+ /// Maximum allowed length for column names, in characters.
+ /// Maximum allowed internal buffer size, in bytes.
public BufferV3(int bufferSize, int maxNameLen, int maxBufSize) : base(bufferSize, maxNameLen, maxBufSize)
{
}
@@ -49,7 +54,12 @@ public BufferV3(int bufferSize, int maxNameLen, int maxBufSize) : base(bufferSiz
// Number of bits scale is shifted by.
private const int ScaleShift = 16;
- ///
+ ///
+ /// Writes a decimal column in QuestDB's binary column format (scale, length, and two's-complement big-endian unscaled value).
+ ///
+ /// Column name to write.
+ /// Nullable decimal value to encode; when null writes zero scale and zero length.
+ /// The buffer instance for call chaining.
public override IBuffer Column(ReadOnlySpan name, decimal? value)
{
// # Binary Format
@@ -120,4 +130,4 @@ public override IBuffer Column(ReadOnlySpan name, decimal? value)
return this;
}
-}
+}
\ No newline at end of file
diff --git a/src/net-questdb-client/Buffers/IBuffer.cs b/src/net-questdb-client/Buffers/IBuffer.cs
index 6074853..6598b74 100644
--- a/src/net-questdb-client/Buffers/IBuffer.cs
+++ b/src/net-questdb-client/Buffers/IBuffer.cs
@@ -228,14 +228,30 @@ public interface IBuffer
///
public IBuffer Column(ReadOnlySpan name, ReadOnlySpan value) where T : struct;
- ///
+ ///
+/// Writes an array column value for the current row.
+///
+/// The column name.
+/// The array to write as the column value, or null to record a NULL value.
+/// The same buffer instance for fluent chaining.
public IBuffer Column(ReadOnlySpan name, Array? value);
- ///
+ ///
+/// Writes a column with the specified name using the provided enumerable of values and shape information.
+///
+/// The column name.
+/// An enumerable of values for the column; elements are of the value type `T`.
+/// An enumerable of integers describing the multidimensional shape/length(s) for the values.
+/// The same instance for call chaining.
public IBuffer Column(ReadOnlySpan name, IEnumerable value, IEnumerable shape) where T : struct;
///
/// Records a DECIMAL column value using the ILP binary decimal layout.
- ///
+ ///
+/// Writes a DECIMAL column with the specified name using the ILP binary decimal layout.
+///
+/// The column name.
+/// The decimal value to write, or `null` to write a NULL column.
+/// The buffer instance for method chaining.
public IBuffer Column(ReadOnlySpan name, decimal? value);
}
\ No newline at end of file
diff --git a/src/net-questdb-client/Senders/AbstractSender.cs b/src/net-questdb-client/Senders/AbstractSender.cs
index 54a3e26..290c96e 100644
--- a/src/net-questdb-client/Senders/AbstractSender.cs
+++ b/src/net-questdb-client/Senders/AbstractSender.cs
@@ -94,7 +94,12 @@ public ISender Column(ReadOnlySpan name, long value)
return this;
}
- ///
+ ///
+ /// Appends an integer-valued column with the specified name to the current buffered row.
+ ///
+ /// The column name.
+ /// The integer value to append for the column.
+ /// The same instance to allow fluent chaining.
public ISender Column(ReadOnlySpan name, int value)
{
Buffer.Column(name, value);
@@ -311,6 +316,9 @@ private void FlushIfNecessary(CancellationToken ct = default)
}
}
+ ///
+ /// Sets to the current UTC time if it has not been initialized.
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void GuardLastFlushNotSet()
{
@@ -320,6 +328,12 @@ private void GuardLastFlushNotSet()
}
}
+ ///
+ /// Adds a nullable decimal column value to the current row in the buffer.
+ ///
+ /// The column name.
+ /// The decimal value to write, or null to emit a null for the column.
+ /// The same instance for fluent chaining.
public ISender Column(ReadOnlySpan name, decimal? value)
{
Buffer.Column(name, value);
diff --git a/src/net-questdb-client/Senders/HttpSender.cs b/src/net-questdb-client/Senders/HttpSender.cs
index d748653..9f50f86 100644
--- a/src/net-questdb-client/Senders/HttpSender.cs
+++ b/src/net-questdb-client/Senders/HttpSender.cs
@@ -57,6 +57,10 @@ internal class HttpSender : AbstractSender
private readonly Func _sendRequestFactory;
private readonly Func _settingRequestFactory;
+ ///
+ /// Initializes a new HttpSender configured according to the provided options.
+ ///
+ /// Configuration for the sender, including connection endpoint, TLS and certificate settings, buffering and protocol parameters, authentication, and timeouts.
public HttpSender(SenderOptions options)
{
_sendRequestFactory = GenerateRequest;
@@ -70,6 +74,17 @@ public HttpSender(string confStr) : this(new SenderOptions(confStr))
{
}
+ ///
+ /// Configure and initialize the SocketsHttpHandler and HttpClient, set TLS and authentication options, determine the Line Protocol version (probing /settings when set to Auto), and create the internal send buffer.
+ ///
+ ///
+ /// - Applies pool and connection settings from Options.
+ /// - When using HTTPS, configures TLS protocols, optional remote-certificate validation override (when tls_verify is unsafe_off), optional custom root CA installation, and optional client certificates.
+ /// - Sets connection timeout, PreAuthenticate, BaseAddress, and disables HttpClient timeout.
+ /// - Adds Basic or Bearer Authorization header when credentials or token are provided.
+ /// - If protocol_version is Auto, probes the server's /settings with a 1-second retry window to select the highest mutually supported protocol up to V3, falling back to V1 on errors or unexpected responses.
+ /// - Initializes the Buffer with init_buf_size, max_name_len, max_buf_size, and the chosen protocol version.
+ ///
private void Build()
{
_handler = new SocketsHttpHandler
@@ -211,7 +226,10 @@ private CancellationTokenSource GenerateRequestCts(CancellationToken ct = defaul
///
/// Creates a new HTTP request with appropriate encoding.
///
- ///
+ ///
+ /// Create an HTTP POST request targeting "/write" with the sender's buffer as the request body.
+ ///
+ /// An configured with the buffer as the request body, Content-Type set to "text/plain" with charset "utf-8", and Content-Length set to the buffer length.
private HttpRequestMessage GenerateRequest()
{
var request = new HttpRequestMessage(HttpMethod.Post, "/write")
@@ -307,7 +325,15 @@ public override void Rollback()
Buffer.Clear();
}
- ///
+ ///
+ /// Sends the current buffer synchronously to the server, applying configured retries and handling server-side errors.
+ ///
+ ///
+ /// Validates that a pending transaction is being committed before sending. If the buffer is empty this method returns immediately.
+ /// On success updates from the server response date; on failure sets to now. The buffer is always cleared after the operation.
+ ///
+ /// Cancellation token to cancel the send operation.
+ /// Thrown with if a transaction is open but not committing, or with for server/transport errors.
public override void Send(CancellationToken ct = default)
{
if (WithinTransaction && !CommittingTransaction)
@@ -361,6 +387,15 @@ public override void Send(CancellationToken ct = default)
}
}
+ ///
+ /// Sends an HTTP request produced by and retries on transient connection or server errors until a successful response is received or elapses.
+ ///
+ /// Cancellation token used to cancel the overall operation and linked to per-request timeouts.
+ /// Factory that produces a fresh for each attempt.
+ /// Maximum duration to keep retrying transient failures; retries are skipped if this is zero.
+ /// The final returned by the server for a successful request.
+ /// Thrown with when a connection could not be established within the allowed retries.
+ /// The caller is responsible for disposing the returned .///
private HttpResponseMessage SendWithRetries(CancellationToken ct, Func requestFactory, TimeSpan retryTimeout)
{
HttpResponseMessage? response = null;
@@ -452,6 +487,11 @@ private void HandleErrorJson(HttpResponseMessage response)
}
}
+ ///
+ /// Read an error payload from the HTTP response (JSON if possible, otherwise raw text) and throw an IngressError containing the server reason and the parsed error details.
+ ///
+ /// The HTTP response containing a JSON or plain-text error body.
+ /// Always thrown with ; the message contains response.ReasonPhrase followed by the deserialized JSON error or the raw response body.
private async Task HandleErrorJsonAsync(HttpResponseMessage response)
{
await using var respStream = await response.Content.ReadAsStreamAsync();
@@ -618,4 +658,4 @@ public override void Dispose()
Buffer.Clear();
Buffer.TrimExcessBuffers();
}
-}
+}
\ No newline at end of file
diff --git a/src/net-questdb-client/Senders/ISender.cs b/src/net-questdb-client/Senders/ISender.cs
index c7227a5..6535519 100644
--- a/src/net-questdb-client/Senders/ISender.cs
+++ b/src/net-questdb-client/Senders/ISender.cs
@@ -124,25 +124,55 @@ public interface ISender : IDisposable
///
/// The name of the column
/// The value for the column
- /// Itself
+ ///
+/// Adds a column (field) with the specified string value to the current row.
+///
+/// The column name.
+/// The column value as a character span.
+/// The sender instance for fluent chaining.
public ISender Column(ReadOnlySpan name, ReadOnlySpan value);
- ///
+ ///
+/// Adds a column with the specified name and 64-bit integer value to the current row.
+///
+/// The column (field) name.
+/// The 64-bit integer value for the column.
+/// The current sender instance for method chaining.
public ISender Column(ReadOnlySpan name, long value);
///
public ISender Column(ReadOnlySpan name, int value);
- ///
+ ///
+/// Adds a boolean field column with the specified name and value to the current row.
+///
+/// The column (field) name.
+/// The boolean value to store in the column.
+/// The same instance to allow fluent chaining.
public ISender Column(ReadOnlySpan name, bool value);
- ///
+ ///
+/// Adds a double-precision field column to the current row.
+///
+/// The column (field) name.
+/// The column's double-precision value.
+/// The same instance for fluent chaining.
public ISender Column(ReadOnlySpan name, double value);
- ///
+ ///
+/// Adds a column (field) with the specified DateTime value to the current row.
+///
+/// The column name.
+/// The DateTime value to add.
+/// The same instance for fluent chaining.
public ISender Column(ReadOnlySpan name, DateTime value);
- ///
+ ///
+/// Adds a column with the specified name and DateTimeOffset value to the current row.
+///
+/// The column name.
+/// The DateTimeOffset value to store for the column (used as a timestamp value).
+/// The sender instance for fluent chaining.
public ISender Column(ReadOnlySpan name, DateTimeOffset value);
///
@@ -211,11 +241,20 @@ public interface ISender : IDisposable
///
/// Clears the sender's buffer.
- ///
+ ///
+/// Clears the sender's internal buffer and resets buffer-related state, removing all pending rows.
+///
public void Clear();
///
+ ///
+/// Adds a column to the current row using a sequence of value-type elements and an explicit multidimensional shape.
+///
+/// The element value type stored in the column.
+/// The column name.
+/// A sequence of elements that form the column's data.
+/// A sequence of integers describing the dimensions of the array representation; dimension lengths must match the number of elements in when multiplied together.
+/// The same instance for fluent chaining.
public ISender Column(ReadOnlySpan name, IEnumerable value, IEnumerable shape) where T : struct;
///
@@ -224,11 +263,21 @@ public interface ISender : IDisposable
///
///
///
- ///
+ ///
+/// Adds a column whose value is provided as a native array; multidimensional (non-jagged) arrays are supported.
+///
+/// The column name.
+/// A native array containing the column data. Multidimensional arrays are treated as shaped data (do not pass jagged arrays).
+/// The sender instance for fluent chaining.
public ISender Column(ReadOnlySpan name, Array value);
///
+ ///
+/// Adds a column with the specified name and a sequence of value-type elements from a span to the current row.
+///
+/// The column (field) name.
+/// A contiguous sequence of value-type elements representing the column data.
+/// The same instance to allow fluent chaining.
public ISender Column(ReadOnlySpan name, ReadOnlySpan value) where T : struct;
///
@@ -236,13 +285,24 @@ public interface ISender : IDisposable
///
/// The name of the column
/// The value for the column
- /// Itself
+ ///
+ /// Adds a column with the specified string value to the current row.
+ ///
+ /// The column name.
+ /// The column's string value; may be null.
+ /// The same sender instance for fluent chaining.
public ISender Column(ReadOnlySpan name, string? value)
{
return Column(name, value.AsSpan());
}
- ///
+ ///
+ /// Adds a column whose value is a sequence of value-type elements with the given multidimensional shape when both and are provided; no action is taken if either is null.
+ ///
+ /// The column name.
+ /// The sequence of elements for the column, or null to skip adding the column.
+ /// The dimensions describing the array shape, or null to skip adding the column.
+ /// This sender instance for fluent chaining.
public ISender NullableColumn(ReadOnlySpan name, IEnumerable? value, IEnumerable? shape)
where T : struct
{
@@ -254,7 +314,12 @@ public ISender NullableColumn(ReadOnlySpan name, IEnumerable? value,
return this;
}
- ///
+ ///
+ /// Adds a column using a native array value when the provided array is non-null.
+ ///
+ /// The column name.
+ /// The array to use as the column value; if null, no column is added. Multidimensional arrays are supported (non-jagged).
+ /// The same instance for fluent chaining.
public ISender NullableColumn(ReadOnlySpan name, Array? value)
{
if (value != null)
@@ -265,7 +330,12 @@ public ISender NullableColumn(ReadOnlySpan name, Array? value)
return this;
}
- ///
+ ///
+ /// Adds a string column with the given name when the provided value is not null.
+ ///
+ /// The column name.
+ /// The string value to add; if null, no column is added.
+ /// The current sender instance for fluent chaining.
public ISender NullableColumn(ReadOnlySpan name, string? value)
{
if (value != null)
@@ -276,7 +346,12 @@ public ISender NullableColumn(ReadOnlySpan name, string? value)
return this;
}
- ///
+ ///
+ /// Adds a long column with the specified name when the provided nullable value has a value; does nothing when the value is null.
+ ///
+ /// The column name.
+ /// The nullable long value to add as a column; if null the sender is unchanged.
+ /// The current sender instance for fluent chaining.
public ISender NullableColumn(ReadOnlySpan name, long? value)
{
if (value != null)
@@ -287,7 +362,12 @@ public ISender NullableColumn(ReadOnlySpan name, long? value)
return this;
}
- ///
+ ///
+ /// Adds a boolean column with the given name when a value is provided; does nothing if the value is null.
+ ///
+ /// The column name.
+ /// The nullable boolean value to add as a column.
+ /// The current sender instance to allow fluent chaining.
public ISender NullableColumn(ReadOnlySpan name, bool? value)
{
if (value != null)
@@ -298,7 +378,12 @@ public ISender NullableColumn(ReadOnlySpan name, bool? value)
return this;
}
- ///
+ ///
+ /// Adds a column with the given double value when the value is non-null; otherwise no column is added and the sender is unchanged.
+ ///
+ /// The column name.
+ /// The column value; if non-null, the value is written as a double field.
+ /// The sender instance after the operation.
public ISender NullableColumn(ReadOnlySpan name, double? value)
{
if (value != null)
@@ -309,7 +394,12 @@ public ISender NullableColumn(ReadOnlySpan name, double? value)
return this;
}
- ///
+ ///
+ /// Adds a DateTime column with the specified name when a value is provided; no action is taken if the value is null.
+ ///
+ /// The column name.
+ /// The nullable DateTime value to add as a column.
+ /// The current instance for fluent chaining; unchanged if is null.
public ISender NullableColumn(ReadOnlySpan name, DateTime? value)
{
if (value != null)
@@ -320,7 +410,12 @@ public ISender NullableColumn(ReadOnlySpan name, DateTime? value)
return this;
}
- ///
+ ///
+ /// Adds a column with the given name and DateTimeOffset value when a value is provided; does nothing if the value is null.
+ ///
+ /// The column name.
+ /// The DateTimeOffset value to add; if null the column is not added.
+ /// The same instance to allow fluent chaining.
public ISender NullableColumn(ReadOnlySpan name, DateTimeOffset? value)
{
if (value != null)
@@ -333,6 +428,11 @@ public ISender NullableColumn(ReadOnlySpan name, DateTimeOffset? value)
///
/// Adds a DECIMAL column in the binary format.
- ///
+ ///
+/// Adds a decimal column in binary format to the current row.
+///
+/// The column name.
+/// The decimal value to add; may be null to represent a NULL field.
+/// The sender instance for fluent call chaining.
public ISender Column(ReadOnlySpan name, decimal? value);
}
\ No newline at end of file
From 079195efc886d7cba3dbd369e468af0e88d3db15 Mon Sep 17 00:00:00 2001
From: Raphael DALMON
Date: Fri, 17 Oct 2025 17:01:48 +0200
Subject: [PATCH 2/2] refactor: improve XML documentation for Buffer and
IBuffer interfaces
---
src/net-questdb-client/Buffers/Buffer.cs | 8 --
src/net-questdb-client/Buffers/IBuffer.cs | 32 ++---
src/net-questdb-client/Senders/HttpSender.cs | 43 +++----
src/net-questdb-client/Senders/ISender.cs | 127 ++++++++-----------
4 files changed, 90 insertions(+), 120 deletions(-)
diff --git a/src/net-questdb-client/Buffers/Buffer.cs b/src/net-questdb-client/Buffers/Buffer.cs
index 5ea5e2e..9c17b04 100644
--- a/src/net-questdb-client/Buffers/Buffer.cs
+++ b/src/net-questdb-client/Buffers/Buffer.cs
@@ -31,14 +31,6 @@ namespace QuestDB.Buffers;
///
public static class Buffer
{
- ///
- /// Creates an IBuffer instance, based on the provided protocol version.
- ///
- ///
- ///
- ///
- ///
- ///
///
/// Creates a concrete IBuffer implementation configured for the specified protocol version.
///
diff --git a/src/net-questdb-client/Buffers/IBuffer.cs b/src/net-questdb-client/Buffers/IBuffer.cs
index 6598b74..628128a 100644
--- a/src/net-questdb-client/Buffers/IBuffer.cs
+++ b/src/net-questdb-client/Buffers/IBuffer.cs
@@ -229,29 +229,29 @@ public interface IBuffer
public IBuffer Column(ReadOnlySpan name, ReadOnlySpan value) where T : struct;
///
-/// Writes an array column value for the current row.
-///
-/// The column name.
-/// The array to write as the column value, or null to record a NULL value.
-/// The same buffer instance for fluent chaining.
+ /// Writes an array column value for the current row.
+ ///
+ /// The column name.
+ /// The array to write as the column value, or null to record a NULL value.
+ /// The same buffer instance for fluent chaining.
public IBuffer Column(ReadOnlySpan name, Array? value);
///
-/// Writes a column with the specified name using the provided enumerable of values and shape information.
-///
-/// The column name.
-/// An enumerable of values for the column; elements are of the value type `T`.
-/// An enumerable of integers describing the multidimensional shape/length(s) for the values.
-/// The same instance for call chaining.
+ /// Writes a column with the specified name using the provided enumerable of values and shape information.
+ ///
+ /// The column name.
+ /// An enumerable of values for the column; elements are of the value type `T`.
+ /// An enumerable of integers describing the multidimensional shape/length(s) for the values.
+ /// The same instance for call chaining.
public IBuffer Column(ReadOnlySpan name, IEnumerable value, IEnumerable shape) where T : struct;
///
/// Records a DECIMAL column value using the ILP binary decimal layout.
///
-/// Writes a DECIMAL column with the specified name using the ILP binary decimal layout.
-///
-/// The column name.
-/// The decimal value to write, or `null` to write a NULL column.
-/// The buffer instance for method chaining.
+ /// Writes a DECIMAL column with the specified name using the ILP binary decimal layout.
+ ///
+ /// The column name.
+ /// The decimal value to write, or `null` to write a NULL column.
+ /// The buffer instance for method chaining.
public IBuffer Column(ReadOnlySpan name, decimal? value);
}
\ No newline at end of file
diff --git a/src/net-questdb-client/Senders/HttpSender.cs b/src/net-questdb-client/Senders/HttpSender.cs
index 9f50f86..3cb644a 100644
--- a/src/net-questdb-client/Senders/HttpSender.cs
+++ b/src/net-questdb-client/Senders/HttpSender.cs
@@ -149,9 +149,9 @@ private void Build()
{
_client.DefaultRequestHeaders.Authorization
= new AuthenticationHeaderValue("Basic",
- Convert.ToBase64String(
- Encoding.ASCII.GetBytes(
- $"{Options.username}:{Options.password}")));
+ Convert.ToBase64String(
+ Encoding.ASCII.GetBytes(
+ $"{Options.username}:{Options.password}")));
}
else if (!string.IsNullOrEmpty(Options.token))
{
@@ -223,9 +223,6 @@ private CancellationTokenSource GenerateRequestCts(CancellationToken ct = defaul
return cts;
}
- ///
- /// Creates a new HTTP request with appropriate encoding.
- ///
///
/// Create an HTTP POST request targeting "/write" with the sender's buffer as the request body.
///
@@ -233,7 +230,7 @@ private CancellationTokenSource GenerateRequestCts(CancellationToken ct = defaul
private HttpRequestMessage GenerateRequest()
{
var request = new HttpRequestMessage(HttpMethod.Post, "/write")
- { Content = new BufferStreamContent(Buffer), };
+ { Content = new BufferStreamContent(Buffer), };
request.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain") { CharSet = "utf-8", };
request.Content.Headers.ContentLength = Buffer.Length;
return request;
@@ -260,13 +257,13 @@ public override ISender Transaction(ReadOnlySpan tableName)
if (WithinTransaction)
{
throw new IngressError(ErrorCode.InvalidApiCall,
- "Cannot start another transaction - only one allowed at a time.");
+ "Cannot start another transaction - only one allowed at a time.");
}
if (Length > 0)
{
throw new IngressError(ErrorCode.InvalidApiCall,
- "Buffer must be clear before you can start a transaction.");
+ "Buffer must be clear before you can start a transaction.");
}
Buffer.Transaction(tableName);
@@ -274,7 +271,6 @@ public override ISender Transaction(ReadOnlySpan tableName)
}
///
- /// />
public override void Commit(CancellationToken ct = default)
{
try
@@ -396,7 +392,8 @@ public override void Send(CancellationToken ct = default)
/// The final returned by the server for a successful request.
/// Thrown with when a connection could not be established within the allowed retries.
/// The caller is responsible for disposing the returned .///
- private HttpResponseMessage SendWithRetries(CancellationToken ct, Func requestFactory, TimeSpan retryTimeout)
+ private HttpResponseMessage SendWithRetries(CancellationToken ct, Func requestFactory,
+ TimeSpan retryTimeout)
{
HttpResponseMessage? response = null;
CancellationTokenSource cts = GenerateRequestCts(ct);
@@ -414,9 +411,9 @@ private HttpResponseMessage SendWithRetries(CancellationToken ct, Func TimeSpan.Zero)
- // retry if appropriate - error that's retriable, and retries are enabled
+ // retry if appropriate - error that's retriable, and retries are enabled
{
- if (response == null // if it was a cannot correct error
+ if (response == null // if it was a cannot correct error
|| (!response.IsSuccessStatusCode // or some other http error
&& IsRetriableError(response.StatusCode)))
{
@@ -426,9 +423,9 @@ private HttpResponseMessage SendWithRetries(CancellationToken ct, Func TimeSpan.Zero)
{
- if (response == null // if it was a cannot correct error
+ if (response == null // if it was a cannot correct error
|| (!response.IsSuccessStatusCode // or some other http error
&& IsRetriableError(response.StatusCode)))
{
@@ -552,9 +549,9 @@ public override async Task SendAsync(CancellationToken ct = default)
while (retryTimer.Elapsed < Options.retry_timeout // whilst we can still retry
&& (
- response == null || // either we can't connect
- (!response.IsSuccessStatusCode && // or we have another http error
- IsRetriableError(response.StatusCode)))
+ response == null || // either we can't connect
+ (!response.IsSuccessStatusCode && // or we have another http error
+ IsRetriableError(response.StatusCode)))
)
{
retryInterval = TimeSpan.FromMilliseconds(Math.Min(retryInterval.TotalMilliseconds * 2, 1000));
@@ -574,7 +571,7 @@ public override async Task SendAsync(CancellationToken ct = default)
try
{
response = await _client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead,
- cts.Token);
+ cts.Token);
}
catch (HttpRequestException)
{
@@ -588,7 +585,7 @@ public override async Task SendAsync(CancellationToken ct = default)
if (response == null)
{
throw new IngressError(ErrorCode.ServerFlushError,
- $"Cannot connect to `{Options.Host}:{Options.Port}`");
+ $"Cannot connect to `{Options.Host}:{Options.Port}`");
}
// return if ok
diff --git a/src/net-questdb-client/Senders/ISender.cs b/src/net-questdb-client/Senders/ISender.cs
index 6535519..5735f13 100644
--- a/src/net-questdb-client/Senders/ISender.cs
+++ b/src/net-questdb-client/Senders/ISender.cs
@@ -22,12 +22,8 @@
*
******************************************************************************/
-// ReSharper disable CommentTypo
-
using QuestDB.Utils;
-// ReSharper disable InconsistentNaming
-
namespace QuestDB.Senders;
///
@@ -46,7 +42,7 @@ public interface ISender : IDisposable
public int RowCount { get; }
///
- /// Represents whether or not the Sender is in a transactional state.
+ /// Represents whether the Sender is in a transactional state.
///
public bool WithinTransaction { get; }
@@ -125,54 +121,54 @@ public interface ISender : IDisposable
/// The name of the column
/// The value for the column
///
-/// Adds a column (field) with the specified string value to the current row.
-///
-/// The column name.
-/// The column value as a character span.
-/// The sender instance for fluent chaining.
+ /// Adds a column (field) with the specified string value to the current row.
+ ///
+ /// The column name.
+ /// The column value as a character span.
+ /// The sender instance for fluent chaining.
public ISender Column(ReadOnlySpan name, ReadOnlySpan value);
///
-/// Adds a column with the specified name and 64-bit integer value to the current row.
-///
-/// The column (field) name.
-/// The 64-bit integer value for the column.
-/// The current sender instance for method chaining.
+ /// Adds a column with the specified name and 64-bit integer value to the current row.
+ ///
+ /// The column (field) name.
+ /// The 64-bit integer value for the column.
+ /// The current sender instance for method chaining.
public ISender Column(ReadOnlySpan name, long value);
///
public ISender Column(ReadOnlySpan name, int value);
///
-/// Adds a boolean field column with the specified name and value to the current row.
-///
-/// The column (field) name.
-/// The boolean value to store in the column.
-/// The same instance to allow fluent chaining.
+ /// Adds a boolean field column with the specified name and value to the current row.
+ ///
+ /// The column (field) name.
+ /// The boolean value to store in the column.
+ /// The same instance to allow fluent chaining.
public ISender Column(ReadOnlySpan name, bool value);
///
-/// Adds a double-precision field column to the current row.
-///
-/// The column (field) name.
-/// The column's double-precision value.
-/// The same instance for fluent chaining.
+ /// Adds a double-precision field column to the current row.
+ ///
+ /// The column (field) name.
+ /// The column's double-precision value.
+ /// The same instance for fluent chaining.
public ISender Column(ReadOnlySpan name, double value);
///
-/// Adds a column (field) with the specified DateTime value to the current row.
-///
-/// The column name.
-/// The DateTime value to add.
-/// The same instance for fluent chaining.
+ /// Adds a column (field) with the specified DateTime value to the current row.
+ ///
+ /// The column name.
+ /// The DateTime value to add.
+ /// The same instance for fluent chaining.
public ISender Column(ReadOnlySpan name, DateTime value);
///
-/// Adds a column with the specified name and DateTimeOffset value to the current row.
-///
-/// The column name.
-/// The DateTimeOffset value to store for the column (used as a timestamp value).
-/// The sender instance for fluent chaining.
+ /// Adds a column with the specified name and DateTimeOffset value to the current row.
+ ///
+ /// The column name.
+ /// The DateTimeOffset value to store for the column (used as a timestamp value).
+ /// The sender instance for fluent chaining.
public ISender Column(ReadOnlySpan name, DateTimeOffset value);
///
@@ -242,49 +238,36 @@ public interface ISender : IDisposable
///
/// Clears the sender's buffer.
///
-/// Clears the sender's internal buffer and resets buffer-related state, removing all pending rows.
-///
+ /// Clears the sender's internal buffer and resets buffer-related state, removing all pending rows.
+ ///
public void Clear();
- ///
-/// Adds a column to the current row using a sequence of value-type elements and an explicit multidimensional shape.
-///
-/// The element value type stored in the column.
-/// The column name.
-/// A sequence of elements that form the column's data.
-/// A sequence of integers describing the dimensions of the array representation; dimension lengths must match the number of elements in when multiplied together.
-/// The same instance for fluent chaining.
+ /// Adds a column to the current row using a sequence of value-type elements and an explicit multidimensional shape.
+ ///
+ /// The element value type stored in the column.
+ /// The column name.
+ /// A sequence of elements that form the column's data.
+ /// A sequence of integers describing the dimensions of the array representation; dimension lengths must match the number of elements in when multiplied together.
+ /// The same instance for fluent chaining.
public ISender Column(ReadOnlySpan name, IEnumerable value, IEnumerable shape) where T : struct;
///
- /// Adds an ARRAY to the current row.
- /// Arrays are n-dimensional non-jagged arrays.
+ /// Adds a column whose value is provided as a native array; multidimensional (non-jagged) arrays are supported.
///
- ///
- ///
- ///
-/// Adds a column whose value is provided as a native array; multidimensional (non-jagged) arrays are supported.
-///
-/// The column name.
-/// A native array containing the column data. Multidimensional arrays are treated as shaped data (do not pass jagged arrays).
-/// The sender instance for fluent chaining.
+ /// The column name.
+ /// A native array containing the column data. Multidimensional arrays are treated as shaped data (do not pass jagged arrays).
+ /// The sender instance for fluent chaining.
public ISender Column(ReadOnlySpan name, Array value);
- ///
-/// Adds a column with the specified name and a sequence of value-type elements from a span to the current row.
-///
-/// The column (field) name.
-/// A contiguous sequence of value-type elements representing the column data.
-/// The same instance to allow fluent chaining.
+ /// Adds a column with the specified name and a sequence of value-type elements from a span to the current row.
+ ///
+ /// The column (field) name.
+ /// A contiguous sequence of value-type elements representing the column data.
+ /// The same instance to allow fluent chaining.
public ISender Column(ReadOnlySpan name, ReadOnlySpan value) where T : struct;
- ///
- /// Adds a column (field) to the current row.
- ///
- /// The name of the column
- /// The value for the column
///
/// Adds a column with the specified string value to the current row.
///
@@ -427,12 +410,10 @@ public ISender NullableColumn(ReadOnlySpan name, DateTimeOffset? value)
}
///
- /// Adds a DECIMAL column in the binary format.
- ///
-/// Adds a decimal column in binary format to the current row.
-///
-/// The column name.
-/// The decimal value to add; may be null to represent a NULL field.
-/// The sender instance for fluent call chaining.
+ /// Adds a decimal column in binary format to the current row.
+ ///
+ /// The column name.
+ /// The decimal value to add; may be null to represent a NULL field.
+ /// The sender instance for fluent call chaining.
public ISender Column(ReadOnlySpan name, decimal? value);
}
\ No newline at end of file