예제 #1
0
 /// <summary>
 /// Get the partitions for a specific table
 /// </summary>
 /// <param name="tableName">The name of the table</param>
 /// <param name="canHandleMultiplePartitions">True if the caller can handle getting multiple partitions</param>
 /// <param name="sqlTree">The SQL tree that can be modified to give the user the correct partitions</param>
 /// <param name="httpContext">The http context that contains user information etc.</param>
 /// <returns></returns>
 public virtual Task <IImmutableList <Partition> > GetPartitions(bool canHandleMultiplePartitions, PartitionsBuilder partitionsBuilder, HttpContext httpContext, PartitionOptions partitionOptions)
 {
     return(Task.FromResult <IImmutableList <Partition> >(ImmutableList.Create <Partition>(partitionsBuilder.NewPartition().Build())));
 }
예제 #2
0
        public async Task <Transport.TransportPartitionsResult> GetPartitions(bool canHandlePartitions, string sql, SqlParameters sqlParameters, HttpContext httpContext)
        {
            var sqlTree = _sqlParser.Parse(sql, out var errors);

            foreach (var header in httpContext.Request.Headers)
            {
                if (header.Key.StartsWith("P_", StringComparison.OrdinalIgnoreCase))
                {
                    var parameterName = header.Key.Substring(2);

                    if (header.Value.Count > 1)
                    {
                        throw new SqlErrorException("Two parameters found with the same name in the http headers.");
                    }
                    var value = header.Value.First();

                    var base64Value = Convert.ToBase64String(Encoding.UTF8.GetBytes(value));

                    //Add the parameter as base64 inline parameter
                    sqlTree.Statements.Insert(0, new SetVariableStatement()
                    {
                        VariableReference = new SqlParser.Expressions.VariableReference()
                        {
                            Name = parameterName
                        },
                        ScalarExpression = new Base64Literal()
                        {
                            Value = base64Value
                        }
                    });
                }
            }

            if (errors.Count > 0)
            {
                throw new SqlErrorException(errors.First().Message);
            }

            //Apply the row level security filter on the query
            await RowLevelSecurityHelper.ApplyRowLevelSecurity(sqlTree, httpContext, _metadataStore, _serviceProvider);

            var schema = _sqlExecutor.GetSchema(sqlTree, sqlParameters);

            //Take table name and get the partition resolver
            if (!_metadataStore.TryGetTable(schema.TableName, out var table))
            {
                throw new SqlErrorException($"The table {schema.TableName} was not found.");
            }

            //Get the partitions
            var discoveryService  = _serviceProvider.GetService <IDiscoveryService>();
            var partitionsBuilder = new PartitionsBuilder(sqlTree);
            var partitions        = await table.PartitionResolver.GetPartitions(canHandlePartitions, partitionsBuilder, httpContext, new PartitionOptions(_serviceProvider, discoveryService));

            var partitionListBuilder = ImmutableList.CreateBuilder <Transport.TransportPartition>();

            foreach (var partition in partitions)
            {
                List <TransportServiceLocation> locations = new List <TransportServiceLocation>();
                foreach (var location in partition.Locations)
                {
                    locations.Add(new TransportServiceLocation(location.Host, location.Tls));
                }
                partitionListBuilder.Add(new Transport.TransportPartition(locations, partition.SqlTree.Print()));
            }

            return(new Transport.TransportPartitionsResult(ConvertColumns(schema.Columns), partitionListBuilder.ToImmutable()));
        }