Ejemplo n.º 1
0
        public Task Delete()
        {
            var returnContextToPool = ContextPool.AllocateOperationContext(out DocumentsOperationContext context); // we don't dispose this as operation is async

            try
            {
                using (var tracker = new RequestTimeTracker(HttpContext, Logger, Database, "DeleteByQuery"))
                {
                    var reader = context.Read(RequestBodyStream(), "queries/delete");
                    var query  = IndexQueryServerSide.Create(HttpContext, reader, Database.QueryMetadataCache, tracker);

                    if (TrafficWatchManager.HasRegisteredClients)
                    {
                        TrafficWatchQuery(query);
                    }

                    ExecuteQueryOperation(query,
                                          (runner, options, onProgress, token) => runner.ExecuteDeleteQuery(query, options, context, onProgress, token),
                                          context, returnContextToPool, Operations.Operations.OperationType.DeleteByQuery);

                    return(Task.CompletedTask);
                }
            }
            catch
            {
                returnContextToPool.Dispose();
                throw;
            }
        }
Ejemplo n.º 2
0
        public async Task Delete()
        {
            var queryContext = QueryOperationContext.Allocate(Database); // we don't dispose this as operation is async

            try
            {
                using (var tracker = new RequestTimeTracker(HttpContext, Logger, Database, "DeleteByQuery"))
                {
                    var reader = await queryContext.Documents.ReadForMemoryAsync(RequestBodyStream(), "queries/delete");

                    var query = IndexQueryServerSide.Create(HttpContext, reader, Database.QueryMetadataCache, tracker);

                    if (TrafficWatchManager.HasRegisteredClients)
                    {
                        TrafficWatchQuery(query);
                    }

                    await ExecuteQueryOperation(query,
                                                (runner, options, onProgress, token) => runner.ExecuteDeleteQuery(query, options, queryContext, onProgress, token),
                                                queryContext, Operations.Operations.OperationType.DeleteByQuery);
                }
            }
            catch
            {
                queryContext.Dispose();
                throw;
            }
        }
