Skip to content

Commit 7c40410

Browse files
committed
fix result sets and issues
1 parent 2aa5b7b commit 7c40410

19 files changed

+119
-68
lines changed

ydb/core/kqp/common/compilation/events.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ namespace NKikimr::NKqp::NPrivateEvents {
1414

1515
struct TEvCompileRequest: public TEventLocal<TEvCompileRequest, TKqpEvents::EvCompileRequest> {
1616
TEvCompileRequest(const TIntrusiveConstPtr<NACLib::TUserToken>& userToken, const TMaybe<TString>& uid,
17-
TMaybe<TKqpQueryId>&& query, bool keepInCache, bool canDivideIntoStatements, TInstant deadline,
17+
TMaybe<TKqpQueryId>&& query, bool keepInCache, bool perStatementResult, TInstant deadline,
1818
TKqpDbCountersPtr dbCounters, std::shared_ptr<std::atomic<bool>> intrestedInResult,
1919
const TIntrusivePtr<TUserRequestContext>& userRequestContext, NLWTrace::TOrbit orbit = {},
2020
TKqpTempTablesState::TConstPtr tempTablesState = nullptr, bool collectDiagnostics = false, TMaybe<TQueryAst> queryAst = Nothing())
2121
: UserToken(userToken)
2222
, Uid(uid)
2323
, Query(std::move(query))
2424
, KeepInCache(keepInCache)
25-
, CanDivideIntoStatements(canDivideIntoStatements)
25+
, PerStatementResult(perStatementResult)
2626
, Deadline(deadline)
2727
, DbCounters(dbCounters)
2828
, UserRequestContext(userRequestContext)
@@ -39,7 +39,7 @@ struct TEvCompileRequest: public TEventLocal<TEvCompileRequest, TKqpEvents::EvCo
3939
TMaybe<TString> Uid;
4040
TMaybe<TKqpQueryId> Query;
4141
bool KeepInCache = false;
42-
bool CanDivideIntoStatements = false;
42+
bool PerStatementResult = false;
4343
// it is allowed for local event to use absolute time (TInstant) instead of time interval (TDuration)
4444
TInstant Deadline;
4545
TKqpDbCountersPtr DbCounters;

ydb/core/kqp/compile_service/kqp_compile_actor.cpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class TKqpCompileActor : public TActorBootstrapped<TKqpCompileActor> {
5252
TKqpDbCountersPtr dbCounters, std::optional<TKqpFederatedQuerySetup> federatedQuerySetup,
5353
const TIntrusivePtr<TUserRequestContext>& userRequestContext,
5454
NWilson::TTraceId traceId, TKqpTempTablesState::TConstPtr tempTablesState, bool collectFullDiagnostics,
55-
bool canDivideIntoStatements, ECompileActorAction compileAction, TMaybe<TQueryAst> queryAst)
55+
bool perStatementResult, ECompileActorAction compileAction, TMaybe<TQueryAst> queryAst)
5656
: Owner(owner)
5757
, ModuleResolverState(moduleResolverState)
5858
, Counters(counters)
@@ -70,7 +70,7 @@ class TKqpCompileActor : public TActorBootstrapped<TKqpCompileActor> {
7070
, CompileActorSpan(TWilsonKqp::CompileActor, std::move(traceId), "CompileActor")
7171
, TempTablesState(std::move(tempTablesState))
7272
, CollectFullDiagnostics(collectFullDiagnostics)
73-
, CanDivideIntoStatements(canDivideIntoStatements)
73+
, PerStatementResult(perStatementResult)
7474
, CompileAction(compileAction)
7575
, QueryAst(std::move(queryAst))
7676
{
@@ -136,9 +136,9 @@ class TKqpCompileActor : public TActorBootstrapped<TKqpCompileActor> {
136136
NSQLTranslation::EBindingsMode bindingsMode = Config->BindingsMode;
137137
bool isEnableExternalDataSources = AppData(ctx)->FeatureFlags.GetEnableExternalDataSources();
138138
bool isEnablePgConstsToParams = Config->EnablePgConstsToParams;
139-
bool perStatementExecution = Config->EnablePerStatementQueryExecution && CanDivideIntoStatements;
139+
bool perStatementExecution = Config->EnablePerStatementQueryExecution && PerStatementResult;
140140

141-
return SqlToAstStatements(ConvertType(QueryId.Settings.QueryType), QueryId.Settings.Syntax, QueryId.Text, QueryId.QueryParameterTypes, cluster, kqpTablePathPrefix, kqpYqlSyntaxVersion, bindingsMode, isEnableExternalDataSources, isEnablePgConstsToParams, QueryId.IsSql(), perStatementExecution);
141+
return ParseStatements(ConvertType(QueryId.Settings.QueryType), QueryId.Settings.Syntax, QueryId.Text, QueryId.QueryParameterTypes, cluster, kqpTablePathPrefix, kqpYqlSyntaxVersion, bindingsMode, isEnableExternalDataSources, isEnablePgConstsToParams, QueryId.IsSql(), perStatementExecution);
142142
}
143143

144144
void StartParsing(const TActorContext &ctx) {
@@ -354,7 +354,8 @@ class TKqpCompileActor : public TActorBootstrapped<TKqpCompileActor> {
354354

355355
if (astStatements.empty()) {
356356
NYql::TIssue issue(NYql::TPosition(), "Parsing result of query is empty");
357-
ReplyError(Ydb::StatusIds::GENERIC_ERROR, {issue});
357+
ReplyError(Ydb::StatusIds::INTERNAL_ERROR, {issue});
358+
return;
358359
}
359360

360361
for (size_t statementId = 0; statementId < astStatements.size(); ++statementId) {
@@ -369,7 +370,7 @@ class TKqpCompileActor : public TActorBootstrapped<TKqpCompileActor> {
369370
issue.AddSubIssue(MakeIntrusive<NYql::TIssue>(i));
370371
}
371372

372-
ReplyError(Ydb::StatusIds::GENERIC_ERROR, {issue});
373+
ReplyError(Ydb::StatusIds::INTERNAL_ERROR, {issue});
373374
return;
374375
}
375376
}
@@ -379,7 +380,7 @@ class TKqpCompileActor : public TActorBootstrapped<TKqpCompileActor> {
379380
<< ", owner: " << Owner
380381
<< ", statements size: " << astStatements.size());
381382

382-
auto responseEv = MakeHolder<TEvKqp::TEvParseResponse>(QueryId, astStatements);
383+
auto responseEv = MakeHolder<TEvKqp::TEvParseResponse>(QueryId, std::move(astStatements));
383384
Send(Owner, responseEv.Release());
384385

385386
Counters->ReportCompileFinish(DbCounters);
@@ -495,7 +496,7 @@ class TKqpCompileActor : public TActorBootstrapped<TKqpCompileActor> {
495496
TKqpTempTablesState::TConstPtr TempTablesState;
496497
bool CollectFullDiagnostics;
497498

498-
const bool CanDivideIntoStatements;
499+
const bool PerStatementResult;
499500
ECompileActorAction CompileAction;
500501
TMaybe<TQueryAst> QueryAst;
501502
};
@@ -543,14 +544,14 @@ IActor* CreateKqpCompileActor(const TActorId& owner, const TKqpSettings::TConstP
543544
TKqpDbCountersPtr dbCounters, const TIntrusivePtr<TUserRequestContext>& userRequestContext,
544545
NWilson::TTraceId traceId, TKqpTempTablesState::TConstPtr tempTablesState,
545546
ECompileActorAction compileAction, TMaybe<TQueryAst> queryAst, bool collectFullDiagnostics,
546-
bool canDivideIntoStatements)
547+
bool perStatementResult)
547548
{
548549
return new TKqpCompileActor(owner, kqpSettings, tableServiceConfig, queryServiceConfig, metadataProviderConfig,
549550
moduleResolverState, counters,
550551
uid, query, userToken, dbCounters,
551552
federatedQuerySetup, userRequestContext,
552553
std::move(traceId), std::move(tempTablesState), collectFullDiagnostics,
553-
canDivideIntoStatements, compileAction, std::move(queryAst));
554+
perStatementResult, compileAction, std::move(queryAst));
554555
}
555556

556557
} // namespace NKqp

ydb/core/kqp/compile_service/kqp_compile_service.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ class TKqpQueryCache {
232232
};
233233

234234
struct TKqpCompileRequest {
235-
TKqpCompileRequest(const TActorId& sender, const TString& uid, TKqpQueryId query, bool keepInCache, bool canDivideIntoStatements,
235+
TKqpCompileRequest(const TActorId& sender, const TString& uid, TKqpQueryId query, bool keepInCache, bool perStatementResult,
236236
const TIntrusiveConstPtr<NACLib::TUserToken>& userToken, const TInstant& deadline, TKqpDbCountersPtr dbCounters,
237237
ui64 cookie, std::shared_ptr<std::atomic<bool>> intrestedInResult,
238238
const TIntrusivePtr<TUserRequestContext>& userRequestContext,
@@ -244,7 +244,7 @@ struct TKqpCompileRequest {
244244
, Query(std::move(query))
245245
, Uid(uid)
246246
, KeepInCache(keepInCache)
247-
, CanDivideIntoStatements(canDivideIntoStatements)
247+
, PerStatementResult(perStatementResult)
248248
, UserToken(userToken)
249249
, Deadline(deadline)
250250
, DbCounters(dbCounters)
@@ -262,7 +262,7 @@ struct TKqpCompileRequest {
262262
TKqpQueryId Query;
263263
TString Uid;
264264
bool KeepInCache = false;
265-
bool CanDivideIntoStatements = false;
265+
bool PerStatementResult = false;
266266
TIntrusiveConstPtr<NACLib::TUserToken> UserToken;
267267
TInstant Deadline;
268268
TKqpDbCountersPtr DbCounters;
@@ -638,7 +638,7 @@ class TKqpCompileService : public TActorBootstrapped<TKqpCompileService> {
638638
ev->Get()->Query ? ev->Get()->Query->UserSid : 0);
639639

640640
TKqpCompileRequest compileRequest(ev->Sender, CreateGuidAsString(), std::move(*request.Query),
641-
request.KeepInCache, request.CanDivideIntoStatements, request.UserToken, request.Deadline, dbCounters,
641+
request.KeepInCache, request.PerStatementResult, request.UserToken, request.Deadline, dbCounters,
642642
ev->Cookie, std::move(ev->Get()->IntrestedInResult), ev->Get()->UserRequestContext,
643643
std::move(ev->Get()->Orbit), std::move(compileServiceSpan), std::move(ev->Get()->TempTablesState),
644644
TableServiceConfig.GetEnableAstCache() ? ECompileActorAction::PARSE : ECompileActorAction::COMPILE);
@@ -980,7 +980,7 @@ class TKqpCompileService : public TActorBootstrapped<TKqpCompileService> {
980980
void StartCompilation(TKqpCompileRequest&& request, const TActorContext& ctx) {
981981
auto compileActor = CreateKqpCompileActor(ctx.SelfID, KqpSettings, TableServiceConfig, QueryServiceConfig, MetadataProviderConfig, ModuleResolverState, Counters,
982982
request.Uid, request.Query, request.UserToken, FederatedQuerySetup, request.DbCounters, request.UserRequestContext,
983-
request.CompileServiceSpan.GetTraceId(), request.TempTablesState, request.Action, std::move(request.QueryAst), CollectDiagnostics, request.CanDivideIntoStatements);
983+
request.CompileServiceSpan.GetTraceId(), request.TempTablesState, request.Action, std::move(request.QueryAst), CollectDiagnostics, request.PerStatementResult);
984984
auto compileActorId = ctx.ExecutorThread.RegisterActor(compileActor, TMailboxType::HTSwap,
985985
AppData(ctx)->UserPoolId);
986986

ydb/core/kqp/compile_service/kqp_compile_service.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ IActor* CreateKqpCompileActor(const TActorId& owner, const TKqpSettings::TConstP
3838
ECompileActorAction compileAction = ECompileActorAction::COMPILE,
3939
TMaybe<TQueryAst> queryAst = {},
4040
bool collectFullDiagnostics = false,
41-
bool canDivideIntoStatements = false);
41+
bool PerStatementResult = false);
4242

4343
IActor* CreateKqpCompileRequestActor(const TActorId& owner, const TIntrusiveConstPtr<NACLib::TUserToken>& userToken, const TMaybe<TString>& uid,
4444
TMaybe<TKqpQueryId>&& query, bool keepInCache, const TInstant& deadline, TKqpDbCountersPtr dbCounters,

ydb/core/kqp/executer_actor/kqp_data_executer.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,9 @@ class TKqpDataExecuter : public TKqpExecuterBase<TKqpDataExecuter, EExecType::Da
128128
const NKikimrConfig::TTableServiceConfig::EChannelTransportVersion chanTransportVersion,
129129
const NKikimrConfig::TTableServiceConfig::TAggregationConfig& aggregation,
130130
const TActorId& creator, TDuration maximalSecretsSnapshotWaitTime, const TIntrusivePtr<TUserRequestContext>& userRequestContext,
131-
const bool enableOlapSink)
131+
const bool enableOlapSink, ui32 statementResultIndex)
132132
: TBase(std::move(request), database, userToken, counters, executerRetriesConfig, chanTransportVersion, aggregation,
133-
maximalSecretsSnapshotWaitTime, userRequestContext, TWilsonKqp::DataExecuter, "DataExecuter"
133+
maximalSecretsSnapshotWaitTime, userRequestContext, statementResultIndex, TWilsonKqp::DataExecuter, "DataExecuter"
134134
)
135135
, AsyncIoFactory(std::move(asyncIoFactory))
136136
, StreamResult(streamResult)
@@ -2460,10 +2460,10 @@ IActor* CreateKqpDataExecuter(IKqpGateway::TExecPhysicalRequest&& request, const
24602460
TKqpRequestCounters::TPtr counters, bool streamResult, const NKikimrConfig::TTableServiceConfig::TAggregationConfig& aggregation,
24612461
const NKikimrConfig::TTableServiceConfig::TExecuterRetriesConfig& executerRetriesConfig,
24622462
NYql::NDq::IDqAsyncIoFactory::TPtr asyncIoFactory, const NKikimrConfig::TTableServiceConfig::EChannelTransportVersion chanTransportVersion, const TActorId& creator,
2463-
TDuration maximalSecretsSnapshotWaitTime, const TIntrusivePtr<TUserRequestContext>& userRequestContext, const bool enableOlapSink)
2463+
TDuration maximalSecretsSnapshotWaitTime, const TIntrusivePtr<TUserRequestContext>& userRequestContext, const bool enableOlapSink, ui32 statementResultIndex)
24642464
{
24652465
return new TKqpDataExecuter(std::move(request), database, userToken, counters, streamResult, executerRetriesConfig,
2466-
std::move(asyncIoFactory), chanTransportVersion, aggregation, creator, maximalSecretsSnapshotWaitTime, userRequestContext, enableOlapSink);
2466+
std::move(asyncIoFactory), chanTransportVersion, aggregation, creator, maximalSecretsSnapshotWaitTime, userRequestContext, enableOlapSink, statementResultIndex);
24672467
}
24682468

24692469
} // namespace NKqp

ydb/core/kqp/executer_actor/kqp_executer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ IActor* CreateKqpExecuter(IKqpGateway::TExecPhysicalRequest&& request, const TSt
9292
NYql::NDq::IDqAsyncIoFactory::TPtr asyncIoFactory, TPreparedQueryHolder::TConstPtr preparedQuery,
9393
const NKikimrConfig::TTableServiceConfig::EChannelTransportVersion chanTransportVersion, const TActorId& creator,
9494
TDuration maximalSecretsSnapshotWaitTime, const TIntrusivePtr<TUserRequestContext>& userRequestContext,
95-
const bool enableOlapSink);
95+
const bool enableOlapSink, ui32 statementResultIndex);
9696

9797
IActor* CreateKqpSchemeExecuter(TKqpPhyTxHolder::TConstPtr phyTx, NKikimrKqp::EQueryType queryType, const TActorId& target,
9898
const TMaybe<TString>& requestType, const TString& database,

ydb/core/kqp/executer_actor/kqp_executer_impl.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,12 @@ IActor* CreateKqpExecuter(IKqpGateway::TExecPhysicalRequest&& request, const TSt
8484
NYql::NDq::IDqAsyncIoFactory::TPtr asyncIoFactory, TPreparedQueryHolder::TConstPtr preparedQuery,
8585
const NKikimrConfig::TTableServiceConfig::EChannelTransportVersion chanTransportVersion, const TActorId& creator,
8686
TDuration maximalSecretsSnapshotWaitTime, const TIntrusivePtr<TUserRequestContext>& userRequestContext,
87-
const bool enableOlapSink)
87+
const bool enableOlapSink, ui32 statementResultIndex)
8888
{
8989
if (request.Transactions.empty()) {
9090
// commit-only or rollback-only data transaction
9191
YQL_ENSURE(request.LocksOp == ELocksOp::Commit || request.LocksOp == ELocksOp::Rollback);
92-
return CreateKqpDataExecuter(std::move(request), database, userToken, counters, false, aggregation, executerRetriesConfig, std::move(asyncIoFactory), chanTransportVersion, creator, maximalSecretsSnapshotWaitTime, userRequestContext, enableOlapSink);
92+
return CreateKqpDataExecuter(std::move(request), database, userToken, counters, false, aggregation, executerRetriesConfig, std::move(asyncIoFactory), chanTransportVersion, creator, maximalSecretsSnapshotWaitTime, userRequestContext, enableOlapSink, statementResultIndex);
9393
}
9494

9595
TMaybe<NKqpProto::TKqpPhyTx::EType> txsType;
@@ -105,13 +105,13 @@ IActor* CreateKqpExecuter(IKqpGateway::TExecPhysicalRequest&& request, const TSt
105105
switch (*txsType) {
106106
case NKqpProto::TKqpPhyTx::TYPE_COMPUTE:
107107
case NKqpProto::TKqpPhyTx::TYPE_DATA:
108-
return CreateKqpDataExecuter(std::move(request), database, userToken, counters, false, aggregation, executerRetriesConfig, std::move(asyncIoFactory), chanTransportVersion, creator, maximalSecretsSnapshotWaitTime, userRequestContext, enableOlapSink);
108+
return CreateKqpDataExecuter(std::move(request), database, userToken, counters, false, aggregation, executerRetriesConfig, std::move(asyncIoFactory), chanTransportVersion, creator, maximalSecretsSnapshotWaitTime, userRequestContext, enableOlapSink, statementResultIndex);
109109

110110
case NKqpProto::TKqpPhyTx::TYPE_SCAN:
111-
return CreateKqpScanExecuter(std::move(request), database, userToken, counters, aggregation, executerRetriesConfig, preparedQuery, chanTransportVersion, maximalSecretsSnapshotWaitTime, userRequestContext);
111+
return CreateKqpScanExecuter(std::move(request), database, userToken, counters, aggregation, executerRetriesConfig, preparedQuery, chanTransportVersion, maximalSecretsSnapshotWaitTime, userRequestContext, statementResultIndex);
112112

113113
case NKqpProto::TKqpPhyTx::TYPE_GENERIC:
114-
return CreateKqpDataExecuter(std::move(request), database, userToken, counters, true, aggregation, executerRetriesConfig, std::move(asyncIoFactory), chanTransportVersion, creator, maximalSecretsSnapshotWaitTime, userRequestContext, enableOlapSink);
114+
return CreateKqpDataExecuter(std::move(request), database, userToken, counters, true, aggregation, executerRetriesConfig, std::move(asyncIoFactory), chanTransportVersion, creator, maximalSecretsSnapshotWaitTime, userRequestContext, enableOlapSink, statementResultIndex);
115115

116116
default:
117117
YQL_ENSURE(false, "Unsupported physical tx type: " << (ui32)*txsType);

ydb/core/kqp/executer_actor/kqp_executer_impl.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ class TKqpExecuterBase : public TActorBootstrapped<TDerived> {
119119
const NKikimrConfig::TTableServiceConfig::EChannelTransportVersion chanTransportVersion,
120120
const NKikimrConfig::TTableServiceConfig::TAggregationConfig& aggregation,
121121
TDuration maximalSecretsSnapshotWaitTime, const TIntrusivePtr<TUserRequestContext>& userRequestContext,
122+
ui32 statementResultIndex,
122123
ui64 spanVerbosity = 0, TString spanName = "KqpExecuterBase")
123124
: Request(std::move(request))
124125
, Database(database)
@@ -130,6 +131,7 @@ class TKqpExecuterBase : public TActorBootstrapped<TDerived> {
130131
, MaximalSecretsSnapshotWaitTime(maximalSecretsSnapshotWaitTime)
131132
, AggregationSettings(aggregation)
132133
, HasOlapTable(false)
134+
, StatementResultIndex(statementResultIndex)
133135
{
134136
TasksGraph.GetMeta().Snapshot = IKqpGateway::TKqpSnapshot(Request.Snapshot.Step, Request.Snapshot.TxId);
135137
TasksGraph.GetMeta().Arena = MakeIntrusive<NActors::TProtoArenaHolder>();
@@ -1624,7 +1626,7 @@ class TKqpExecuterBase : public TActorBootstrapped<TDerived> {
16241626
IActor* proxy;
16251627
if (txResult.IsStream && txResult.QueryResultIndex.Defined()) {
16261628
proxy = CreateResultStreamChannelProxy(TxId, channel.Id, txResult.MkqlItemType,
1627-
txResult.ColumnOrder, *txResult.QueryResultIndex, Target, this->SelfId());
1629+
txResult.ColumnOrder, *txResult.QueryResultIndex, Target, this->SelfId(), StatementResultIndex);
16281630
} else {
16291631
proxy = CreateResultDataChannelProxy(TxId, channel.Id, this->SelfId(),
16301632
channel.DstInputIndex, ResponseEv.get());
@@ -1757,6 +1759,8 @@ class TKqpExecuterBase : public TActorBootstrapped<TDerived> {
17571759
bool UnknownAffectedShardCount = false;
17581760
THashMap<NYql::NDq::TStageId, THashMap<ui64, TShardInfo>> SourceScanStageIdToParititions;
17591761

1762+
ui32 StatementResultIndex;
1763+
17601764
private:
17611765
static constexpr TDuration ResourceUsageUpdateInterval = TDuration::MilliSeconds(100);
17621766
};
@@ -1770,14 +1774,14 @@ IActor* CreateKqpDataExecuter(IKqpGateway::TExecPhysicalRequest&& request, const
17701774
NYql::NDq::IDqAsyncIoFactory::TPtr asyncIoFactory,
17711775
const NKikimrConfig::TTableServiceConfig::EChannelTransportVersion chanTransportVersion, const TActorId& creator,
17721776
TDuration maximalSecretsSnapshotWaitTime, const TIntrusivePtr<TUserRequestContext>& userRequestContext,
1773-
const bool enableOlapSink);
1777+
const bool enableOlapSink, ui32 statementResultIndex);
17741778

17751779
IActor* CreateKqpScanExecuter(IKqpGateway::TExecPhysicalRequest&& request, const TString& database,
17761780
const TIntrusiveConstPtr<NACLib::TUserToken>& userToken, TKqpRequestCounters::TPtr counters,
17771781
const NKikimrConfig::TTableServiceConfig::TAggregationConfig& aggregation,
17781782
const NKikimrConfig::TTableServiceConfig::TExecuterRetriesConfig& executerRetriesConfig,
17791783
TPreparedQueryHolder::TConstPtr preparedQuery, const NKikimrConfig::TTableServiceConfig::EChannelTransportVersion chanTransportVersion,
1780-
TDuration maximalSecretsSnapshotWaitTime, const TIntrusivePtr<TUserRequestContext>& userRequestContext);
1784+
TDuration maximalSecretsSnapshotWaitTime, const TIntrusivePtr<TUserRequestContext>& userRequestContext, ui32 statementResultIndex);
17811785

17821786
} // namespace NKqp
17831787
} // namespace NKikimr

0 commit comments

Comments
 (0)