コード例 #1
0
        public async Task <(bool success, IReadOnlyCollection <object> results)> RunAsync(IDocumentStore documentStore, Connection connection, QueryParts queryParts, bool logStats, ILogger logger, CancellationToken cancellationToken, Dictionary <string, IReadOnlyCollection <object> > variables = null)
        {
            try
            {
                if (!queryParts.IsValidQuery())
                {
                    logger.LogError("Invalid Query. Aborting Select.");
                    return(false, null);
                }
                var results = await documentStore.ExecuteAsync(connection.Database, queryParts.CollectionName,
                                                               async (IDocumentExecuteContext context) =>
                {
                    var queryOptions = new QueryOptions
                    {
                        PopulateQueryMetrics      = true,
                        EnableCrossPartitionQuery = true,
                        MaxBufferedItemCount      = 200,
                        MaxItemCount = -1,
                    };
                    var rawQuery = queryParts.ToRawQuery();
                    if (variables != null && variables.Any() && queryParts.HasVariablesInWhereClause())
                    {
                        rawQuery = _variableInjectionTask.InjectVariables(rawQuery, variables, logger);
                    }
                    var query = context.QueryAsSql <object>(rawQuery, queryOptions);
                    return(await query.ConvertAndLogRequestUnits(logStats, logger));
                }, cancellationToken);

                if (variables != null && !string.IsNullOrEmpty(queryParts.CleanVariableName))
                {
                    if (variables.ContainsKey(queryParts.CleanVariableName))
                    {
                        throw new Exception($"Variable {queryParts.CleanVariableName} has already been defined and used. Please use another variable name.");
                    }
                    else
                    {
                        variables.Add(queryParts.CleanVariableName, results);
                    }
                }

                return(true, results);
            }
            catch (Exception ex)
            {
                logger.Log(LogLevel.Error, new EventId(), $"Unable to run {Constants.QueryParsingKeywords.SELECT} query", ex);
                return(false, null);
            }
        }