Ejemplo n.º 3
0
        public async Task StreamQueryPost()
        {
            // ReSharper disable once ArgumentsStyleLiteral
            using (var tracker = new RequestTimeTracker(HttpContext, Logger, Database, "StreamQuery", doPerformanceHintIfTooLong: false))
                using (var token = CreateTimeLimitedQueryToken())
                    using (Database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                    {
                        var stream    = TryGetRequestFromStream("ExportOptions") ?? RequestBodyStream();
                        var queryJson = await context.ReadForMemoryAsync(stream, "index/query");

                        var query = IndexQueryServerSide.Create(queryJson, context, Database.QueryMetadataCache);
                        tracker.Query = query.Query;

                        var format          = GetStringQueryString("format", false);
                        var properties      = GetStringValuesQueryString("field", false);
                        var propertiesArray = properties.Count == 0 ? null : properties.ToArray();
                        using (var writer = GetQueryResultWriter(format, HttpContext.Response, context, ResponseBodyStream(), propertiesArray))
                        {
                            try
                            {
                                await Database.QueryRunner.ExecuteStreamQuery(query, context, HttpContext.Response, writer, token).ConfigureAwait(false);
                            }
                            catch (IndexDoesNotExistException)
                            {
                                HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                                writer.WriteError("Index " + query.Metadata.IndexName + " does not exists");
                            }
                        }
                    }
        }
Ejemplo n.º 4
0
        private async Task ServerSideQuery(QueryOperationContext queryContext, RequestTimeTracker tracker, HttpMethod method)
        {
            var indexQuery = await GetIndexQuery(queryContext.Documents, method, tracker);

            await using (var writer = new AsyncBlittableJsonTextWriter(queryContext.Documents, ResponseBodyStream()))
            {
                writer.WriteStartObject();
                writer.WritePropertyName(nameof(indexQuery.ServerSideQuery));
                writer.WriteString(indexQuery.ServerSideQuery);

                writer.WriteEndObject();
            }
        }
Ejemplo n.º 5
0
        private async Task ServerSideQuery(DocumentsOperationContext context, RequestTimeTracker tracker, HttpMethod method)
        {
            var indexQuery = await GetIndexQuery(context, method, tracker);

            using (var writer = new AsyncBlittableJsonTextWriter(context, ResponseBodyStream(), Database.DatabaseShutdown))
            {
                writer.WriteStartObject();
                writer.WritePropertyName(nameof(indexQuery.ServerSideQuery));
                writer.WriteString(indexQuery.ServerSideQuery);

                writer.WriteEndObject();
                await writer.OuterFlushAsync();
            }
        }
Ejemplo n.º 6
0
        public async Task StreamQueryPost()
        {
            // ReSharper disable once ArgumentsStyleLiteral
            using (var tracker = new RequestTimeTracker(HttpContext, Logger, Database, "StreamQuery", doPerformanceHintIfTooLong: false))
                using (var token = CreateTimeLimitedQueryToken())
                    using (Database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                    {
                        var stream    = TryGetRequestFromStream("ExportOptions") ?? RequestBodyStream();
                        var queryJson = await context.ReadForMemoryAsync(stream, "index/query");

                        var query = IndexQueryServerSide.Create(queryJson, Database.QueryMetadataCache);
                        tracker.Query = query.Query;

                        if (TrafficWatchManager.HasRegisteredClients)
                        {
                            var sb = new StringBuilder();
                            // append stringBuilder with the query
                            sb.Append(query.Query);
                            // if query got parameters append with parameters
                            if (query.QueryParameters != null && query.QueryParameters.Count > 0)
                            {
                                sb.AppendLine().Append(query.QueryParameters);
                            }
                            AddStringToHttpContext(sb.ToString(), TrafficWatchChangeType.Streams);
                        }

                        var format          = GetStringQueryString("format", false);
                        var properties      = GetStringValuesQueryString("field", false);
                        var propertiesArray = properties.Count == 0 ? null : properties.ToArray();

                        // set the exported file name
                        string fileName = query.Metadata.IsCollectionQuery ? query.Metadata.CollectionName + "_collection" : "query_result";
                        fileName = $"{Database.Name}_{fileName}";

                        using (var writer = GetQueryResultWriter(format, HttpContext.Response, context, ResponseBodyStream(), propertiesArray, fileName))
                        {
                            try
                            {
                                await Database.QueryRunner.ExecuteStreamQuery(query, context, HttpContext.Response, writer, token).ConfigureAwait(false);
                            }
                            catch (IndexDoesNotExistException)
                            {
                                HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                                writer.WriteError("Index " + query.Metadata.IndexName + " does not exists");
                            }
                        }
                    }
        }
Ejemplo n.º 7
0
        private async Task DetailedGraphResult(QueryOperationContext queryContext, RequestTimeTracker tracker, HttpMethod method)
        {
            var indexQuery = await GetIndexQuery(queryContext.Documents, method, tracker);

            var queryRunner = Database.QueryRunner.GetRunner(indexQuery);

            if (!(queryRunner is GraphQueryRunner gqr))
            {
                throw new InvalidOperationException("The specified query is not a graph query.");
            }
            using (var token = CreateTimeLimitedQueryToken())
                await using (var writer = new AsyncBlittableJsonTextWriter(queryContext.Documents, ResponseBodyStream()))
                {
                    await gqr.WriteDetailedQueryResult(indexQuery, queryContext, writer, token);
                }
        }
Ejemplo n.º 8
0
        private async Task DetailedGraphResult(DocumentsOperationContext context, RequestTimeTracker tracker, HttpMethod method)
        {
            var indexQuery = await GetIndexQuery(context, method, tracker);

            var queryRunner = Database.QueryRunner.GetRunner(indexQuery);

            if (!(queryRunner is GraphQueryRunner gqr))
            {
                throw new InvalidOperationException("The specified query is not a graph query.");
            }
            using (var token = CreateTimeLimitedQueryToken())
                using (Database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext ctx))
                    using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        await gqr.WriteDetailedQueryResult(indexQuery, ctx, writer, token);
                    }
        }
Ejemplo n.º 9
0
        private async Task Explain(QueryOperationContext queryContext, RequestTimeTracker tracker, HttpMethod method)
        {
            var indexQuery = await GetIndexQuery(queryContext.Documents, method, tracker);

            var explanations = Database.QueryRunner.ExplainDynamicIndexSelection(indexQuery, out string indexName);

            await using (var writer = new AsyncBlittableJsonTextWriter(queryContext.Documents, ResponseBodyStream()))
            {
                writer.WriteStartObject();
                writer.WritePropertyName("IndexName");
                writer.WriteString(indexName);
                writer.WriteComma();
                writer.WriteArray(queryContext.Documents, "Results", explanations, (w, c, explanation) => w.WriteExplanation(queryContext.Documents, explanation));

                writer.WriteEndObject();
            }
        }
