Beispiel #1
0
        public async Task <XeroOAuth2Token> GetStoredToken(string tenantId = null)
        {
            var partitionKey = new PartitionKey(nameof(PartitionKeyValue.Xero));

            // strategy 1 by query
            async Task <Token> GetTheFirstOne()
            {
                var queryRequestOptions = new QueryRequestOptions()
                {
                    PartitionKey   = partitionKey,
                    MaxConcurrency = 1
                };

                var query = _container.GetItemQueryIterator <Token>(
                    "SELECT top 1 * FROM c",
                    requestOptions: queryRequestOptions);

                var feed = await query.ReadNextAsync();

                return(feed.FirstOrDefault());
            }

            // strategy 2 by read item
            async Task <Token> GetByTenantId()
            {
                var resp = await _container.ReadItemAsync <Token>(tenantId, partitionKey);

                return(resp);
            }

            var result = tenantId == null ? await GetTheFirstOne() : await GetByTenantId();

            if (result == null)
            {
                return(null);
            }

            // remap to XeroOAuth2Token object
            var xeroToken = result.IsOrMap <XeroOAuth2Token>();

            xeroToken.Tenants = new[] { result.Tenant }.ToList();

            return(xeroToken);
        }
Beispiel #2
0
 public override FeedIteratorInternal GetReadFeedIterator(QueryDefinition queryDefinition, QueryRequestOptions queryRequestOptions, string resourceLink, Documents.ResourceType resourceType, string continuationToken, int pageSize)
 {
     return(base.GetReadFeedIterator(queryDefinition, queryRequestOptions, resourceLink, resourceType, continuationToken, pageSize));
 }
Beispiel #3
0
        private async Task <ResponseMessage> ReadNextInternalAsync(
            CosmosDiagnosticsContext diagnostics,
            CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();

            Stream        stream    = null;
            OperationType operation = OperationType.ReadFeed;

            if (this.querySpec != null)
            {
                stream    = this.clientContext.SerializerCore.ToStreamSqlQuerySpec(this.querySpec, this.resourceType);
                operation = OperationType.Query;
            }

            if (this.feedTokenInternal == null)
            {
                TryCatch <FeedTokenInternal> tryCatchFeedTokeninternal = await this.TryInitializeFeedTokenAsync(cancellationToken);

                if (!tryCatchFeedTokeninternal.Succeeded)
                {
                    if (tryCatchFeedTokeninternal.Exception.InnerException is CosmosException cosmosException)
                    {
                        return(cosmosException.ToCosmosResponseMessage(new RequestMessage(method: null, requestUri: null, diagnosticsContext: diagnostics)));
                    }

                    return(CosmosExceptionFactory.CreateInternalServerErrorException(
                               message: tryCatchFeedTokeninternal.Exception.InnerException.Message,
                               innerException: tryCatchFeedTokeninternal.Exception.InnerException,
                               diagnosticsContext: diagnostics).ToCosmosResponseMessage(new RequestMessage(method: null, requestUri: null, diagnosticsContext: diagnostics)));
                }

                this.feedTokenInternal = tryCatchFeedTokeninternal.Result;
            }

            ResponseMessage response = await this.clientContext.ProcessResourceOperationStreamAsync(
                resourceUri : this.resourceLink,
                resourceType : this.resourceType,
                operationType : operation,
                requestOptions : this.requestOptions,
                cosmosContainerCore : null,
                partitionKey : this.requestOptions?.PartitionKey,
                streamPayload : stream,
                requestEnricher : request =>
            {
                QueryRequestOptions.FillContinuationToken(request, this.ContinuationToken);
                if (this.querySpec != null)
                {
                    request.Headers.Add(HttpConstants.HttpHeaders.ContentType, MediaTypes.QueryJson);
                    request.Headers.Add(HttpConstants.HttpHeaders.IsQuery, bool.TrueString);
                }

                this.feedTokenInternal?.EnrichRequest(request);
            },
                diagnosticsScope : diagnostics,
                cancellationToken : cancellationToken);

            // Retry in case of splits or other scenarios only on partitioned resources
            if (this.containerCore != null &&
                await this.feedTokenInternal.ShouldRetryAsync(this.containerCore, response, cancellationToken))
            {
                return(await this.ReadNextInternalAsync(diagnostics, cancellationToken));
            }

            if (response.IsSuccessStatusCode)
            {
                this.feedTokenInternal.UpdateContinuation(response.Headers.ContinuationToken);
                this.ContinuationToken      = this.feedTokenInternal.GetContinuation();
                this.hasMoreResultsInternal = !this.feedTokenInternal.IsDone;
            }
            else
            {
                this.hasMoreResultsInternal = false;
            }

            return(response);
        }
