diff --git a/src/DataStax.AstraDB.DataApi/Collections/Collection.cs b/src/DataStax.AstraDB.DataApi/Collections/Collection.cs index d1f2a04..a1837fc 100644 --- a/src/DataStax.AstraDB.DataApi/Collections/Collection.cs +++ b/src/DataStax.AstraDB.DataApi/Collections/Collection.cs @@ -134,39 +134,21 @@ private async Task> InsertOneAsync(T document, Co } /// - /// Synchronous version of + /// Synchronous version of /// - /// - public CollectionInsertManyResult InsertMany(List documents) + /// + public CollectionInsertManyResult InsertMany(IEnumerable documents) { - return InsertMany(documents, null, null); + return InsertMany(documents, null); } /// - /// Synchronous version of + /// Synchronous version of /// - /// - public CollectionInsertManyResult InsertMany(List documents, InsertManyOptions insertOptions) + /// + public CollectionInsertManyResult InsertMany(IEnumerable documents, InsertManyOptions insertOptions) { - return InsertMany(documents, insertOptions, null); - } - - /// - /// Synchronous version of - /// - /// - public CollectionInsertManyResult InsertMany(List documents, CommandOptions commandOptions) - { - return InsertMany(documents, null, commandOptions); - } - - /// - /// Synchronous version of - /// - /// - public CollectionInsertManyResult InsertMany(List documents, InsertManyOptions insertOptions, CommandOptions commandOptions) - { - return InsertManyAsync(documents, insertOptions, commandOptions, runSynchronously: true).ResultSync(); + return InsertManyAsync(documents, insertOptions, runSynchronously: true).ResultSync(); } /// @@ -174,44 +156,30 @@ public CollectionInsertManyResult InsertMany(List documents, InsertManyO /// /// The list of documents to insert. /// - /// Thrown if the documents list is null or empty. - /// Thrown if an error occurs during the bulk operation, + /// + /// If you need to control concurrency, chunk size, whether the insert is ordered or not, or other options, use the overload. + /// + /// Thrown if an error occurs during the bulk operation, /// with partial results returned in the property. - public Task> InsertManyAsync(List documents) - { - return InsertManyAsync(documents, new CommandOptions()); - } - - /// - /// - /// Allows specifying whether the documents should be inserted in order as well as the chunk size. - public Task> InsertManyAsync(List documents, InsertManyOptions insertOptions) + public Task> InsertManyAsync(IEnumerable documents) { - return InsertManyAsync(documents, insertOptions, null, runSynchronously: false); + return InsertManyAsync(documents, null); } - /// - /// - /// - public Task> InsertManyAsync(List documents, CommandOptions commandOptions) - { - return InsertManyAsync(documents, null, commandOptions, runSynchronously: false); - } - - /// - /// - /// - /// - public Task> InsertManyAsync(List documents, InsertManyOptions insertOptions, CommandOptions commandOptions) + /// + /// The list of documents to insert. + /// Allows specifying the insertion chunk size, ordered/unordered mode, concurrency, as well as other generic command-execution options. + public Task> InsertManyAsync(IEnumerable documents, InsertManyOptions insertOptions) { - return InsertManyAsync(documents, insertOptions, commandOptions, runSynchronously: false); + return InsertManyAsync(documents, insertOptions, runSynchronously: false); } - private async Task> InsertManyAsync(List documents, InsertManyOptions insertOptions, CommandOptions commandOptions, bool runSynchronously) + private async Task> InsertManyAsync(IEnumerable documents, InsertManyOptions insertOptions, bool runSynchronously) { - Guard.NotNullOrEmpty(documents, nameof(documents)); + Guard.NotNull(documents, nameof(documents)); if (insertOptions == null) insertOptions = new InsertManyOptions(); + var commandOptions = insertOptions.CommandOptions(); if (insertOptions.Concurrency > 1 && insertOptions.Ordered) { throw new ArgumentException("Cannot run ordered insert_many concurrently."); @@ -673,7 +641,8 @@ public CollectionFindCursor Find(CollectionFindManyOptions findOptions) public CollectionFindCursor Find(CollectionFilter filter, CollectionFindManyOptions findOptions) { findOptions ??= new CollectionFindManyOptions(); - return new(findOptions.WithFilterParam(filter), null, RunFindManyAsync); + var commandOptions = findOptions.CommandOptions(); + return new(findOptions.WithFilterParam(filter), commandOptions, RunFindManyAsync); } /// @@ -706,23 +675,27 @@ public CollectionFindCursor Find(CollectionFindManyOptions< return Find(null, findOptions); } - /// - /// - /// + /// + /// + /// The Find alternatives that accept a TResult type parameter allow for deserializing the document as a different type + /// (most commonly used when using projection to return a subset of fields) + /// public CollectionFindCursor Find(CollectionFilter filter, CollectionFindManyOptions findOptions) where TResult : class { findOptions ??= new CollectionFindManyOptions(); - return new(findOptions.WithFilterParam(filter), null, RunFindManyAsync); + var commandOptions = findOptions.CommandOptions(); + return new(findOptions.WithFilterParam(filter), commandOptions, RunFindManyAsync); } internal async Task> RunFindManyAsync(CollectionFindCursor cursor, string nextPageState, bool runSynchronously) where TResult : class { var options = cursor.FindOptions.Clone(); options.PageState = nextPageState; - - var command = CreateCommand("find").WithPayload(options).AddCommandOptions(cursor.CommandOptions); + + var payloadOptions = options.PayloadOptions(); + var command = CreateCommand("find").WithPayload(payloadOptions).AddCommandOptions(cursor.CommandOptions); var response = await command.RunAsyncReturnDocumentData, TResult, FindStatusResult>(runSynchronously).ConfigureAwait(false); - + return new FindPage( response.Data.NextPageState, response.Data.Items, diff --git a/src/DataStax.AstraDB.DataApi/Core/CommandOptions.cs b/src/DataStax.AstraDB.DataApi/Core/CommandOptions.cs index ccdc791..30bf0a1 100644 --- a/src/DataStax.AstraDB.DataApi/Core/CommandOptions.cs +++ b/src/DataStax.AstraDB.DataApi/Core/CommandOptions.cs @@ -48,6 +48,7 @@ public class CommandOptions /// /// The token to use for authentication /// + [JsonIgnore] public string Token { get; set; } /// @@ -55,6 +56,7 @@ public class CommandOptions /// /// Defaults to /// + [JsonIgnore] public RunMode? RunMode { get; set; } /// @@ -62,6 +64,7 @@ public class CommandOptions /// /// Defaults to /// + [JsonIgnore] public DataAPIDestination? Destination { get; set; } /// @@ -69,6 +72,7 @@ public class CommandOptions /// /// Defaults to HttpVersion: 2.0, FollowRedirects: true /// + [JsonIgnore] public HttpClientOptions HttpClientOptions { get; set; } /// @@ -77,6 +81,7 @@ public class CommandOptions /// /// See for information. /// + [JsonIgnore] public TimeoutOptions TimeoutOptions { get; set; } = new TimeoutOptions(); /// @@ -84,6 +89,7 @@ public class CommandOptions /// /// Defaults to /// + [JsonIgnore] public APIVersion? APIVersion { get; set; } internal string APIUrlBase @@ -101,6 +107,7 @@ internal string APIUrlBase /// /// An optional CancellationToken to interrupt asynchronous operations /// + [JsonIgnore] public CancellationToken? CancellationToken { get; set; } internal CancellationToken? BulkOperationCancellationToken { get; set; } diff --git a/src/DataStax.AstraDB.DataApi/Core/HttpClientOptions.cs b/src/DataStax.AstraDB.DataApi/Core/HttpClientOptions.cs index ba6e4d5..ff4f946 100644 --- a/src/DataStax.AstraDB.DataApi/Core/HttpClientOptions.cs +++ b/src/DataStax.AstraDB.DataApi/Core/HttpClientOptions.cs @@ -32,4 +32,14 @@ public class HttpClientOptions /// Whether the HTTP client should follow redirects or not. /// public bool FollowRedirects { get; set; } = true; -} \ No newline at end of file + + internal HttpClientOptions Clone() + { + return new HttpClientOptions + { + HttpVersion = HttpVersion, + FollowRedirects = FollowRedirects, + }; + } + +} diff --git a/src/DataStax.AstraDB.DataApi/Core/InsertManyOptions.cs b/src/DataStax.AstraDB.DataApi/Core/InsertManyOptions.cs index 8840257..ae10dc0 100644 --- a/src/DataStax.AstraDB.DataApi/Core/InsertManyOptions.cs +++ b/src/DataStax.AstraDB.DataApi/Core/InsertManyOptions.cs @@ -19,17 +19,17 @@ namespace DataStax.AstraDB.DataApi.Core; /// /// Options for inserting multiple documents into a collection. /// -public class InsertManyOptions +public class InsertManyOptions : CommandOptions { /// /// Default batch size. /// - public const int DefaultChunkSize = 100; + public const int DefaultChunkSize = 50; /// - /// Maximum concurrency. + /// Default concurrency for unordered insertions. /// - public const int MaxConcurrency = int.MaxValue; + public const int DefaultConcurrency = 20; private bool _Ordered = false; /// @@ -48,10 +48,42 @@ public bool Ordered /// The number of parallel processes to use while inserting documents. /// Must be set to 1 for ordered inserts. /// - public int Concurrency { get; set; } = MaxConcurrency; + public int Concurrency { get; set; } = DefaultConcurrency; /// /// The number of documents to insert in each batch. /// public int ChunkSize { get; set; } = DefaultChunkSize; + + internal CommandOptions CommandOptions() + { + return new CommandOptions { + Token = Token, + RunMode = RunMode, + Destination = Destination, + HttpClientOptions = HttpClientOptions != null ? HttpClientOptions.Clone() : null, + TimeoutOptions = TimeoutOptions != null ? TimeoutOptions.Clone() : null, + APIVersion = APIVersion, + CancellationToken = CancellationToken + }; + } + + internal InsertManyOptions Clone() + { + return new InsertManyOptions + { + Ordered = Ordered, + Concurrency = Concurrency, + ChunkSize = ChunkSize, + // CommandOptions properties: + Token = Token, + RunMode = RunMode, + Destination = Destination, + HttpClientOptions = HttpClientOptions != null ? HttpClientOptions.Clone() : null, + TimeoutOptions = TimeoutOptions != null ? TimeoutOptions.Clone() : null, + APIVersion = APIVersion, + CancellationToken = CancellationToken + }; + } + } diff --git a/src/DataStax.AstraDB.DataApi/Core/Query/CollectionFindManyOptions.cs b/src/DataStax.AstraDB.DataApi/Core/Query/CollectionFindManyOptions.cs index 1ca338d..20a8e89 100644 --- a/src/DataStax.AstraDB.DataApi/Core/Query/CollectionFindManyOptions.cs +++ b/src/DataStax.AstraDB.DataApi/Core/Query/CollectionFindManyOptions.cs @@ -25,7 +25,7 @@ namespace DataStax.AstraDB.DataApi.Core.Query; /// Options for finding multiple documents in a collection. /// /// The type of the document. -public class CollectionFindManyOptions : IFindManyOptions> +public class CollectionFindManyOptions : CommandOptions, IFindManyOptions> { /// The projection to apply to the results. [JsonIgnore] @@ -55,14 +55,16 @@ public class CollectionFindManyOptions : IFindManyOptions + /// Whether to include the sort vector in the result or not + /// [JsonIgnore] - internal bool? IncludeSortVector { get; set; } + public bool? IncludeSortVector { get; set; } bool? IFindManyOptions>.IncludeSortVector { get => IncludeSortVector; set => IncludeSortVector = value; } internal Filter Filter { get; set; } - [JsonIgnore] internal string PageState { get; set; } string IFindOptions>.PageState { get => PageState; set => PageState = value; } @@ -114,6 +116,33 @@ internal Dictionary Options } } + IFindManyOptions> IFindManyOptions>.PayloadOptions() + { + return new CollectionFindManyOptions { + Filter = Filter, + InitialPageState = InitialPageState, + Skip = Skip, + Limit = Limit, + IncludeSortVector = IncludeSortVector, + IncludeSimilarity = IncludeSimilarity, + Projection = Projection != null ? Projection.Clone() : null, + Sort = Sort != null ? Sort.Clone() : null, + }; + } + + internal CommandOptions CommandOptions() + { + return new CommandOptions { + Token = Token, + RunMode = RunMode, + Destination = Destination, + HttpClientOptions = HttpClientOptions != null ? HttpClientOptions.Clone() : null, + TimeoutOptions = TimeoutOptions != null ? TimeoutOptions.Clone() : null, + APIVersion = APIVersion, + CancellationToken = CancellationToken + }; + } + internal CollectionFindManyOptions Clone() { return new CollectionFindManyOptions @@ -125,7 +154,15 @@ internal CollectionFindManyOptions Clone() IncludeSortVector = IncludeSortVector, IncludeSimilarity = IncludeSimilarity, Projection = Projection != null ? Projection.Clone() : null, - Sort = Sort != null ? Sort.Clone() : null + Sort = Sort != null ? Sort.Clone() : null, + // CommandOptions properties: + Token = Token, + RunMode = RunMode, + Destination = Destination, + HttpClientOptions = HttpClientOptions != null ? HttpClientOptions.Clone() : null, + TimeoutOptions = TimeoutOptions != null ? TimeoutOptions.Clone() : null, + APIVersion = APIVersion, + CancellationToken = CancellationToken }; } diff --git a/src/DataStax.AstraDB.DataApi/Core/Query/IFindManyOptions.cs b/src/DataStax.AstraDB.DataApi/Core/Query/IFindManyOptions.cs index a635330..7122a36 100644 --- a/src/DataStax.AstraDB.DataApi/Core/Query/IFindManyOptions.cs +++ b/src/DataStax.AstraDB.DataApi/Core/Query/IFindManyOptions.cs @@ -40,4 +40,6 @@ internal interface IFindManyOptions : IFindOptions internal bool? IncludeSortVector { get; set; } internal IFindManyOptions Clone(); + + internal IFindManyOptions PayloadOptions(); } diff --git a/src/DataStax.AstraDB.DataApi/Core/Query/TableFindManyOptions.cs b/src/DataStax.AstraDB.DataApi/Core/Query/TableFindManyOptions.cs index 156d03e..c089e93 100644 --- a/src/DataStax.AstraDB.DataApi/Core/Query/TableFindManyOptions.cs +++ b/src/DataStax.AstraDB.DataApi/Core/Query/TableFindManyOptions.cs @@ -25,7 +25,7 @@ namespace DataStax.AstraDB.DataApi.Core.Query; /// A set of options to be used when finding rows in a table. /// /// -public class TableFindManyOptions : IFindManyOptions> +public class TableFindManyOptions : CommandOptions, IFindManyOptions> { /// The projection to apply to the results. [JsonIgnore] @@ -86,7 +86,7 @@ public class TableFindManyOptions : IFindManyOptions> /// /// [JsonIgnore] - internal bool? IncludeSortVector { get; set; } + public bool? IncludeSortVector { get; set; } bool? IFindManyOptions>.IncludeSortVector { get => IncludeSortVector; set => IncludeSortVector = value; } @@ -144,6 +144,33 @@ internal Dictionary Options } } + IFindManyOptions> IFindManyOptions>.PayloadOptions() + { + return new TableFindManyOptions { + Filter = Filter, + InitialPageState = InitialPageState, + Skip = Skip, + Limit = Limit, + IncludeSortVector = IncludeSortVector, + IncludeSimilarity = IncludeSimilarity, + Projection = Projection != null ? Projection.Clone() : null, + Sort = Sort != null ? Sort.Clone() : null, + }; + } + + internal CommandOptions CommandOptions() + { + return new CommandOptions { + Token = Token, + RunMode = RunMode, + Destination = Destination, + HttpClientOptions = HttpClientOptions != null ? HttpClientOptions.Clone() : null, + TimeoutOptions = TimeoutOptions != null ? TimeoutOptions.Clone() : null, + APIVersion = APIVersion, + CancellationToken = CancellationToken + }; + } + internal TableFindManyOptions Clone() { return new TableFindManyOptions @@ -155,50 +182,37 @@ internal TableFindManyOptions Clone() IncludeSortVector = IncludeSortVector, IncludeSimilarity = IncludeSimilarity, Projection = Projection != null ? Projection.Clone() : null, - Sort = Sort != null ? Sort.Clone() : null + Sort = Sort != null ? Sort.Clone() : null, + // CommandOptions properties: + Token = Token, + RunMode = RunMode, + Destination = Destination, + HttpClientOptions = HttpClientOptions != null ? HttpClientOptions.Clone() : null, + TimeoutOptions = TimeoutOptions != null ? TimeoutOptions.Clone() : null, + APIVersion = APIVersion, + CancellationToken = CancellationToken }; } - IFindManyOptions> IFindManyOptions>.Clone() + IFindManyOptions> IFindManyOptions>.Clone() + { + return Clone(); + } + internal TableFindManyOptions WithFilterParam(TableFilter filter) + { + if (filter == null) { - - return Clone(); - + return this; } - - - internal TableFindManyOptions WithFilterParam(TableFilter filter) - + if (Filter != null) { - - if (filter == null) - - { - - return this; - - } - - - - if (Filter != null) - - { - - throw new ArgumentException("Cannot pass a filter both within FindOptions and as stand-alone argument"); - - } - - - - var cloned = Clone(); - - cloned.Filter = filter; - - return cloned; - + throw new ArgumentException("Cannot pass a filter both within FindOptions and as stand-alone argument"); } - } \ No newline at end of file + var cloned = Clone(); + cloned.Filter = filter; + return cloned; + } +} diff --git a/src/DataStax.AstraDB.DataApi/Core/TimeoutOptions.cs b/src/DataStax.AstraDB.DataApi/Core/TimeoutOptions.cs index 098f994..46f254e 100644 --- a/src/DataStax.AstraDB.DataApi/Core/TimeoutOptions.cs +++ b/src/DataStax.AstraDB.DataApi/Core/TimeoutOptions.cs @@ -94,4 +94,18 @@ public class TimeoutOptions /// The timeout for keyspace administration operations, such as creating or deleting keyspaces. /// public TimeSpan? KeyspaceAdminTimeout { get; set; } + + internal TimeoutOptions Clone() + { + return new TimeoutOptions + { + ConnectionTimeout = ConnectionTimeout, + RequestTimeout = RequestTimeout, + BulkOperationTimeout = BulkOperationTimeout, + CollectionAdminTimeout = CollectionAdminTimeout, + TableAdminTimeout = TableAdminTimeout, + DatabaseAdminTimeout = DatabaseAdminTimeout, + KeyspaceAdminTimeout = KeyspaceAdminTimeout, + }; + } } diff --git a/src/DataStax.AstraDB.DataApi/Tables/Table.cs b/src/DataStax.AstraDB.DataApi/Tables/Table.cs index 2e51f6e..9653687 100644 --- a/src/DataStax.AstraDB.DataApi/Tables/Table.cs +++ b/src/DataStax.AstraDB.DataApi/Tables/Table.cs @@ -652,21 +652,12 @@ private async Task CreateGenericIndexAsync(string indexName, string columnName, // /// - /// This is a synchronous version of + /// Synchronous version of /// - /// + /// public TableInsertManyResult InsertMany(IEnumerable rows) { - return InsertMany(rows, null as CommandOptions); - } - - /// - /// Synchronous version of - /// - /// - public TableInsertManyResult InsertMany(IEnumerable rows, CommandOptions commandOptions) - { - return InsertManyAsync(rows, null, commandOptions, true).ResultSync(); + return InsertMany(rows, null); } /// @@ -675,55 +666,38 @@ public TableInsertManyResult InsertMany(IEnumerable rows, CommandOptions comm /// public TableInsertManyResult InsertMany(IEnumerable rows, InsertManyOptions insertOptions) { - return InsertManyAsync(rows, insertOptions, null, true).ResultSync(); + return InsertManyAsync(rows, insertOptions, runSynchronously: true).ResultSync(); } /// - /// Insert multiple rows into the table. + /// Asynchronously insert multiple rows into the table. /// - /// + /// The list of rows to insert. /// /// - /// If you need to control concurrency, chunk size, or whether the insert is ordered or not, use the overload. - /// To additionally control timesouts, use the overload. + /// If you need to control concurrency, chunk size, whether the insert is ordered or not, or other options, use the overload. /// - /// Thrown if the rows collection is null or empty. - /// Thrown if an error occurs during the bulk operation, with partial results returned in the property. + /// Thrown if an error occurs during the bulk operation, + /// with partial results returned in the property. public Task InsertManyAsync(IEnumerable rows) { - return InsertManyAsync(rows, null, null, false); + return InsertManyAsync(rows, null); } /// - /// - /// - public Task InsertManyAsync(IEnumerable rows, CommandOptions commandOptions) - { - return InsertManyAsync(rows, null, commandOptions, false); - } - - /// - /// - /// + /// The list of rows to insert. + /// Allows specifying the insertion chunk size, ordered/unordered mode, concurrency, as well as other generic command-execution options. public Task InsertManyAsync(IEnumerable rows, InsertManyOptions insertOptions) { - return InsertManyAsync(rows, insertOptions, null, false); + return InsertManyAsync(rows, insertOptions, runSynchronously: false); } - /// - /// - /// - /// - public Task InsertManyAsync(IEnumerable rows, InsertManyOptions insertOptions, CommandOptions commandOptions) + private async Task InsertManyAsync(IEnumerable rows, InsertManyOptions insertOptions, bool runSynchronously) { - return InsertManyAsync(rows, insertOptions, commandOptions, false); - } - - private async Task InsertManyAsync(IEnumerable rows, InsertManyOptions insertOptions, CommandOptions commandOptions, bool runSynchronously) - { - Guard.NotNullOrEmpty(rows, nameof(rows)); + Guard.NotNull(rows, nameof(rows)); if (insertOptions == null) insertOptions = new InsertManyOptions(); + var commandOptions = insertOptions.CommandOptions(); if (insertOptions.Concurrency > 1 && insertOptions.Ordered) { throw new ArgumentException("Cannot run ordered insert_many concurrently."); @@ -916,7 +890,8 @@ public TableFindCursor Find(TableFindManyOptions findOptions) public TableFindCursor Find(TableFilter filter, TableFindManyOptions findOptions) { findOptions ??= new TableFindManyOptions(); - return new(findOptions.WithFilterParam(filter), null, RunFindManyAsync); + var commandOptions = findOptions.CommandOptions(); + return new(findOptions.WithFilterParam(filter), commandOptions, RunFindManyAsync); } /// @@ -949,22 +924,26 @@ public TableFindCursor Find(TableFindManyOptions findOpt return Find(null, findOptions); } - /// - /// - /// + /// + /// + /// The Find alternatives that accept a TResult type parameter allow for deserializing the row as a different type + /// (most commonly used when using projection to return a subset of fields) + /// public TableFindCursor Find(TableFilter filter, TableFindManyOptions findOptions) where TResult : class { findOptions ??= new TableFindManyOptions(); - return new(findOptions.WithFilterParam(filter), null, RunFindManyAsync); + var commandOptions = findOptions.CommandOptions(); + return new(findOptions.WithFilterParam(filter), commandOptions, RunFindManyAsync); } internal async Task> RunFindManyAsync(TableFindCursor cursor, string nextPageState, bool runSynchronously) where TResult : class { var options = cursor.FindOptions.Clone(); options.PageState = nextPageState; - + + var payloadOptions = options.PayloadOptions(); var commandOptions = SetRowSerializationOptions(cursor.CommandOptions, false); - var command = CreateCommand("find").WithPayload(options).AddCommandOptions(commandOptions); + var command = CreateCommand("find").WithPayload(payloadOptions).AddCommandOptions(commandOptions); var response = await command.RunAsyncReturnData, TableFindStatusResult>(runSynchronously).ConfigureAwait(false); if (typeof(Row).IsAssignableFrom(typeof(TResult))) diff --git a/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/CollectionCursorTests.cs b/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/CollectionCursorTests.cs index 3ff7a5a..2ee6315 100644 --- a/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/CollectionCursorTests.cs +++ b/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/CollectionCursorTests.cs @@ -26,6 +26,32 @@ public CollectionCursorTests(AssemblyFixture assemblyFixture, CollectionCursorFi _fixture = fixture; } + // This one is skipped on HCD because in some cases a wrong token will *not* bring failure + [SkipWhenNotAstra] + [Fact] + public async Task Test_CollectionCursor_CommandOptions() + { + var filledCollection = _fixture.FilledCollection; + + var theFilter = Builders.CollectionFilter.Gt(d => d.PInt, 2); + var theGoodFindOptions = new CollectionFindManyOptions { + Sort = Builders.CollectionSort.Descending(d => d.PInt) + }; + var theBadFindOptions = new CollectionFindManyOptions { + Sort = Builders.CollectionSort.Descending(d => d.PInt), + Token = "blibblo" + }; + + var goodCur = filledCollection.Find(theFilter, theGoodFindOptions); + var badCur = filledCollection.Find(theFilter, theBadFindOptions); + + await foreach (var item in goodCur) { /* moot */ }; + await Assert.ThrowsAsync( async () => + { + await foreach (var item in badCur) { /* moot */ } + }); + } + [Fact] public async Task Test_CollectionCursor_IdleProperties() { diff --git a/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/CollectionTests.cs b/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/CollectionTests.cs index c3983d4..e82e105 100644 --- a/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/CollectionTests.cs +++ b/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/CollectionTests.cs @@ -628,6 +628,38 @@ public async Task InsertDocumentsOrderedAsync() } } + [SkipWhenNotAstra] + [Fact] + public async Task InsertManyCommandOptions() + { + var collectionName = "simpleObjects"; + try + { + List items = new List(); + for (var i = 0; i < 10; i++) + { + items.Add(new SimpleObject() + { + _id = i, + Name = $"Test Object {i}" + }); + } + ; + var collection = await fixture.Database.CreateCollectionAsync(collectionName); + + // passing generic command options: + await Assert.ThrowsAsync>>( async () => + { + await collection.InsertManyAsync( + items, new InsertManyOptions() { Token = "blibbli" }); + }); + } + finally + { + await fixture.Database.DropCollectionAsync(collectionName); + } + } + [Fact] public async Task CountDocuments_NoFilter_ReturnsCorrectCount() { diff --git a/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/TableTests.cs b/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/TableTests.cs index 0b96aa1..d2f17f3 100644 --- a/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/TableTests.cs +++ b/test/DataStax.AstraDB.DataApi.IntegrationTests/Tests/TableTests.cs @@ -1,5 +1,6 @@ using DataStax.AstraDB.DataApi.Core; using DataStax.AstraDB.DataApi.Core.Query; +using DataStax.AstraDB.DataApi.Core.Results; using DataStax.AstraDB.DataApi.IntegrationTests.Fixtures; using DataStax.AstraDB.DataApi.Tables; using Microsoft.VisualBasic; @@ -56,6 +57,45 @@ public async Task InsertRows() } } + [SkipWhenNotAstra] + [Fact] + public async Task InsertManyCommandOptions() + { + var tableName = "insertRowsTest"; + try + { + var table = await fixture.Database.CreateTableAsync(tableName); + var row1 = new RowBook() + { + Title = "Computed Wilderness", + Author = "Ryan Eau", + NumberOfPages = 432, + DueDate = DateTime.UtcNow - TimeSpan.FromDays(1), + Genres = new HashSet { "History", "Biography" } + }; + var row2 = new RowBook() + { + Title = "Desert Peace", + Author = "Walter Dray", + NumberOfPages = 355, + DueDate = DateTime.UtcNow - TimeSpan.FromDays(2), + Genres = new HashSet { "Fiction" } + }; + var rows = new List { row1, row2 }; + + // passing generic command options: + await Assert.ThrowsAsync>( async () => + { + await table.InsertManyAsync( + rows, new InsertManyOptions() { Token = "blibbli" }); + }); + } + finally + { + await fixture.Database.DropTableAsync(tableName); + } + } + [Fact] public async Task InsertManyRows() {