Ejemplo n.º 10
0
        public async Task HandleQuery(HttpMethod httpMethod)
        {
            using (var tracker = new RequestTimeTracker(HttpContext, Logger, Database, "Query"))
                using (var token = CreateTimeLimitedQueryToken())
                    using (Database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                    {
                        var debug = GetStringQueryString("debug", required: false);
                        if (string.IsNullOrWhiteSpace(debug) == false)
                        {
                            await Debug(context, debug, token, tracker, httpMethod);

                            return;
                        }

                        await Query(context, token, tracker, httpMethod);
                    }
        }
Ejemplo n.º 11
0
        public async Task HandleQuery(HttpMethod httpMethod)
        {
            using (var tracker = new RequestTimeTracker(HttpContext, Logger, Database, "Query"))
            {
                try
                {
                    using (var token = CreateTimeLimitedQueryToken())
                        using (var queryContext = QueryOperationContext.Allocate(Database))
                        {
                            var debug = GetStringQueryString("debug", required: false);
                            if (string.IsNullOrWhiteSpace(debug) == false)
                            {
                                await Debug(queryContext, debug, token, tracker, httpMethod);

                                return;
                            }

                            var diagnostics = GetBoolValueQueryString("diagnostics", required: false) ?? false;
                            await Query(queryContext, token, tracker, httpMethod, diagnostics);
                        }
                }
                catch (Exception e)
                {
                    if (tracker.Query == null)
                    {
                        string errorMessage;
                        if (e is EndOfStreamException || e is ArgumentException)
                        {
                            errorMessage = "Failed: " + e.Message;
                        }
                        else
                        {
                            errorMessage = "Failed: " +
                                           HttpContext.Request.Path.Value +
                                           e.ToString();
                        }
                        tracker.Query = errorMessage;
                        if (TrafficWatchManager.HasRegisteredClients)
                        {
                            AddStringToHttpContext(errorMessage, TrafficWatchChangeType.Queries);
                        }
                    }
                    throw;
                }
            }
        }
Ejemplo n.º 12
0
 public async Task StreamQueryGet()
 {
     // ReSharper disable once ArgumentsStyleLiteral
     using (var tracker = new RequestTimeTracker(HttpContext, Logger, Database, "StreamQuery", doPerformanceHintIfTooLong: false))
         using (var token = CreateTimeLimitedQueryToken())
             using (Database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
             {
                 var    documentId    = GetStringQueryString("fromDocument", false);
                 string overrideQuery = null;
                 if (string.IsNullOrEmpty(documentId) == false)
                 {
                     Document document;
                     using (context.OpenReadTransaction())
                     {
                         document = Database.DocumentsStorage.Get(context, documentId);
                         if (document == null)
                         {
                             throw new DocumentDoesNotExistException($"Was request to stream a query taken from {documentId} document, but it does not exist.");
                         }
                         if (document.Data.TryGet("Query", out overrideQuery) == false)
                         {
                             throw new MissingFieldException($"Expected {documentId} to have a property named 'Query' of type 'String' but couldn't locate such property.");
                         }
                     }
                 }
                 var query = IndexQueryServerSide.Create(HttpContext, GetStart(), GetPageSize(), context, overrideQuery);
                 tracker.Query = query.Query;
                 var format          = GetStringQueryString("format", false);
                 var properties      = GetStringValuesQueryString("field", false);
                 var propertiesArray = properties.Count == 0 ? null : properties.ToArray();
                 using (var writer = GetQueryResultWriter(format, HttpContext.Response, context, ResponseBodyStream(), propertiesArray))
                 {
                     try
                     {
                         await Database.QueryRunner.ExecuteStreamQuery(query, context, HttpContext.Response, writer, token).ConfigureAwait(false);
                     }
                     catch (IndexDoesNotExistException)
                     {
                         HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                         writer.WriteError("Index " + query.Metadata.IndexName + " does not exists");
                     }
                 }
             }
 }
Ejemplo n.º 13
0
        private async Task Explain(DocumentsOperationContext context, RequestTimeTracker tracker, HttpMethod method)
        {
            var indexQuery = await GetIndexQuery(context, method);

            tracker.Query = indexQuery.Query;

            var explanations = Database.QueryRunner.ExplainDynamicIndexSelection(indexQuery);

            using (var writer = new AsyncBlittableJsonTextWriter(context, ResponseBodyStream(), Database.DatabaseShutdown))
            {
                writer.WriteStartObject();
                writer.WriteArray(context, "Results", explanations, (w, c, explanation) =>
                {
                    w.WriteExplanation(context, explanation);
                });
                writer.WriteEndObject();
                await writer.OuterFlushAsync();
            }
        }
Ejemplo n.º 14
0
        public async Task StreamQueryPost()
        {
            // ReSharper disable once ArgumentsStyleLiteral
            using (var tracker = new RequestTimeTracker(HttpContext, Logger, Database, "StreamQuery", doPerformanceHintIfTooLong: false))
                using (var token = CreateTimeLimitedQueryToken())
                    using (var queryContext = QueryOperationContext.Allocate(Database))
                    {
                        var stream    = TryGetRequestFromStream("ExportOptions") ?? RequestBodyStream();
                        var queryJson = await queryContext.Documents.ReadForMemoryAsync(stream, "index/query");

                        var query = IndexQueryServerSide.Create(HttpContext, queryJson, Database.QueryMetadataCache, tracker);

                        if (TrafficWatchManager.HasRegisteredClients)
                        {
                            var sb = new StringBuilder();
                            // append stringBuilder with the query
                            sb.Append(query.Query);
                            // if query got parameters append with parameters
                            if (query.QueryParameters != null && query.QueryParameters.Count > 0)
                            {
                                sb.AppendLine().Append(query.QueryParameters);
                            }
                            AddStringToHttpContext(sb.ToString(), TrafficWatchChangeType.Streams);
                        }

                        var format          = GetStringQueryString("format", false);
                        var debug           = GetStringQueryString("debug", false);
                        var properties      = GetStringValuesQueryString("field", false);
                        var propertiesArray = properties.Count == 0 ? null : properties.ToArray();

                        // set the exported file name prefix
                        var fileNamePrefix = query.Metadata.IsCollectionQuery ? query.Metadata.CollectionName + "_collection" : "query_result";
                        fileNamePrefix = $"{Database.Name}_{fileNamePrefix}";
                        if (string.IsNullOrWhiteSpace(debug) == false)
                        {
                            if (string.Equals(debug, "entries", StringComparison.OrdinalIgnoreCase))
                            {
                                using (var writer = GetIndexEntriesQueryResultWriter(format, HttpContext.Response, ResponseBodyStream(), propertiesArray, fileNamePrefix))
                                {
                                    try
                                    {
                                        await Database.QueryRunner.ExecuteStreamIndexEntriesQuery(query, queryContext, HttpContext.Response, writer, token).ConfigureAwait(false);
                                    }
                                    catch (IndexDoesNotExistException)
                                    {
                                        HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                                        writer.WriteError($"Index {query.Metadata.IndexName} does not exist");
                                    }
                                }
                            }
                            else
                            {
                                ThrowUnsupportedException($"You have selected {debug} debug mode, which is not supported.");
                            }
                        }
                        else
                        {
                            using (var writer = GetQueryResultWriter(format, HttpContext.Response, queryContext.Documents, ResponseBodyStream(), propertiesArray, fileNamePrefix))
                            {
                                try
                                {
                                    await Database.QueryRunner.ExecuteStreamQuery(query, queryContext, HttpContext.Response, writer, token).ConfigureAwait(false);
                                }
                                catch (IndexDoesNotExistException)
                                {
                                    HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                                    writer.WriteError($"Index {query.Metadata.IndexName} does not exist");
                                }
                            }
                        }
                    }
        }
Ejemplo n.º 15
0
        private async Task <IndexQueryServerSide> GetIndexQuery(JsonOperationContext context, HttpMethod method, RequestTimeTracker tracker)
        {
            if (method == HttpMethod.Get)
            {
                return(IndexQueryServerSide.Create(HttpContext, GetStart(), GetPageSize(), context, tracker));
            }

            var json = await context.ReadForMemoryAsync(RequestBodyStream(), "index/query");

            return(IndexQueryServerSide.Create(HttpContext, json, Database.QueryMetadataCache, tracker));
        }
Ejemplo n.º 16
0
        private async Task Query(DocumentsOperationContext context, OperationCancelToken token, RequestTimeTracker tracker, HttpMethod method)
        {
            var indexQuery = await GetIndexQuery(context, method, tracker);

            if (TrafficWatchManager.HasRegisteredClients)
            {
                TrafficWatchQuery(indexQuery);
            }

            var existingResultEtag = GetLongFromHeaders("If-None-Match");

            if (indexQuery.Metadata.HasFacet)
            {
                await FacetedQuery(indexQuery, context, token);

                return;
            }

            if (indexQuery.Metadata.HasSuggest)
            {
                await SuggestQuery(indexQuery, context, token);

                return;
            }

            var metadataOnly = GetBoolValueQueryString("metadataOnly", required: false) ?? false;

            DocumentQueryResult result;

            try
            {
                result = await Database.QueryRunner.ExecuteQuery(indexQuery, context, existingResultEtag, token).ConfigureAwait(false);
            }
            catch (IndexDoesNotExistException)
            {
                HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                return;
            }

            if (result.NotModified)
            {
                HttpContext.Response.StatusCode = (int)HttpStatusCode.NotModified;
                return;
            }

            HttpContext.Response.Headers[Constants.Headers.Etag] = CharExtensions.ToInvariantString(result.ResultEtag);

            int numberOfResults;

            using (var writer = new AsyncBlittableJsonTextWriter(context, ResponseBodyStream(), Database.DatabaseShutdown))
            {
                result.Timings  = indexQuery.Timings?.ToTimings();
                numberOfResults = await writer.WriteDocumentQueryResultAsync(context, result, metadataOnly);

                await writer.OuterFlushAsync();
            }

            Database.QueryMetadataCache.MaybeAddToCache(indexQuery.Metadata, result.IndexName);
            AddPagingPerformanceHint(PagingOperationType.Queries, $"{nameof(Query)} ({result.IndexName})", indexQuery.Query, numberOfResults, indexQuery.PageSize, result.DurationInMs);
        }
Ejemplo n.º 17
0
 public async Task StreamQueryGet()
 {
     // ReSharper disable once ArgumentsStyleLiteral
     using (var tracker = new RequestTimeTracker(HttpContext, Logger, Database, "StreamQuery", doPerformanceHintIfTooLong: false))
         using (var token = CreateTimeLimitedQueryToken())
             using (Database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
             {
                 var    documentId    = GetStringQueryString("fromDocument", false);
                 string overrideQuery = null;
                 if (string.IsNullOrEmpty(documentId) == false)
                 {
                     Document document;
                     using (context.OpenReadTransaction())
                     {
                         document = Database.DocumentsStorage.Get(context, documentId);
                         if (document == null)
                         {
                             throw new DocumentDoesNotExistException($"Was request to stream a query taken from {documentId} document, but it does not exist.");
                         }
                         if (document.Data.TryGet("Query", out overrideQuery) == false)
                         {
                             throw new MissingFieldException($"Expected {documentId} to have a property named 'Query' of type 'String' but couldn't locate such property.");
                         }
                     }
                 }
                 var query           = IndexQueryServerSide.Create(HttpContext, GetStart(), GetPageSize(), context, tracker, overrideQuery);
                 var format          = GetStringQueryString("format", false);
                 var debug           = GetStringQueryString("debug", false);
                 var properties      = GetStringValuesQueryString("field", false);
                 var propertiesArray = properties.Count == 0 ? null : properties.ToArray();
                 // set the exported file name prefix
                 var fileNamePrefix = query.Metadata.IsCollectionQuery ? query.Metadata.CollectionName + "_collection" : "query_result";
                 fileNamePrefix = $"{Database.Name}_{fileNamePrefix}";
                 if (string.IsNullOrWhiteSpace(debug) == false)
                 {
                     if (string.Equals(debug, "entries", StringComparison.OrdinalIgnoreCase))
                     {
                         using (var writer = GetIndexEntriesQueryResultWriter(format, HttpContext.Response, context, ResponseBodyStream(), propertiesArray, fileNamePrefix))
                         {
                             try
                             {
                                 await Database.QueryRunner.ExecuteStreamIndexEntriesQuery(query, context, HttpContext.Response, writer, token).ConfigureAwait(false);
                             }
                             catch (IndexDoesNotExistException)
                             {
                                 HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                                 writer.WriteError($"Index {query.Metadata.IndexName} does not exist");
                             }
                         }
                     }
                     else
                     {
                         ThrowUnsupportedException($"You have selected {debug} debug mode, which is not supported.");
                     }
                 }
                 else
                 {
                     using (var writer = GetQueryResultWriter(format, HttpContext.Response, context, ResponseBodyStream(), propertiesArray, fileNamePrefix))
                     {
                         try
                         {
                             await Database.QueryRunner.ExecuteStreamQuery(query, context, HttpContext.Response, writer, token).ConfigureAwait(false);
                         }
                         catch (IndexDoesNotExistException)
                         {
                             HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                             writer.WriteError($"Index {query.Metadata.IndexName} does not exist");
                         }
                     }
                 }
             }
 }
Ejemplo n.º 18
0
        public static IndexQueryServerSide Create(HttpContext httpContext, int start, int pageSize, JsonOperationContext context, RequestTimeTracker tracker, string overrideQuery = null)
        {
            IndexQueryServerSide result = null;

            try
            {
                var isQueryOverwritten = !string.IsNullOrEmpty(overrideQuery);
                if ((httpContext.Request.Query.TryGetValue("query", out var query) == false || query.Count == 0 || string.IsNullOrWhiteSpace(query[0])) &&
                    isQueryOverwritten == false)
                {
                    throw new InvalidOperationException("Missing mandatory query string parameter 'query'");
                }

                var actualQuery = isQueryOverwritten ? overrideQuery : query[0];
                result = new IndexQueryServerSide
                {
                    Query = Uri.UnescapeDataString(actualQuery),
                    // all defaults which need to have custom value
                    Start    = start,
                    PageSize = pageSize,
                };

                foreach (var item in httpContext.Request.Query)
                {
                    try
                    {
                        switch (item.Key)
                        {
                        case "query":
                            continue;

                        case "parameters":
                            using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(item.Value[0])))
                            {
                                result.QueryParameters = context.Read(stream, "query parameters");
                            }

                            continue;

                        case RequestHandler.StartParameter:
                        case RequestHandler.PageSizeParameter:
                            break;

                        case "waitForNonStaleResults":
                            result.WaitForNonStaleResults = bool.Parse(item.Value[0]);
                            break;

                        case "waitForNonStaleResultsTimeoutInMs":
                            result.WaitForNonStaleResultsTimeout = TimeSpan.FromMilliseconds(long.Parse(item.Value[0]));
                            break;

                        case "skipDuplicateChecking":
                            result.SkipDuplicateChecking = bool.Parse(item.Value[0]);
                            break;
                        }
                    }
                    catch (Exception e)
                    {
                        throw new ArgumentException($"Could not handle query string parameter '{item.Key}' (value: {item.Value}) for query: {result.Query}", e);
                    }
                }

                result.Metadata = new QueryMetadata(result.Query, result.QueryParameters, 0);
                if (result.Metadata.HasTimings)
                {
                    result.Timings = new QueryTimingsScope(start: false);
                }

                tracker.Query = result.Query;
                return(result);
            }
            catch (Exception e)
            {
                string errorMessage;
                if (e is InvalidOperationException || e is ArgumentException)
                {
                    errorMessage = e.Message;
                }
                else
                {
                    errorMessage = $"Failed to parse query: {result.Query}";
                }

                tracker.Query = errorMessage;
                if (TrafficWatchManager.HasRegisteredClients)
                {
                    AddStringToHttpContext(httpContext, errorMessage, TrafficWatchChangeType.Queries);
                }
                throw;
            }
        }
Ejemplo n.º 19
0
        private async Task Debug(QueryOperationContext queryContext, string debug, OperationCancelToken token, RequestTimeTracker tracker, HttpMethod method)
        {
            if (string.Equals(debug, "entries", StringComparison.OrdinalIgnoreCase))
            {
                await IndexEntries(queryContext, token, tracker, method);

                return;
            }

            if (string.Equals(debug, "explain", StringComparison.OrdinalIgnoreCase))
            {
                await Explain(queryContext, tracker, method);

                return;
            }

            if (string.Equals(debug, "serverSideQuery", StringComparison.OrdinalIgnoreCase))
            {
                await ServerSideQuery(queryContext, tracker, method);

                return;
            }

            if (string.Equals(debug, "graph", StringComparison.OrdinalIgnoreCase))
            {
                await Graph(queryContext, tracker, method);

                return;
            }

            if (string.Equals(debug, "detailedGraphResult", StringComparison.OrdinalIgnoreCase))
            {
                await DetailedGraphResult(queryContext, tracker, method);

                return;
            }
            throw new NotSupportedException($"Not supported query debug operation: '{debug}'");
        }
Ejemplo n.º 20
0
        private async Task Graph(DocumentsOperationContext context, RequestTimeTracker tracker, HttpMethod method)
        {
            var indexQuery = await GetIndexQuery(context, method, tracker);

            var queryRunner = Database.QueryRunner.GetRunner(indexQuery);

            if (!(queryRunner is GraphQueryRunner gqr))
            {
                throw new InvalidOperationException("The specified query is not a graph query.");
            }

            using (var token = CreateTimeLimitedQueryToken())
                using (Database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext ctx))
                {
                    var results = await gqr.GetAnalyzedQueryResults(indexQuery, ctx, null, token);

                    var nodes  = new DynamicJsonArray();
                    var edges  = new DynamicJsonArray();
                    var output = new DynamicJsonValue
                    {
                        ["Nodes"] = nodes,
                        ["Edges"] = edges
                    };

                    foreach (var item in results.Nodes)
                    {
                        var val = item.Value;
                        if (val is Document d)
                        {
                            d.EnsureMetadata();
                            val = d.Data;
                        }
                        nodes.Add(new DynamicJsonValue
                        {
                            ["Id"]    = item.Key,
                            ["Value"] = val
                        });
                    }

                    foreach (var edge in results.Edges)
                    {
                        var array = new DynamicJsonArray();
                        var djv   = new DynamicJsonValue
                        {
                            ["Name"]    = edge.Key,
                            ["Results"] = array
                        };
                        foreach (var item in edge.Value)
                        {
                            var edgeVal = item.Edge;
                            if (edgeVal is Document d)
                            {
                                edgeVal = d.Id?.ToString() ?? "anonymous/" + Guid.NewGuid();
                            }
                            array.Add(new DynamicJsonValue
                            {
                                ["From"] = item.Source,
                                ["To"]   = item.Destination,
                                ["Edge"] = edgeVal
                            });
                        }
                        edges.Add(djv);
                    }

                    using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        context.Write(writer, output);
                    }
                }
        }