Beispiel #4
0
 public override IAsyncEnumerable <TryCatch <ReadFeedPage> > GetReadFeedAsyncEnumerable(
     ReadFeedCrossFeedRangeState state,
     QueryRequestOptions requestOptions = null)
 {
     return(base.GetReadFeedAsyncEnumerable(state, requestOptions));
 }
 /// <summary>
 /// This method creates a query for users under an database using a SQL statement. It returns a FeedIterator.
 /// For more information on preparing SQL statements with parameterized values, please see <see cref="QueryDefinition"/> overload.
 /// </summary>
 /// <param name="queryText">The cosmos SQL query text.</param>
 /// <param name="continuationToken">(Optional) The continuation token in the Azure Cosmos DB service.</param>
 /// <param name="requestOptions">(Optional) The options for the user query request <see cref="QueryRequestOptions"/></param>
 /// <returns>An iterator to go through the users</returns>
 /// <example>
 /// 1. This create the type feed iterator for users with queryText as input,
 /// <code language="c#">
 /// <![CDATA[
 /// string queryText = "SELECT * FROM c where c.id like '%testId%'";
 /// FeedIterator<UserProperties> resultSet = this.cosmosDatabase.GetUserQueryIterator<UserProperties>(queryText);
 /// while (feedIterator.HasMoreResults)
 /// {
 ///     FeedResponse<UserProperties> iterator = await feedIterator.ReadNextAsync(this.cancellationToken);
 /// }
 /// ]]>
 /// </code>
 /// </example>
 /// <example>
 /// 2. This create the type feed iterator for users without queryText, retrieving all users.
 /// <code language="c#">
 /// <![CDATA[
 /// FeedIterator<UserProperties> resultSet = this.cosmosDatabase.GetUserQueryIterator<ContainerProperties>();
 /// while (feedIterator.HasMoreResults)
 /// {
 ///     FeedResponse<UserProperties> iterator =
 ///     await feedIterator.ReadNextAsync(this.cancellationToken);
 /// }
 /// ]]>
 /// </code>
 /// </example>
 public abstract FeedIterator <T> GetUserQueryIterator <T>(
     string queryText                   = null,
     string continuationToken           = null,
     QueryRequestOptions requestOptions = null);
 /// <summary>
 /// This method creates a query for users under an database using a SQL statement. It returns a FeedIterator.
 /// For more information on preparing SQL statements with parameterized values, please see <see cref="QueryDefinition"/> overload.
 /// </summary>
 /// <param name="queryDefinition">The cosmos SQL query definition.</param>
 /// <param name="continuationToken">(Optional) The continuation token in the Azure Cosmos DB service.</param>
 /// <param name="requestOptions">(Optional) The options for the user query request <see cref="QueryRequestOptions"/></param>
 /// <returns>An iterator to go through the users</returns>
 /// <example>
 /// This create the type feed iterator for users with queryDefinition as input.
 /// <code language="c#">
 /// <![CDATA[
 /// string queryText = "SELECT * FROM c where c.id like @testId";
 /// QueryDefinition queryDefinition = new QueryDefinition(queryText);
 /// queryDefinition.WithParameter("@testId", "testUserId");
 /// FeedIterator<UserProperties> resultSet = this.cosmosDatabase.GetUserQueryIterator<UserProperties>(queryDefinition);
 /// while (feedIterator.HasMoreResults)
 /// {
 ///     foreach (UserProperties properties in await feedIterator.ReadNextAsync())
 ///     {
 ///         Console.WriteLine(properties.Id);
 ///     }
 /// }
 /// ]]>
 /// </code>
 /// </example>
 public abstract FeedIterator <T> GetUserQueryIterator <T>(
     QueryDefinition queryDefinition,
     string continuationToken           = null,
     QueryRequestOptions requestOptions = null);
 /// <summary>
 /// This method creates a query for containers under an database using a SQL statement. It returns a FeedIterator.
 /// For more information on preparing SQL statements with parameterized values, please see <see cref="QueryDefinition"/> overload.
 /// </summary>
 /// <param name="queryDefinition">The cosmos SQL query definition.</param>
 /// <param name="continuationToken">The continuation token in the Azure Cosmos DB service.</param>
 /// <param name="requestOptions">(Optional) The options for the container request <see cref="QueryRequestOptions"/></param>
 /// <returns>An iterator to go through the containers</returns>
 /// <example>
 /// This create the stream feed iterator for containers with queryDefinition as input.
 /// <code language="c#">
 /// <![CDATA[
 /// string queryText = "SELECT * FROM c where c.id like '%testId%'";
 /// QueryDefinition queryDefinition = new QueryDefinition(queryText);
 /// FeedIterator resultSet = this.cosmosDatabase.GetContainerQueryStreamIterator(queryDefinition);
 /// while (feedIterator.HasMoreResults)
 /// {
 ///     using (ResponseMessage response = await feedIterator.ReadNextAsync())
 ///     {
 ///         using (StreamReader sr = new StreamReader(response.Content))
 ///         using (JsonTextReader jtr = new JsonTextReader(sr))
 ///         {
 ///             JObject result = JObject.Load(jtr);
 ///         }
 ///     }
 /// }
 /// ]]>
 /// </code>
 /// </example>
 /// <remarks>
 /// Refer to https://docs.microsoft.com/azure/cosmos-db/sql-query-getting-started for syntax and examples.
 /// <para>
 /// <see cref="Container.ReadContainerStreamAsync(ContainerRequestOptions, CancellationToken)" /> is recommended for single container look-up.
 /// </para>
 /// </remarks>
 public abstract FeedIterator GetContainerQueryStreamIterator(
     QueryDefinition queryDefinition,
     string continuationToken           = null,
     QueryRequestOptions requestOptions = null);
 /// <summary>
 /// This method creates a query for containers under an database using a SQL statement. It returns a FeedIterator.
 /// For more information on preparing SQL statements with parameterized values, please see <see cref="QueryDefinition"/> overload.
 /// </summary>
 /// <param name="queryText">The cosmos SQL query text.</param>
 /// <param name="continuationToken">The continuation token in the Azure Cosmos DB service.</param>
 /// <param name="requestOptions">(Optional) The options for the container request <see cref="QueryRequestOptions"/></param>
 /// <returns>An iterator to go through the containers</returns>
 /// <example>
 /// 1. This create the stream feed iterator for containers with queryText as input.
 /// <code language="c#">
 /// <![CDATA[
 /// string queryText = "SELECT * FROM c where c.id like '%testId%'";
 /// FeedIterator resultSet = this.cosmosDatabase.GetContainerQueryStreamIterator(queryText);
 /// while (feedIterator.HasMoreResults)
 /// {
 /// ResponseMessage iterator =
 /// await feedIterator.ReadNextAsync(this.cancellationToken);
 /// }
 /// ]]>
 /// </code>
 /// </example>
 /// <example>
 /// 2. This create the stream feed iterator for containers without queryText, retrieving all container.
 /// <code language="c#">
 /// <![CDATA[
 /// FeedIterator resultSet = this.cosmosDatabase.GetContainerQueryStreamIterator();
 /// while (feedIterator.HasMoreResults)
 /// {
 /// ResponseMessage iterator =
 /// await feedIterator.ReadNextAsync(this.cancellationToken);
 /// }
 /// ]]>
 /// </code>
 /// </example>
 /// <remarks>
 /// Refer to https://docs.microsoft.com/azure/cosmos-db/sql-query-getting-started for syntax and examples.
 /// <para>
 /// <see cref="Container.ReadContainerStreamAsync(ContainerRequestOptions, CancellationToken)" /> is recommended for single container look-up.
 /// </para>
 /// </remarks>
 public abstract FeedIterator GetContainerQueryStreamIterator(
     string queryText                   = null,
     string continuationToken           = null,
     QueryRequestOptions requestOptions = null);
 public abstract FeedIteratorInternal GetItemQueryStreamIteratorInternal(
     SqlQuerySpec sqlQuerySpec,
     bool isContinuationExcpected,
     string continuationToken,
     FeedRangeInternal feedRange,
     QueryRequestOptions requestOptions);
        /// <summary>
        /// Used in the compute gateway to support legacy gateway interface.
        /// </summary>
        public override async Task <TryExecuteQueryResult> TryExecuteQueryAsync(
            QueryFeatures supportedQueryFeatures,
            QueryDefinition queryDefinition,
            string continuationToken,
            FeedRangeInternal feedRangeInternal,
            QueryRequestOptions requestOptions,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (queryDefinition == null)
            {
                throw new ArgumentNullException(nameof(queryDefinition));
            }

            if (requestOptions == null)
            {
                throw new ArgumentNullException(nameof(requestOptions));
            }

            if (feedRangeInternal != null)
            {
                // The user has scoped down to a physical partition or logical partition.
                // In either case let the query execute as a passthrough.
                QueryIterator passthroughQueryIterator = QueryIterator.Create(
                    client: this.queryClient,
                    clientContext: this.ClientContext,
                    sqlQuerySpec: queryDefinition.ToSqlQuerySpec(),
                    continuationToken: continuationToken,
                    feedRangeInternal: feedRangeInternal,
                    queryRequestOptions: requestOptions,
                    resourceLink: this.LinkUri,
                    isContinuationExpected: false,
                    allowNonValueAggregateQuery: true,
                    forcePassthrough: true, // Forcing a passthrough, since we don't want to get the query plan nor try to rewrite it.
                    partitionedQueryExecutionInfo: null);

                return(new QueryPlanIsSupportedResult(passthroughQueryIterator));
            }

            cancellationToken.ThrowIfCancellationRequested();

            Documents.PartitionKeyDefinition partitionKeyDefinition;
            if (requestOptions.Properties != null &&
                requestOptions.Properties.TryGetValue("x-ms-query-partitionkey-definition", out object partitionKeyDefinitionObject))
            {
                if (partitionKeyDefinitionObject is Documents.PartitionKeyDefinition definition)
                {
                    partitionKeyDefinition = definition;
                }
                else
                {
                    throw new ArgumentException(
                              "partitionkeydefinition has invalid type",
                              nameof(partitionKeyDefinitionObject));
                }
            }
            else
            {
                ContainerQueryProperties containerQueryProperties = await this.queryClient.GetCachedContainerQueryPropertiesAsync(
                    this.LinkUri,
                    requestOptions.PartitionKey,
                    cancellationToken);

                partitionKeyDefinition = containerQueryProperties.PartitionKeyDefinition;
            }

            QueryPlanHandler queryPlanHandler = new QueryPlanHandler(this.queryClient);

            TryCatch <(PartitionedQueryExecutionInfo queryPlan, bool supported)> tryGetQueryInfoAndIfSupported = await queryPlanHandler.TryGetQueryInfoAndIfSupportedAsync(
                supportedQueryFeatures,
                queryDefinition.ToSqlQuerySpec(),
                partitionKeyDefinition,
                requestOptions.PartitionKey.HasValue,
                cancellationToken);

            if (tryGetQueryInfoAndIfSupported.Failed)
            {
                return(new FailedToGetQueryPlanResult(tryGetQueryInfoAndIfSupported.Exception));
            }

            (PartitionedQueryExecutionInfo queryPlan, bool supported) = tryGetQueryInfoAndIfSupported.Result;
            TryExecuteQueryResult tryExecuteQueryResult;

            if (supported)
            {
                QueryIterator queryIterator = QueryIterator.Create(
                    client: this.queryClient,
                    clientContext: this.ClientContext,
                    sqlQuerySpec: queryDefinition.ToSqlQuerySpec(),
                    continuationToken: continuationToken,
                    feedRangeInternal: feedRangeInternal,
                    queryRequestOptions: requestOptions,
                    resourceLink: this.LinkUri,
                    isContinuationExpected: false,
                    allowNonValueAggregateQuery: true,
                    forcePassthrough: false,
                    partitionedQueryExecutionInfo: queryPlan);

                tryExecuteQueryResult = new QueryPlanIsSupportedResult(queryIterator);
            }
            else
            {
                tryExecuteQueryResult = new QueryPlanNotSupportedResult(queryPlan);
            }

            return(tryExecuteQueryResult);
        }
 public abstract FeedIterator <T> GetItemQueryIterator <T>(
     FeedRange feedRange,
     QueryDefinition queryDefinition,
     string continuationToken           = null,
     QueryRequestOptions requestOptions = null);
 public abstract FeedIterator GetItemQueryStreamIterator(
     FeedRange feedRange,
     QueryDefinition queryDefinition,
     string continuationToken,
     QueryRequestOptions requestOptions = null);
 public abstract IAsyncEnumerable <TryCatch <ReadFeedPage> > GetReadFeedAsyncEnumerable(
     ReadFeedCrossFeedRangeState state,
     QueryRequestOptions requestOptions = null);