コード例 #2
0
        public async Task <(bool success, IReadOnlyCollection <object> results)> RunAsync(IDocumentStore documentStore, Connection connection, QueryParts queryParts, bool logStats, ILogger logger, CancellationToken cancellationToken, Dictionary <string, IReadOnlyCollection <object> > variables = null)
        {
            try
            {
                if (!queryParts.IsValidQuery())
                {
                    logger.LogError("Invalid Query. Aborting Delete.");
                    return(false, null);
                }

                //get the ids
                var selectQuery = queryParts.ToRawSelectQuery();
                var results     = await documentStore.ExecuteAsync(connection.Database, queryParts.CollectionName,
                                                                   async (IDocumentExecuteContext context) =>
                {
                    var queryOptions = new QueryOptions
                    {
                        PopulateQueryMetrics      = true,
                        EnableCrossPartitionQuery = true,
                        MaxBufferedItemCount      = 200,
                        MaxDegreeOfParallelism    = MAX_DEGREE_PARALLEL,
                        MaxItemCount = -1,
                    };
                    if (variables != null && variables.Any() && queryParts.HasVariablesInWhereClause())
                    {
                        selectQuery = _variableInjectionTask.InjectVariables(selectQuery, variables, logger);
                    }
                    var query = context.QueryAsSql <object>(selectQuery, queryOptions);
                    return(await query.ConvertAndLogRequestUnits(false, logger));
                }, cancellationToken);

                var fromObjects = JArray.FromObject(results);
                if (queryParts.IsTransaction)
                {
                    logger.LogInformation($"Transaction Created. TransactionId: {queryParts.TransactionId}");
                    await _transactionTask.BackuQueryAsync(connection.Name, connection.Database, queryParts.CollectionName, queryParts.TransactionId, queryParts.CleanOrginalQuery);
                }
                var partitionKeyPath = await documentStore.LookupPartitionKeyPath(connection.Database, queryParts.CollectionName);

                var deleteCount = 0;
                var actionTransactionCacheBlock = new ActionBlock <JObject>(async document =>
                {
                    await documentStore.ExecuteAsync(connection.Database, queryParts.CollectionName,
                                                     async(IDocumentExecuteContext context) =>
                    {
                        if (cancellationToken.IsCancellationRequested)
                        {
                            throw new TaskCanceledException("Task has been requested to cancel.");
                        }
                        var documentId = document[Constants.DocumentFields.ID].ToString();

                        if (queryParts.IsTransaction)
                        {
                            var backupResult = await _transactionTask.BackupAsync(context, connection.Name, connection.Database, queryParts.CollectionName, queryParts.TransactionId, logger, null, document);
                            if (!backupResult.isSuccess)
                            {
                                logger.LogError($"Unable to backup document {documentId}. Skipping Delete.");
                                return(false);
                            }
                        }

                        var partionKeyValue = document.SelectToken(partitionKeyPath).ToString();
                        var deleted         = await context.DeleteAsync(documentId.CleanId(), new RequestOptions
                        {
                            PartitionKey = partionKeyValue
                        });
                        if (deleted)
                        {
                            Interlocked.Increment(ref deleteCount);
                            logger.LogInformation($"Deleted {documentId}");
                        }
                        else
                        {
                            logger.LogInformation($"Document {documentId} unable to be deleted.");
                        }
                        return(true);
                    }, cancellationToken);
                },
                                                                            new ExecutionDataflowBlockOptions
                {
                    MaxDegreeOfParallelism = MAX_DEGREE_PARALLEL,
                    CancellationToken      = cancellationToken
                });

                foreach (JObject doc in fromObjects)
                {
                    actionTransactionCacheBlock.Post(doc);
                }
                actionTransactionCacheBlock.Complete();
                await actionTransactionCacheBlock.Completion;
                logger.LogInformation($"Deleted {deleteCount} out of {fromObjects.Count}");
                if (queryParts.IsTransaction && deleteCount > 0)
                {
                    logger.LogInformation($"To rollback execute: ROLLBACK {queryParts.TransactionId}");
                }
                return(true, null);
            }
            catch (Exception ex)
            {
                logger.Log(LogLevel.Error, new EventId(), $"Unable to run {Constants.QueryParsingKeywords.DELETE} query", ex);
                return(false, null);
            }
        }