Ejemplo n.º 21
0
        private async Task Debug(DocumentsOperationContext context, string debug, OperationCancelToken token, RequestTimeTracker tracker, HttpMethod method)
        {
            if (string.Equals(debug, "entries", StringComparison.OrdinalIgnoreCase))
            {
                await IndexEntries(context, token, tracker, method);

                return;
            }

            if (string.Equals(debug, "explain", StringComparison.OrdinalIgnoreCase))
            {
                await Explain(context, tracker, method);

                return;
            }

            throw new NotSupportedException($"Not supported query debug operation: '{debug}'");
        }
Ejemplo n.º 22
0
        private async Task Graph(QueryOperationContext queryContext, RequestTimeTracker tracker, HttpMethod method)
        {
            var indexQuery = await GetIndexQuery(queryContext.Documents, method, tracker);

            var queryRunner = Database.QueryRunner.GetRunner(indexQuery);

            if (!(queryRunner is GraphQueryRunner gqr))
            {
                throw new InvalidOperationException("The specified query is not a graph query.");
            }

            using (var token = CreateTimeLimitedQueryToken())
            {
                var results = await gqr.GetAnalyzedQueryResults(indexQuery, queryContext, null, token);

                var nodes  = new DynamicJsonArray();
                var edges  = new DynamicJsonArray();
                var output = new DynamicJsonValue
                {
                    ["Nodes"] = nodes,
                    ["Edges"] = edges
                };

                foreach (var item in results.Nodes)
                {
                    var val = item.Value;
                    if (val is Document d)
                    {
                        d.EnsureMetadata();
                        val = d.Data;
                    }
                    nodes.Add(new DynamicJsonValue
                    {
                        ["Id"]    = item.Key,
                        ["Value"] = val
                    });
                }
                var added = new HashSet <(string, string, object)>();
                foreach (var edge in results.Edges)
                {
                    added.Clear();
                    var array = new DynamicJsonArray();
                    var djv   = new DynamicJsonValue
                    {
                        ["Name"]    = edge.Key,
                        ["Results"] = array
                    };
                    foreach (var item in edge.Value)
                    {
                        var edgeVal = item.Edge;
                        if (edgeVal is Document d)
                        {
                            edgeVal = d.Id?.ToString() ?? "anonymous/" + Guid.NewGuid();
                        }
                        if (added.Add((item.Source, item.Destination, edgeVal)) == false)
                        {
                            continue;
                        }
                        array.Add(new DynamicJsonValue
                        {
                            ["From"] = item.Source,
                            ["To"]   = item.Destination,
                            ["Edge"] = edgeVal
                        });
                    }
                    edges.Add(djv);
                }

                await using (var writer = new AsyncBlittableJsonTextWriter(queryContext.Documents, ResponseBodyStream()))
                {
                    queryContext.Documents.Write(writer, output);
                }
            }
        }
