-
Notifications
You must be signed in to change notification settings - Fork 207
/
Copy pathSqlExecuteQueryStructure.cs
79 lines (75 loc) · 4.06 KB
/
SqlExecuteQueryStructure.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System.Net;
using Azure.DataApiBuilder.Auth;
using Azure.DataApiBuilder.Config.DatabasePrimitives;
using Azure.DataApiBuilder.Core.Models;
using Azure.DataApiBuilder.Core.Services;
using Azure.DataApiBuilder.Service.Exceptions;
namespace Azure.DataApiBuilder.Core.Resolvers
{
///<summary>
/// Wraps all the required data and logic to write a SQL EXECUTE query
///</summary>
public class SqlExecuteStructure : BaseSqlQueryStructure
{
// Holds the final, resolved parameters that will be passed when building the execute stored procedure query
// Keys are the stored procedure arguments (e.g. @id, @username...)
// Values are the engine-generated referencing parameters (e.g. @param0, @param1...)
public Dictionary<string, object> ProcedureParameters { get; set; }
/// <summary>
/// Constructs a structure with all needed components to build an EXECUTE stored procedure call
/// requestParams will be resolved from either the request querystring or body by this point
/// Construct the ProcedureParameters dictionary through resolving requestParams and defaults from config/metadata
/// Also performs type checking at this stage instead of in RequestValidator to prevent code duplication
/// </summary>
public SqlExecuteStructure(
string entityName,
ISqlMetadataProvider sqlMetadataProvider,
IAuthorizationResolver authorizationResolver,
GQLFilterParser gQLFilterParser,
IDictionary<string, object?> requestParams)
: base(sqlMetadataProvider, authorizationResolver, gQLFilterParser, entityName: entityName)
{
StoredProcedureDefinition storedProcedureDefinition = GetUnderlyingStoredProcedureDefinition();
ProcedureParameters = new();
foreach ((string paramKey, ParameterDefinition paramDefinition) in storedProcedureDefinition.Parameters)
{
Type systemType = GetUnderlyingStoredProcedureDefinition().Parameters[paramKey].SystemType!;
// Populate with request param if able
if (requestParams.TryGetValue(paramKey, out object? requestParamValue))
{
// Parameterize, then add referencing parameter to ProcedureParameters dictionary
string? parametrizedName = null;
if (requestParamValue is not null)
{
parametrizedName = MakeDbConnectionParam(GetParamAsSystemType(requestParamValue.ToString()!, paramKey, systemType), paramKey);
}
else
{
parametrizedName = MakeDbConnectionParam(value: null, paramKey);
}
ProcedureParameters.Add(paramKey, $"{parametrizedName}");
}
else
{
// Fill with default value from runtime config
if (paramDefinition.HasConfigDefault)
{
object? value = paramDefinition.ConfigDefaultValue == null ? null : GetParamAsSystemType(paramDefinition.ConfigDefaultValue!.ToString()!, paramKey, systemType);
string parameterizedName = MakeDbConnectionParam(value, paramKey);
ProcedureParameters.Add(paramKey, $"{parameterizedName}");
}
else
{
// In case required parameters not found in request and no default specified in config
// Should already be handled in the request validation step
throw new DataApiBuilderException(message: $"Did not provide all procedure params, missing: \"{paramKey}\"",
statusCode: HttpStatusCode.BadRequest,
subStatusCode: DataApiBuilderException.SubStatusCodes.BadRequest);
}
}
}
}
}
}