コード例 #3
0
        public async Task <(bool success, IReadOnlyCollection <object> results)> RunAsync(IDocumentStore documentStore, Connection connection, QueryParts queryParts, bool logStats, ILogger logger, CancellationToken cancellationToken, Dictionary <string, IReadOnlyCollection <object> > variables = null)
        {
            try
            {
                if (!queryParts.IsValidQuery())
                {
                    logger.LogError("Invalid Query. Aborting Update.");
                    return(false, null);
                }

                if (queryParts.IsReplaceUpdateQuery())
                {
                    logger.LogError($"Full document updating not supported in SELECT/WHERE queries. To update those documents use an update by documentId query. Skipping Update.");
                    return(false, null);
                }
                //get the ids
                var selectQuery = queryParts.ToRawSelectQuery();
                var results     = await documentStore.ExecuteAsync(connection.Database, queryParts.CollectionName,
                                                                   async (IDocumentExecuteContext context) =>
                {
                    var queryOptions = new QueryOptions
                    {
                        PopulateQueryMetrics      = true,
                        EnableCrossPartitionQuery = true,
                        MaxBufferedItemCount      = 200,
                        MaxDegreeOfParallelism    = MAX_DEGREE_PARALLEL,
                        MaxItemCount = -1,
                    };

                    if (variables != null && variables.Any() && queryParts.HasVariablesInWhereClause())
                    {
                        selectQuery = _variableInjectionTask.InjectVariables(selectQuery, variables, logger);
                    }

                    var query = context.QueryAsSql <object>(selectQuery, queryOptions);
                    return(await query.ConvertAndLogRequestUnits(false, logger));
                }, cancellationToken);

                var fromObjects = JArray.FromObject(results);
                if (queryParts.IsTransaction)
                {
                    logger.LogInformation($"Transaction Created. TransactionId: {queryParts.TransactionId}");
                    await _transactionTask.BackuQueryAsync(connection.Name, connection.Database, queryParts.CollectionName, queryParts.TransactionId, queryParts.CleanOrginalQuery);
                }
                var partitionKeyPath = await documentStore.LookupPartitionKeyPath(connection.Database, queryParts.CollectionName);

                var updateCount = 0;
                var actionTransactionCacheBlock = new ActionBlock <JObject>(async document =>
                {
                    await documentStore.ExecuteAsync(connection.Database, queryParts.CollectionName,
                                                     async(IDocumentExecuteContext context) =>
                    {
                        if (cancellationToken.IsCancellationRequested)
                        {
                            throw new TaskCanceledException("Task has been requested to cancel.");
                        }
                        var documentId = document[Constants.DocumentFields.ID].ToString();

                        if (queryParts.IsTransaction)
                        {
                            var backupResult = await _transactionTask.BackupAsync(context, connection.Name, connection.Database, queryParts.CollectionName, queryParts.TransactionId, logger, null, document);
                            if (!backupResult.isSuccess)
                            {
                                logger.LogError($"Unable to backup document {documentId}. Skipping Update.");
                                return(false);
                            }
                        }

                        var partionKeyValue = document.SelectToken(partitionKeyPath).ToString();

                        var partialDoc = JObject.Parse(queryParts.CleanQueryUpdateBody);
                        //ensure the partial update is not trying to update id or the partition key
                        var pToken  = partialDoc.SelectToken(partitionKeyPath);
                        var idToken = partialDoc.SelectToken(Constants.DocumentFields.ID);
                        if (pToken != null || idToken != null)
                        {
                            logger.LogError($"Updates are not allowed on ids or existing partition keys of a document. Skipping updated for document {documentId}.");
                            return(false);
                        }
                        var shouldUpdateToEmptyArray = partialDoc.HasEmptyJArray();
                        document.Merge(partialDoc, new JsonMergeSettings
                        {
                            MergeArrayHandling     = shouldUpdateToEmptyArray ? MergeArrayHandling.Replace : MergeArrayHandling.Merge,
                            MergeNullValueHandling = MergeNullValueHandling.Merge
                        });

                        //save
                        var updatedDoc = await context.UpdateAsync(document, new RequestOptions
                        {
                            PartitionKey = partionKeyValue
                        });
                        if (updatedDoc != null)
                        {
                            Interlocked.Increment(ref updateCount);
                            logger.LogInformation($"Updated {documentId}");
                        }
                        else
                        {
                            logger.LogInformation($"Document {documentId} unable to be updated.");
                        }
                        return(true);
                    }, cancellationToken);
                },
                                                                            new ExecutionDataflowBlockOptions
                {
                    MaxDegreeOfParallelism = MAX_DEGREE_PARALLEL,
                    CancellationToken      = cancellationToken
                });

                foreach (JObject doc in fromObjects)
                {
                    actionTransactionCacheBlock.Post(doc);
                }
                actionTransactionCacheBlock.Complete();
                await actionTransactionCacheBlock.Completion;
                logger.LogInformation($"Updated {updateCount} out of {fromObjects.Count}");
                if (queryParts.IsTransaction && updateCount > 0)
                {
                    logger.LogInformation($"To rollback execute: ROLLBACK {queryParts.TransactionId}");
                }
                return(true, null);
            }
            catch (Exception ex)
            {
                logger.Log(LogLevel.Error, new EventId(), $"Unable to run {Constants.QueryParsingKeywords.DELETE} query", ex);
                return(false, null);
            }
        }