Ejemplo n.º 23
0
        public static IndexQueryServerSide Create(
            HttpContext httpContext,
            BlittableJsonReaderObject json,
            QueryMetadataCache cache,
            RequestTimeTracker tracker,
            QueryType queryType = QueryType.Select)
        {
            IndexQueryServerSide result = null;

            try
            {
                result = JsonDeserializationServer.IndexQuery(json);

                if (result.PageSize == 0 && json.TryGet(nameof(PageSize), out int _) == false)
                {
                    result.PageSize = int.MaxValue;
                }

                if (string.IsNullOrWhiteSpace(result.Query))
                {
                    throw new InvalidOperationException($"Index query does not contain '{nameof(Query)}' field.");
                }

                if (cache.TryGetMetadata(result, out var metadataHash, out var metadata))
                {
                    result.Metadata = metadata;
                    return(result);
                }

                result.Metadata = new QueryMetadata(result.Query, result.QueryParameters, metadataHash, queryType);

                if (result.Metadata.HasTimings)
                {
                    result.Timings = new QueryTimingsScope(start: false);
                }

                if (tracker != null)
                {
                    tracker.Query = result.Query;
                }

                return(result);
            }
            catch (Exception e)
            {
                string errorMessage;
                if (e is InvalidOperationException)
                {
                    errorMessage = e.Message;
                }
                else
                {
                    errorMessage = (result == null ? $"Failed to parse index query : {json}" : $"Failed to parse query: {result.Query}");
                }

                if (tracker != null)
                {
                    tracker.Query = errorMessage;
                }
                if (TrafficWatchManager.HasRegisteredClients)
                {
                    AddStringToHttpContext(httpContext, errorMessage, TrafficWatchChangeType.Queries);
                }
                throw;
            }
        }