Beispiel #14
0
        /// <summary>
        /// Used in the compute gateway to support legacy gateway interface.
        /// </summary>
        internal override async Task <((Exception, PartitionedQueryExecutionInfo), (bool, QueryIterator))> TryExecuteQueryAsync(
            QueryFeatures supportedQueryFeatures,
            QueryDefinition queryDefinition,
            string continuationToken,
            FeedRangeInternal feedRangeInternal,
            QueryRequestOptions requestOptions,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (queryDefinition == null)
            {
                throw new ArgumentNullException(nameof(queryDefinition));
            }

            if (requestOptions == null)
            {
                throw new ArgumentNullException(nameof(requestOptions));
            }

            cancellationToken.ThrowIfCancellationRequested();

            Documents.PartitionKeyDefinition partitionKeyDefinition;
            if (requestOptions.Properties != null &&
                requestOptions.Properties.TryGetValue("x-ms-query-partitionkey-definition", out object partitionKeyDefinitionObject))
            {
                if (partitionKeyDefinitionObject is Documents.PartitionKeyDefinition definition)
                {
                    partitionKeyDefinition = definition;
                }
                else
                {
                    throw new ArgumentException(
                              "partitionkeydefinition has invalid type",
                              nameof(partitionKeyDefinitionObject));
                }
            }
            else
            {
                ContainerQueryProperties containerQueryProperties = await this.queryClient.GetCachedContainerQueryPropertiesAsync(
                    this.LinkUri,
                    requestOptions.PartitionKey,
                    cancellationToken);

                partitionKeyDefinition = containerQueryProperties.PartitionKeyDefinition;
            }

            QueryPlanHandler queryPlanHandler = new QueryPlanHandler(this.queryClient);

            ((Exception exception, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo), bool supported) = await queryPlanHandler.TryGetQueryInfoAndIfSupportedAsync(
                supportedQueryFeatures,
                queryDefinition.ToSqlQuerySpec(),
                partitionKeyDefinition,
                requestOptions.PartitionKey.HasValue,
                cancellationToken);

            if (exception != null)
            {
                return((exception, null), (false, null));
            }

            QueryIterator queryIterator;

            if (supported)
            {
                queryIterator = QueryIterator.Create(
                    client: this.queryClient,
                    clientContext: this.ClientContext,
                    sqlQuerySpec: queryDefinition.ToSqlQuerySpec(),
                    continuationToken: continuationToken,
                    feedRangeInternal: feedRangeInternal,
                    queryRequestOptions: requestOptions,
                    resourceLink: this.LinkUri,
                    isContinuationExpected: false,
                    allowNonValueAggregateQuery: true,
                    partitionedQueryExecutionInfo: partitionedQueryExecutionInfo);
            }
            else
            {
                queryIterator = null;
            }

            return((null, partitionedQueryExecutionInfo), (supported, queryIterator));
        }
Beispiel #15
0
        public override IOrderedQueryable <T> CreateItemQuery <T>(object partitionKey = null, bool allowSynchronousQueryExecution = false, QueryRequestOptions requestOptions = null)
        {
            requestOptions = requestOptions != null ? requestOptions : new QueryRequestOptions();
            if (partitionKey != null)
            {
                requestOptions.PartitionKey = new PartitionKey(partitionKey);
            }
            else
            {
                requestOptions.EnableCrossPartitionQuery = true;
            }

            return(new CosmosLinqQuery <T>(this, this.ClientContext.CosmosSerializer, this.queryClient, requestOptions, allowSynchronousQueryExecution));
        }