-
Notifications
You must be signed in to change notification settings - Fork 2.4k
/
Copy pathSqlQuerySource.cs
98 lines (80 loc) · 3.56 KB
/
SqlQuerySource.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
using Dapper;
using Fluid;
using Fluid.Values;
using Microsoft.Extensions.Options;
using OrchardCore.ContentManagement;
using OrchardCore.Data;
using OrchardCore.Json;
using OrchardCore.Liquid;
using YesSql;
namespace OrchardCore.Queries.Sql
{
public class SqlQuerySource : IQuerySource
{
private readonly ILiquidTemplateManager _liquidTemplateManager;
private readonly IDbConnectionAccessor _dbConnectionAccessor;
private readonly ISession _session;
private readonly JsonSerializerOptions _jsonSerializerOptions;
private readonly TemplateOptions _templateOptions;
public SqlQuerySource(
ILiquidTemplateManager liquidTemplateManager,
IDbConnectionAccessor dbConnectionAccessor,
ISession session,
IOptions<DocumentJsonSerializerOptions> jsonSerializerOptions,
IOptions<TemplateOptions> templateOptions)
{
_liquidTemplateManager = liquidTemplateManager;
_dbConnectionAccessor = dbConnectionAccessor;
_session = session;
_jsonSerializerOptions = jsonSerializerOptions.Value.SerializerOptions;
_templateOptions = templateOptions.Value;
}
public string Name => "Sql";
public Query Create()
{
return new SqlQuery();
}
public async Task<IQueryResults> ExecuteQueryAsync(Query query, IDictionary<string, object> parameters)
{
var sqlQuery = query as SqlQuery;
var sqlQueryResults = new SQLQueryResults();
var tokenizedQuery = await _liquidTemplateManager.RenderStringAsync(sqlQuery.Template, NullEncoder.Default,
parameters.Select(x => new KeyValuePair<string, FluidValue>(x.Key, FluidValue.Create(x.Value, _templateOptions))));
var dialect = _session.Store.Configuration.SqlDialect;
if (!SqlParser.TryParse(tokenizedQuery, _session.Store.Configuration.Schema, dialect, _session.Store.Configuration.TablePrefix, parameters, out var rawQuery, out var messages))
{
sqlQueryResults.Items = Array.Empty<object>();
return sqlQueryResults;
}
await using var connection = _dbConnectionAccessor.CreateConnection();
await connection.OpenAsync();
if (sqlQuery.ReturnDocuments)
{
IEnumerable<long> documentIds;
using var transaction = await connection.BeginTransactionAsync(_session.Store.Configuration.IsolationLevel);
documentIds = await connection.QueryAsync<long>(rawQuery, parameters, transaction);
sqlQueryResults.Items = await _session.GetAsync<ContentItem>(documentIds.ToArray());
return sqlQueryResults;
}
else
{
IEnumerable<dynamic> queryResults;
using var transaction = await connection.BeginTransactionAsync(_session.Store.Configuration.IsolationLevel);
queryResults = await connection.QueryAsync(rawQuery, parameters, transaction);
var results = new List<JsonObject>();
foreach (var document in queryResults)
{
results.Add(JObject.FromObject(document, _jsonSerializerOptions));
}
sqlQueryResults.Items = results;
return sqlQueryResults;
}
}
}
}