Ejemplo n.º 24
0
        private async Task Query(QueryOperationContext queryContext, OperationCancelToken token, RequestTimeTracker tracker, HttpMethod method, bool diagnostics)
        {
            var indexQuery = await GetIndexQuery(queryContext.Documents, method, tracker);

            indexQuery.Diagnostics        = diagnostics ? new List <string>() : null;
            indexQuery.AddTimeSeriesNames = GetBoolValueQueryString("addTimeSeriesNames", false) ?? false;

            queryContext.WithQuery(indexQuery.Metadata);

            if (TrafficWatchManager.HasRegisteredClients)
            {
                TrafficWatchQuery(indexQuery);
            }

            var existingResultEtag = GetLongFromHeaders("If-None-Match");

            if (indexQuery.Metadata.HasFacet)
            {
                await FacetedQuery(indexQuery, queryContext, token);

                return;
            }

            if (indexQuery.Metadata.HasSuggest)
            {
                await SuggestQuery(indexQuery, queryContext, token);

                return;
            }

            var metadataOnly = GetBoolValueQueryString("metadataOnly", required: false) ?? false;
            var shouldReturnServerSideQuery = GetBoolValueQueryString("includeServerSideQuery", required: false) ?? false;

            DocumentQueryResult result;

            try
            {
                result = await Database.QueryRunner.ExecuteQuery(indexQuery, queryContext, existingResultEtag, token).ConfigureAwait(false);
            }
            catch (IndexDoesNotExistException)
            {
                HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                return;
            }

            if (result.NotModified)
            {
                HttpContext.Response.StatusCode = (int)HttpStatusCode.NotModified;
                return;
            }

            HttpContext.Response.Headers[Constants.Headers.Etag] = CharExtensions.ToInvariantString(result.ResultEtag);

            long numberOfResults;
            long totalDocumentsSizeInBytes;

            await using (var writer = new AsyncBlittableJsonTextWriter(queryContext.Documents, ResponseBodyStream()))
            {
                result.Timings = indexQuery.Timings?.ToTimings();
                (numberOfResults, totalDocumentsSizeInBytes) = await writer.WriteDocumentQueryResultAsync(queryContext.Documents, result, metadataOnly, WriteAdditionalData(indexQuery, shouldReturnServerSideQuery), token.Token);
            }

            Database.QueryMetadataCache.MaybeAddToCache(indexQuery.Metadata, result.IndexName);
            AddPagingPerformanceHint(PagingOperationType.Queries, $"{nameof(Query)} ({result.IndexName})", indexQuery.Query, numberOfResults, indexQuery.PageSize, result.DurationInMs, totalDocumentsSizeInBytes);
        }
