internal static string GetQuerySource(DocumentConventions conventions, Type type, IndexSourceType sourceType) { var collectionName = conventions.GetCollectionName(type); string source; switch (sourceType) { case IndexSourceType.Documents: source = "docs"; break; case IndexSourceType.Counters: source = "counters"; break; case IndexSourceType.TimeSeries: source = "timeSeries"; break; default: throw new NotSupportedException($"Not supported index source type '{sourceType}'."); } if (StringExtensions.IsIdentifier(collectionName)) { return($"{source}.{collectionName}"); } return($"{source}[@\"{collectionName.Replace("\"", "\"\"")}\"]"); }
internal static string GetQuerySource(DocumentConventions conventions, Type type, IndexSourceType sourceType) { var collectionName = conventions.GetCollectionName(type); string source; switch (sourceType) { case IndexSourceType.Documents: source = "docs"; break; case IndexSourceType.Counters: source = "counters"; break; case IndexSourceType.TimeSeries: source = "timeSeries"; break; default: throw new NotSupportedException($"Not supported index source type '{sourceType}'."); } if (StringExtensions.IsIdentifier(collectionName)) { return($"{source}.{collectionName}"); } var builder = new StringBuilder($"{source}[@\""); StringExtensions.EscapeString(builder, collectionName); return(builder.Append("\"]").ToString()); }
public Task <string> GenerateDocumentIdAsync(object entity) { var typeTagName = Conventions.GetCollectionName(entity); if (string.IsNullOrEmpty(typeTagName)) //ignore empty tags { return(NullStringCompletedTask); } var tag = Conventions.TransformTypeCollectionNameToDocumentIdPrefix(typeTagName); if (_idGeneratorsByTag.TryGetValue(tag, out var value)) { return(value.GenerateDocumentIdAsync(entity)); } lock (_generatorLock) { if (_idGeneratorsByTag.TryGetValue(tag, out value)) { return(value.GenerateDocumentIdAsync(entity)); } value = CreateGeneratorFor(tag); _idGeneratorsByTag.TryAdd(tag, value); } return(value.GenerateDocumentIdAsync(entity)); }
public Task <string> GenerateDocumentIdAsync(object entity) { var typeTagName = _conventions.GetCollectionName(entity); if (string.IsNullOrEmpty(typeTagName)) //ignore empty tags { return(NullStringCompletedTask); } var tag = _conventions.TransformTypeCollectionNameToDocumentIdPrefix(typeTagName); AsyncHiLoIdGenerator value; if (_idGeneratorsByTag.TryGetValue(tag, out value)) { return(value.GenerateDocumentIdAsync(entity)); } lock (_generatorLock) { if (_idGeneratorsByTag.TryGetValue(tag, out value)) { return(value.GenerateDocumentIdAsync(entity)); } value = new AsyncHiLoIdGenerator(tag, _store, _dbName, _conventions.IdentityPartsSeparator); _idGeneratorsByTag.TryAdd(tag, value); } return(value.GenerateDocumentIdAsync(entity)); }
internal static string GetQuerySource(DocumentConventions conventions, Type type) { var collectionName = conventions.GetCollectionName(type); if (StringExtensions.IsIdentifier(collectionName)) { return("docs." + collectionName); } return("docs[@\"" + collectionName.Replace("\"", "\"\"") + "\"]"); }
public static string GetPrefixedIncludePath <TInclude>(string basePath, DocumentConventions conventions) { var idPrefix = conventions.GetCollectionName(typeof(TInclude)); if (idPrefix != null) { idPrefix = conventions.TransformTypeCollectionNameToDocumentIdPrefix(idPrefix); idPrefix += conventions.IdentityPartsSeparator; } return(basePath + "(" + idPrefix + ")"); }
internal static string GetQuerySource(DocumentConventions conventions, Type type) { var collectionName = conventions.GetCollectionName(type); if (StringExtensions.IsIdentifier(collectionName)) { return("docs." + collectionName); } var builder = new StringBuilder("docs[@\""); StringExtensions.EscapeString(builder, collectionName); return(builder.Append("\"]").ToString()); }
public async Task <string> GenerateDocumentIdAsync(object entity) { var identityPartsSeparator = Conventions.IdentityPartsSeparator; if (_identityPartsSeparator != identityPartsSeparator) { await MaybeRefresh(identityPartsSeparator).ConfigureAwait(false); } var typeTagName = Conventions.GetCollectionName(entity); if (string.IsNullOrEmpty(typeTagName)) //ignore empty tags { return(null); } var tag = Conventions.TransformTypeCollectionNameToDocumentIdPrefix(typeTagName); if (_idGeneratorsByTag.TryGetValue(tag, out var value)) { return(await value.GenerateDocumentIdAsync(entity).ConfigureAwait(false)); } await _generatorLock.WaitAsync().ConfigureAwait(false); try { if (_idGeneratorsByTag.TryGetValue(tag, out value)) { return(await value.GenerateDocumentIdAsync(entity).ConfigureAwait(false)); } value = CreateGeneratorFor(tag); _idGeneratorsByTag.TryAdd(tag, value); } finally { _generatorLock.Release(); } return(await value.GenerateDocumentIdAsync(entity).ConfigureAwait(false)); }
public IChangesObservable <DocumentChange> ForDocumentsInCollection <TEntity>() { var collectionName = _conventions.GetCollectionName(typeof(TEntity)); return(ForDocumentsInCollection(collectionName)); }
internal static SubscriptionCreationOptions CreateSubscriptionOptionsFromGeneric <T>( DocumentConventions conventions, SubscriptionCreationOptions criteria, Expression <Func <T, bool> > predicate, Expression <Func <T, object> > project, Action <ISubscriptionIncludeBuilder <T> > includes) { criteria ??= new SubscriptionCreationOptions(); var collectionName = conventions.GetCollectionName(typeof(T)); if (criteria.Query == null) { var tType = typeof(T); var includeRevisions = tType.IsConstructedGenericType && tType.GetGenericTypeDefinition() == typeof(Revision <>); if (includeRevisions) { collectionName = conventions.GetCollectionName(tType.GenericTypeArguments[0]); } var builder = new StringBuilder("from '"); StringExtensions.EscapeString(builder, collectionName); builder.Append('\''); if (includeRevisions) { builder.Append(" (Revisions = true)"); } criteria.Query = builder.Append(" as doc").ToString(); } if (predicate != null) { var script = predicate.CompileToJavascript( new JavascriptCompilationOptions( JsCompilationFlags.BodyOnly, JavascriptConversionExtensions.MathSupport.Instance, new JavascriptConversionExtensions.DictionarySupport(), JavascriptConversionExtensions.LinqMethodsSupport.Instance, new JavascriptConversionExtensions.SubscriptionsWrappedConstantSupport(conventions), new JavascriptConversionExtensions.ConstSupport(conventions), new JavascriptConversionExtensions.ReplaceParameterWithNewName(predicate.Parameters[0], "this"), JavascriptConversionExtensions.ToStringSupport.Instance, JavascriptConversionExtensions.DateTimeSupport.Instance, JavascriptConversionExtensions.InvokeSupport.Instance, JavascriptConversionExtensions.NullCoalescingSupport.Instance, JavascriptConversionExtensions.NestedConditionalSupport.Instance, JavascriptConversionExtensions.StringSupport.Instance )); criteria.Query = $"declare function predicate() {{ return {script} }}{Environment.NewLine}" + $"{criteria.Query}{Environment.NewLine}" + "where predicate.call(doc)"; } if (project != null) { var script = project.CompileToJavascript( new JavascriptCompilationOptions( JsCompilationFlags.BodyOnly, JavascriptConversionExtensions.MathSupport.Instance, new JavascriptConversionExtensions.DictionarySupport(), JavascriptConversionExtensions.LinqMethodsSupport.Instance, new JavascriptConversionExtensions.ConstSupport(conventions), JavascriptConversionExtensions.ToStringSupport.Instance, JavascriptConversionExtensions.DateTimeSupport.Instance, JavascriptConversionExtensions.InvokeSupport.Instance, JavascriptConversionExtensions.NullCoalescingSupport.Instance, JavascriptConversionExtensions.StringSupport.Instance, JavascriptConversionExtensions.NestedConditionalSupport.Instance, new JavascriptConversionExtensions.ReplaceParameterWithNewName(project.Parameters[0], "doc"), JavascriptConversionExtensions.CounterSupport.Instance, JavascriptConversionExtensions.CompareExchangeSupport.Instance )); criteria.Query += Environment.NewLine + "select " + script; } if (includes != null) { var builder = new IncludeBuilder <T>(conventions); includes(builder); var numberOfIncludesAdded = 0; if (builder.DocumentsToInclude?.Count > 0) { criteria.Query += Environment.NewLine + "include "; foreach (var inc in builder.DocumentsToInclude) { var include = "doc." + inc; if (numberOfIncludesAdded > 0) { criteria.Query += ","; } if (IncludesUtil.RequiresQuotes(include, out var escapedInclude)) { criteria.Query += $"'{escapedInclude}'"; } else { criteria.Query += include; } numberOfIncludesAdded++; } } if (builder.AllCounters) { if (numberOfIncludesAdded == 0) { criteria.Query += Environment.NewLine + "include "; } criteria.Query += $"counters()"; numberOfIncludesAdded++; } else if (builder.CountersToInclude?.Count > 0) { if (numberOfIncludesAdded == 0) { criteria.Query += Environment.NewLine + "include "; } foreach (var counterName in builder.CountersToInclude) { if (numberOfIncludesAdded > 0) { criteria.Query += ","; } if (IncludesUtil.RequiresQuotes(counterName, out var escapedCounterName)) { criteria.Query += $"counters({escapedCounterName})"; } else { criteria.Query += $"counters({counterName})"; } numberOfIncludesAdded++; } } } return(criteria); }
/// <summary> /// Toes the index definition. /// </summary> public IndexDefinition ToIndexDefinition(DocumentConventions conventions, bool validateMap = true) { if (Map == null && validateMap) { throw new InvalidOperationException( string.Format("Map is required to generate an index, you cannot create an index without a valid Map property (in index {0}).", _indexName)); } try { if (Reduce != null) { IndexDefinitionHelper.ValidateReduce(Reduce); } string querySource = (typeof(TDocument) == typeof(object) || ContainsWhereEntityIs()) ? "docs" : "docs." + conventions.GetCollectionName(typeof(TDocument)); var indexDefinition = new IndexDefinition { Name = _indexName, Reduce = IndexDefinitionHelper.PruneToFailureLinqQueryAsStringToWorkableCode <TDocument, TReduceResult>(Reduce, conventions, "results", translateIdentityProperty: false), LockMode = LockMode, Priority = Priority, OutputReduceToCollection = OutputReduceToCollection }; var indexes = ConvertToStringDictionary(Indexes); var stores = ConvertToStringDictionary(Stores); var analyzers = ConvertToStringDictionary(Analyzers); var suggestionsOptions = ConvertToStringSet(SuggestionsOptions).ToDictionary(x => x, x => true); var termVectors = ConvertToStringDictionary(TermVectors); var spatialOptions = ConvertToStringDictionary(SpatialIndexes); if (conventions.PrettifyGeneratedLinqExpressions) { indexDefinition.Reduce = IndexPrettyPrinter.TryFormat(indexDefinition.Reduce); } foreach (var indexesString in IndexesStrings) { if (indexes.ContainsKey(indexesString.Key)) { throw new InvalidOperationException("There is a duplicate key in indexes: " + indexesString.Key); } indexes.Add(indexesString); } foreach (var storeString in StoresStrings) { if (stores.ContainsKey(storeString.Key)) { throw new InvalidOperationException("There is a duplicate key in stores: " + storeString.Key); } stores.Add(storeString); } foreach (var analyzerString in AnalyzersStrings) { if (analyzers.ContainsKey(analyzerString.Key)) { throw new InvalidOperationException("There is a duplicate key in analyzers: " + analyzerString.Key); } analyzers.Add(analyzerString); } foreach (var termVectorString in TermVectorsStrings) { if (termVectors.ContainsKey(termVectorString.Key)) { throw new InvalidOperationException("There is a duplicate key in term vectors: " + termVectorString.Key); } termVectors.Add(termVectorString); } foreach (var spatialString in SpatialIndexesStrings) { if (spatialOptions.ContainsKey(spatialString.Key)) { throw new InvalidOperationException("There is a duplicate key in spatial indexes: " + spatialString.Key); } spatialOptions.Add(spatialString); } ApplyValues(indexDefinition, indexes, (options, value) => options.Indexing = value); ApplyValues(indexDefinition, stores, (options, value) => options.Storage = value); ApplyValues(indexDefinition, analyzers, (options, value) => options.Analyzer = value); ApplyValues(indexDefinition, termVectors, (options, value) => options.TermVector = value); ApplyValues(indexDefinition, spatialOptions, (options, value) => options.Spatial = value); ApplyValues(indexDefinition, suggestionsOptions, (options, value) => options.Suggestions = value); if (Map != null) { var map = IndexDefinitionHelper.PruneToFailureLinqQueryAsStringToWorkableCode <TDocument, TReduceResult>( Map, conventions, querySource, translateIdentityProperty: true); indexDefinition.Maps.Add(conventions.PrettifyGeneratedLinqExpressions ? IndexPrettyPrinter.TryFormat(map) : map); } indexDefinition.AdditionalSources = AdditionalSources; return(indexDefinition); } catch (Exception e) { throw new IndexCompilationException("Failed to create index " + _indexName, e); } }
internal static SubscriptionCreationOptions CreateSubscriptionOptionsFromGeneric <T>( DocumentConventions conventions, SubscriptionCreationOptions criteria, Expression <Func <T, bool> > predicate, Expression <Func <T, object> > project, Action <ISubscriptionIncludeBuilder <T> > includes) { criteria ??= new SubscriptionCreationOptions(); var collectionName = conventions.GetCollectionName(typeof(T)); StringBuilder queryBuilder; if (criteria.Query != null) { queryBuilder = new StringBuilder(criteria.Query); } else { queryBuilder = new StringBuilder(); var tType = typeof(T); var includeRevisions = tType.IsConstructedGenericType && tType.GetGenericTypeDefinition() == typeof(Revision <>); if (includeRevisions) { collectionName = conventions.GetCollectionName(tType.GenericTypeArguments[0]); } queryBuilder.Append("from '"); StringExtensions.EscapeString(queryBuilder, collectionName); queryBuilder.Append('\''); if (includeRevisions) { queryBuilder.Append(" (Revisions = true)"); } criteria.Query = queryBuilder.Append(" as doc").ToString(); } if (predicate != null) { var script = predicate.CompileToJavascript( new JavascriptCompilationOptions( JsCompilationFlags.BodyOnly, JavascriptConversionExtensions.MathSupport.Instance, new JavascriptConversionExtensions.DictionarySupport(), JavascriptConversionExtensions.LinqMethodsSupport.Instance, new JavascriptConversionExtensions.SubscriptionsWrappedConstantSupport(conventions), new JavascriptConversionExtensions.ConstSupport(conventions), new JavascriptConversionExtensions.ReplaceParameterWithNewName(predicate.Parameters[0], "this"), JavascriptConversionExtensions.ToStringSupport.Instance, JavascriptConversionExtensions.DateTimeSupport.Instance, JavascriptConversionExtensions.TimeSpanSupport.Instance, JavascriptConversionExtensions.InvokeSupport.Instance, JavascriptConversionExtensions.NullCoalescingSupport.Instance, JavascriptConversionExtensions.NestedConditionalSupport.Instance, JavascriptConversionExtensions.StringSupport.Instance, new JavascriptConversionExtensions.IdentityPropertySupport(conventions) )); queryBuilder .Insert(0, $"declare function predicate() {{ return {script} }}{Environment.NewLine}") .AppendLine() .Append("where predicate.call(doc)"); } if (project != null) { var script = project.CompileToJavascript( new JavascriptCompilationOptions( JsCompilationFlags.BodyOnly, JavascriptConversionExtensions.MathSupport.Instance, new JavascriptConversionExtensions.DictionarySupport(), JavascriptConversionExtensions.LinqMethodsSupport.Instance, new JavascriptConversionExtensions.ConstSupport(conventions), JavascriptConversionExtensions.ToStringSupport.Instance, JavascriptConversionExtensions.DateTimeSupport.Instance, JavascriptConversionExtensions.TimeSpanSupport.Instance, JavascriptConversionExtensions.InvokeSupport.Instance, JavascriptConversionExtensions.NullCoalescingSupport.Instance, JavascriptConversionExtensions.StringSupport.Instance, JavascriptConversionExtensions.NestedConditionalSupport.Instance, new JavascriptConversionExtensions.ReplaceParameterWithNewName(project.Parameters[0], "doc"), new JavascriptConversionExtensions.IdentityPropertySupport(conventions), JavascriptConversionExtensions.CounterSupport.Instance, JavascriptConversionExtensions.CompareExchangeSupport.Instance, new JavascriptConversionExtensions.LoadSupport(), JavascriptConversionExtensions.MemberInit.Instance )); queryBuilder .AppendLine() .Append("select ") .Append(script); } if (includes != null) { var builder = new IncludeBuilder <T>(conventions); includes(builder); var numberOfIncludesAdded = 0; if (builder.DocumentsToInclude?.Count > 0) { queryBuilder .AppendLine() .Append("include "); foreach (var inc in builder.DocumentsToInclude) { var include = "doc." + inc; if (numberOfIncludesAdded > 0) { queryBuilder.Append(","); } if (IncludesUtil.RequiresQuotes(include, out var escapedInclude)) { queryBuilder .Append("'") .Append(escapedInclude) .Append("'"); } else { queryBuilder.Append(QueryToken.IsKeyword(include) ? $"'{include}'" : include); } numberOfIncludesAdded++; } } if (builder.AllCounters) { if (numberOfIncludesAdded == 0) { queryBuilder .AppendLine() .Append("include "); } var token = CounterIncludesToken.All(string.Empty); token.WriteTo(queryBuilder); numberOfIncludesAdded++; } else if (builder.CountersToInclude?.Count > 0) { if (numberOfIncludesAdded == 0) { queryBuilder .AppendLine() .Append("include "); } foreach (var counterName in builder.CountersToInclude) { if (numberOfIncludesAdded > 0) { queryBuilder.Append(","); } var token = CounterIncludesToken.Create(string.Empty, counterName); token.WriteTo(queryBuilder); numberOfIncludesAdded++; } } if (builder.TimeSeriesToInclude != null) { foreach (var timeSeriesRange in builder.TimeSeriesToInclude) { if (numberOfIncludesAdded == 0) { queryBuilder .AppendLine() .Append("include "); } if (numberOfIncludesAdded > 0) { queryBuilder.Append(","); } var token = TimeSeriesIncludesToken.Create(string.Empty, timeSeriesRange); token.WriteTo(queryBuilder); numberOfIncludesAdded++; } } } criteria.Query = queryBuilder.ToString(); return(criteria); }
internal static string GetTimeSeriesName <TTimeSeriesEntry>(DocumentConventions conventions) { return(conventions.GetCollectionName(typeof(TTimeSeriesEntry))); }