public async Task CreateTextIndexWithOptionAsync() { // Arrange string expectedIndexName = $"{Guid.NewGuid()}"; var option = new IndexCreationOptions { Name = expectedIndexName }; await textIndexSemaphore.WaitAsync(); try { // Act var result = await SUT.CreateTextIndexAsync <T, TKey>(x => x.Version, option, PartitionKey); // Assert var listOfIndexNames = await SUT.GetIndexesNamesAsync <T, TKey>(PartitionKey); Assert.Contains(expectedIndexName, listOfIndexNames); // Cleanup await SUT.DropIndexAsync <T, TKey>(expectedIndexName, PartitionKey); } finally { textIndexSemaphore.Release(); } }
/// <summary> /// Creates an index with the specified name on the specified table /// </summary> /// <param name="name"></param> /// <param name="table"></param> /// <param name="cols"></param> /// <param name="options"></param> /// <param name="where"></param> public void CreateIndex(string name, string table, IndexedColumn[] cols, IndexCreationOptions options, WhereStatement where = null) { // ----------------------------------------- // Begin the SQL generation // ----------------------------------------- StringBuilder sql = new StringBuilder("CREATE ", 256); sql.AppendIf(options.HasFlag(IndexCreationOptions.Unique), "UNIQUE "); sql.Append("INDEX "); sql.AppendIf(options.HasFlag(IndexCreationOptions.IfNotExists), "IF NOT EXISTS "); // Append index name sql.Append($"{name} ON "); sql.Append(QuoteIdentifier(table, this.IdentifierQuoteMode, this.IdentifierQuoteKind)); sql.Append("("); // Append columns int i = cols.Length; foreach (var col in cols) { --i; sql.Append(QuoteIdentifier(col.Name, this.IdentifierQuoteMode, this.IdentifierQuoteKind)); sql.AppendIf(col.Collate != Collation.Default, $" COLLATE {col.Collate.ToString().ToUpperInvariant()}"); sql.AppendIf(col.SortOrder == Sorting.Descending, " DESC"); sql.AppendIf(i > 0, ", "); } // Close sql.Append(")"); // Add where if we have one if (where != null) { sql.Append(" WHERE "); sql.Append(where.BuildStatement()); } // ----------------------------------------- // Execute the command on the database // ----------------------------------------- using (SQLiteCommand command = CreateCommand(sql.ToString())) { command.ExecuteNonQuery(); } }
/// <summary> /// Maps a IndexCreationOptions object to a MongoDB.Driver.CreateIndexOptions object /// </summary> /// <param name="indexCreationOptions">The options for creating an index.</param> /// <returns></returns> protected virtual CreateIndexOptions MapIndexOptions(IndexCreationOptions indexCreationOptions) { return(new CreateIndexOptions { Unique = indexCreationOptions.Unique, TextIndexVersion = indexCreationOptions.TextIndexVersion, SphereIndexVersion = indexCreationOptions.SphereIndexVersion, Sparse = indexCreationOptions.Sparse, Name = indexCreationOptions.Name, Min = indexCreationOptions.Min, Max = indexCreationOptions.Max, LanguageOverride = indexCreationOptions.LanguageOverride, ExpireAfter = indexCreationOptions.ExpireAfter, DefaultLanguage = indexCreationOptions.DefaultLanguage, Bits = indexCreationOptions.Bits, Background = indexCreationOptions.Background, Version = indexCreationOptions.Version }); }
private string PutIndexInternal(string name, IndexDefinition definition, bool disableIndexBeforePut = false, bool isUpdateBySideSide = false, IndexCreationOptions? creationOptions = null) { if (name == null) throw new ArgumentNullException("name"); name = name.Trim(); IsIndexNameValid(name); var existingIndex = IndexDefinitionStorage.GetIndexDefinition(name); if (existingIndex != null) { switch (existingIndex.LockMode) { case IndexLockMode.SideBySide: if (isUpdateBySideSide == false) { Log.Info("Index {0} not saved because it might be only updated by side-by-side index"); throw new InvalidOperationException("Can not overwrite locked index: " + name + ". This index can be only updated by side-by-side index."); } break; case IndexLockMode.LockedIgnore: Log.Info("Index {0} not saved because it was lock (with ignore)", name); return null; case IndexLockMode.LockedError: throw new InvalidOperationException("Can not overwrite locked index: " + name); } } AssertAnalyzersValid(definition); switch (creationOptions ?? FindIndexCreationOptions(definition, ref name)) { case IndexCreationOptions.Noop: return null; case IndexCreationOptions.UpdateWithoutUpdatingCompiledIndex: // ensure that the code can compile new DynamicViewCompiler(definition.Name, definition, Database.Extensions, IndexDefinitionStorage.IndexDefinitionsPath, Database.Configuration).GenerateInstance(); IndexDefinitionStorage.UpdateIndexDefinitionWithoutUpdatingCompiledIndex(definition); return null; case IndexCreationOptions.Update: // ensure that the code can compile new DynamicViewCompiler(definition.Name, definition, Database.Extensions, IndexDefinitionStorage.IndexDefinitionsPath, Database.Configuration).GenerateInstance(); DeleteIndex(name); break; } PutNewIndexIntoStorage(name, definition, disableIndexBeforePut); WorkContext.ClearErrorsFor(name); TransactionalStorage.ExecuteImmediatelyOrRegisterForSynchronization(() => Database.Notifications.RaiseNotifications(new IndexChangeNotification { Name = name, Type = IndexChangeTypes.IndexAdded, })); return name; }
/// <inheritdoc /> public async virtual Task <string> CreateCombinedTextIndexAsync <TDocument, TKey>(IEnumerable <Expression <Func <TDocument, object> > > fields, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) where TDocument : IDocument <TKey> where TKey : IEquatable <TKey> { return(await MongoDbIndexHandler.CreateCombinedTextIndexAsync <TDocument, TKey>(fields, indexCreationOptions, partitionKey)); }
/// <summary> /// Creates a hashed index on the given field. /// IndexCreationOptions can be supplied to further specify /// how the creation should be done. /// </summary> /// <typeparam name="TDocument">The type representing a Document.</typeparam> /// <param name="field">The field we want to index.</param> /// <param name="indexCreationOptions">Options for creating an index.</param> /// <param name="partitionKey">An optional partition key.</param> /// <returns>The result of the create index operation.</returns> public async Task <string> CreateHashedIndexAsync <TDocument>(Expression <Func <TDocument, object> > field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) where TDocument : IDocument <Guid> { return(await MongoDbIndexHandler.CreateHashedIndexAsync <TDocument, Guid>(field, indexCreationOptions, partitionKey)); }
/// <inheritdoc /> public async Task <string> CreateHashedIndexAsync <TDocument, TKey>(Expression <Func <TDocument, object> > field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) where TDocument : IDocument <TKey> where TKey : IEquatable <TKey> { var collection = HandlePartitioned <TDocument, TKey>(partitionKey); var createOptions = indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions); var indexKey = Builders <TDocument> .IndexKeys; return(await collection.Indexes .CreateOneAsync( new CreateIndexModel <TDocument>(indexKey.Hashed(field), createOptions))); }
/// <inheritdoc /> public async Task <string> CreateDescendingIndexAsync <TDocument>(Expression <Func <TDocument, object> > field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) where TDocument : IDocument { return(await CreateDescendingIndexAsync <TDocument, Guid>(field, indexCreationOptions, partitionKey)); }
/// <inheritdoc /> public async Task <string> CreateTextIndexAsync <TDocument, TKey>(Expression <Func <TDocument, object> > field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) where TDocument : IDocument <TKey> where TKey : IEquatable <TKey> { return(await HandlePartitioned <TDocument, TKey>(partitionKey).Indexes .CreateOneAsync( new CreateIndexModel <TDocument>( Builders <TDocument> .IndexKeys.Text(field), indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions) ))); }
/// <inheritdoc /> public async Task <string> CreateCombinedTextIndexAsync <TDocument, TKey>(IEnumerable <Expression <Func <TDocument, object> > > fields, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) where TDocument : IDocument <TKey> where TKey : IEquatable <TKey> { var collection = HandlePartitioned <TDocument, TKey>(partitionKey); var createOptions = indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions); var listOfDefs = new List <IndexKeysDefinition <TDocument> >(); foreach (var field in fields) { listOfDefs.Add(Builders <TDocument> .IndexKeys.Text(field)); } return(await collection.Indexes .CreateOneAsync(new CreateIndexModel <TDocument>(Builders <TDocument> .IndexKeys.Combine(listOfDefs), createOptions))); }
/// <inheritdoc /> public async Task <string> CreateCombinedTextIndexAsync <TDocument>(IEnumerable <Expression <Func <TDocument, object> > > fields, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) where TDocument : IDocument { return(await CreateCombinedTextIndexAsync <TDocument, Guid>(fields, indexCreationOptions, partitionKey)); }
private string PutIndexInternal(string name, IndexDefinition definition, bool disableIndexBeforePut = false, bool isUpdateBySideSide = false, IndexCreationOptions? creationOptions = null, bool isReplication = false) { if (name == null) throw new ArgumentNullException("name"); name = name.Trim(); IsIndexNameValid(name); var existingIndex = IndexDefinitionStorage.GetIndexDefinition(name); if (existingIndex != null) { var newIndexVersion = definition.IndexVersion; var currentIndexVersion = existingIndex.IndexVersion; // whether we update the index definition or not, // we need to update the index version existingIndex.IndexVersion = definition.IndexVersion = Math.Max(currentIndexVersion ?? 0, newIndexVersion ?? 0); switch (isReplication) { case true: if (newIndexVersion != null && currentIndexVersion != null && newIndexVersion <= currentIndexVersion) { //this new index is an older version of the current one return null; } // we need to update the lock mode only if it was updated by another server existingIndex.LockMode = definition.LockMode; break; default: if (CanUpdateIndex(name, definition, isUpdateBySideSide, existingIndex) == false) return null; break; } } AssertAnalyzersValid(definition); switch (creationOptions ?? FindIndexCreationOptions(definition, ref name)) { case IndexCreationOptions.Noop: return null; case IndexCreationOptions.UpdateWithoutUpdatingCompiledIndex: // ensure that the code can compile new DynamicViewCompiler(definition.Name, definition, Database.Extensions, IndexDefinitionStorage.IndexDefinitionsPath, Database.Configuration).GenerateInstance(); IndexDefinitionStorage.UpdateIndexDefinitionWithoutUpdatingCompiledIndex(definition); if (isReplication == false) definition.IndexVersion = (definition.IndexVersion ?? 0) + 1; return null; case IndexCreationOptions.Update: // ensure that the code can compile new DynamicViewCompiler(definition.Name, definition, Database.Extensions, IndexDefinitionStorage.IndexDefinitionsPath, Database.Configuration).GenerateInstance(); DeleteIndex(name); if (isReplication == false) definition.IndexVersion = (definition.IndexVersion ?? 0) + 1; break; case IndexCreationOptions.Create: if (isReplication == false) { // we create a new index, // we need to restore its previous IndexVersion (if it was deleted before) var deletedIndexVersion = IndexDefinitionStorage.GetDeletedIndexVersion(definition); var replacingIndexVersion = GetOriginalIndexVersion(definition.Name); definition.IndexVersion = Math.Max(deletedIndexVersion, replacingIndexVersion); definition.IndexVersion++; } break; } PutNewIndexIntoStorage(name, definition, disableIndexBeforePut); WorkContext.ClearErrorsFor(name); TransactionalStorage.ExecuteImmediatelyOrRegisterForSynchronization(() => Database.Notifications.RaiseNotifications(new IndexChangeNotification { Name = name, Type = IndexChangeTypes.IndexAdded, Version = definition.IndexVersion })); return name; }
/// <summary> /// Creates an index on the given field in descending order. /// IndexCreationOptions can be supplied to further specify /// how the creation should be done. /// </summary> /// <typeparam name="TDocument">The type representing a Document.</typeparam> /// <param name="field">The field we want to index.</param> /// <param name="indexCreationOptions">Options for creating an index.</param> /// <param name="partitionKey">An optional partition key.</param> /// <returns>The result of the create index operation.</returns> public async virtual Task <string> CreateDescendingIndexAsync <TDocument>(Expression <Func <TDocument, object> > field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) where TDocument : IDocument <TKey> { return(await MongoDbIndexHandler.CreateDescendingIndexAsync <TDocument, TKey>(field, indexCreationOptions, partitionKey)); }
public Task Alter(IndexCreationOptions options) { throw new NotImplementedException(); }