Ejemplo n.º 25
0
        private async Task IndexEntries(DocumentsOperationContext context, OperationCancelToken token, RequestTimeTracker tracker, HttpMethod method)
        {
            var indexQuery = await GetIndexQuery(context, method, tracker);

            var existingResultEtag = GetLongFromHeaders("If-None-Match");

            var result = await Database.QueryRunner.ExecuteIndexEntriesQuery(indexQuery, context, existingResultEtag, token);

            if (result.NotModified)
            {
                HttpContext.Response.StatusCode = (int)HttpStatusCode.NotModified;
                return;
            }

            HttpContext.Response.Headers[Constants.Headers.Etag] = CharExtensions.ToInvariantString(result.ResultEtag);

            using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
            {
                writer.WriteIndexEntriesQueryResult(context, result);
            }
        }
Ejemplo n.º 26
0
        private async Task <IndexQueryServerSide> GetIndexQuery(JsonOperationContext context, HttpMethod method, RequestTimeTracker tracker)
        {
            var addSpatialProperties = GetBoolValueQueryString("addSpatialProperties", required: false) ?? false;
            var clientQueryId        = GetStringQueryString("clientQueryId", required: false);

            if (method == HttpMethod.Get)
            {
                return(await IndexQueryServerSide.CreateAsync(HttpContext, GetStart(), GetPageSize(), context, tracker, addSpatialProperties, clientQueryId));
            }

            var json = await context.ReadForMemoryAsync(RequestBodyStream(), "index/query");

            return(IndexQueryServerSide.Create(HttpContext, json, Database.QueryMetadataCache, tracker, addSpatialProperties, clientQueryId, Database));
        }