summaryrefslogtreecommitdiffstats
path: root/yql/essentials/sql/v1/query.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'yql/essentials/sql/v1/query.cpp')
-rw-r--r--yql/essentials/sql/v1/query.cpp109
1 files changed, 94 insertions, 15 deletions
diff --git a/yql/essentials/sql/v1/query.cpp b/yql/essentials/sql/v1/query.cpp
index 22fc6e7b9cf..6ec40c25ce5 100644
--- a/yql/essentials/sql/v1/query.cpp
+++ b/yql/essentials/sql/v1/query.cpp
@@ -27,6 +27,26 @@ bool ValidateView(TPosition pos, TContext& ctx, TStringBuf service, TViewDescrip
return true;
}
+namespace {
+
+bool ValidateColumnIsDefined(TContext& ctx, const TIdentifier& column, const THashSet<TString>& definedColumns, bool allowUndefinedColumns) {
+ if (!allowUndefinedColumns && !definedColumns.contains(column.Name)) {
+ ctx.Error(column.Pos) << "Undefined column: " << column.Name;
+ return false;
+ }
+ return true;
+}
+
+bool ValidateNameIsUnique(TContext& ctx, THashSet<TString>& seenNames, const TIdentifier& name, TStringBuf entityKind) {
+ if (!seenNames.insert(name.Name).second) {
+ ctx.Error(name.Pos) << entityKind << " " << name.Name << " must be defined once";
+ return false;
+ }
+ return true;
+}
+
+} // anonymous namespace
+
class TUniqueTableKey: public ITableKeys {
public:
TUniqueTableKey(TPosition pos, TString service, TDeferredAtom cluster,
@@ -377,6 +397,23 @@ INode::TPtr CreateAlterIndex(const TIndexDescription& index, const INode& node)
return alterIndexNode;
}
+INode::TPtr CreateStatisticsDesc(const TStatisticsDescription& statistics, const INode& node) {
+ auto statisticsColumns = node.Y();
+ for (const auto& col : statistics.Columns) {
+ statisticsColumns = node.L(statisticsColumns, BuildQuotedAtom(col.Pos, col.Name));
+ }
+ auto statisticsTypes = node.Y();
+ for (const auto& type : statistics.Types) {
+ statisticsTypes = node.L(statisticsTypes, BuildQuotedAtom(type.Pos, type.Name));
+ }
+ const auto& statisticsName = node.Y(node.Q("statisticsName"), BuildQuotedAtom(statistics.Name.Pos, statistics.Name.Name));
+ auto statisticsNode = node.Y(
+ node.Q(statisticsName),
+ node.Q(node.Y(node.Q("statisticsColumns"), node.Q(statisticsColumns))),
+ node.Q(node.Y(node.Q("statisticsTypes"), node.Q(statisticsTypes))));
+ return statisticsNode;
+}
+
INode::TPtr CreateChangefeedDesc(const TChangefeedDescription& desc, const INode& node) {
auto settings = node.Y();
if (desc.Settings.Mode) {
@@ -1165,7 +1202,7 @@ public:
return false;
}
- if (!Params_.PkColumns.empty() || !Params_.PartitionByColumns.empty() || !Params_.OrderByColumns.empty() || !Params_.Indexes.empty() || !Params_.Changefeeds.empty())
+ if (!Params_.PkColumns.empty() || !Params_.PartitionByColumns.empty() || !Params_.OrderByColumns.empty() || !Params_.Indexes.empty() || !Params_.Statistics.empty() || !Params_.Changefeeds.empty())
{
THashSet<TString> columnsSet;
for (auto& col : Params_.Columns) {
@@ -1176,8 +1213,7 @@ public:
THashSet<TString> pkColumns;
for (auto& keyColumn : Params_.PkColumns) {
- if (!allowUndefinedColumns && !columnsSet.contains(keyColumn.Name)) {
- ctx.Error(keyColumn.Pos) << "Undefined column: " << keyColumn.Name;
+ if (!ValidateColumnIsDefined(ctx, keyColumn, columnsSet, allowUndefinedColumns)) {
return false;
}
if (!pkColumns.insert(keyColumn.Name).second) {
@@ -1186,35 +1222,30 @@ public:
}
}
for (auto& keyColumn : Params_.PartitionByColumns) {
- if (!allowUndefinedColumns && !columnsSet.contains(keyColumn.Name)) {
- ctx.Error(keyColumn.Pos) << "Undefined column: " << keyColumn.Name;
+ if (!ValidateColumnIsDefined(ctx, keyColumn, columnsSet, allowUndefinedColumns)) {
return false;
}
}
for (auto& keyColumn : Params_.OrderByColumns) {
- if (!allowUndefinedColumns && !columnsSet.contains(keyColumn.first.Name)) {
- ctx.Error(keyColumn.first.Pos) << "Undefined column: " << keyColumn.first.Name;
+ if (!ValidateColumnIsDefined(ctx, keyColumn.first, columnsSet, allowUndefinedColumns)) {
return false;
}
}
THashSet<TString> indexNames;
for (const auto& index : Params_.Indexes) {
- if (!indexNames.insert(index.Name.Name).second) {
- ctx.Error(index.Name.Pos) << "Index " << index.Name.Name << " must be defined once";
+ if (!ValidateNameIsUnique(ctx, indexNames, index.Name, "Index")) {
return false;
}
for (const auto& indexColumn : index.IndexColumns) {
- if (!allowUndefinedColumns && !columnsSet.contains(indexColumn.Name)) {
- ctx.Error(indexColumn.Pos) << "Undefined column: " << indexColumn.Name;
+ if (!ValidateColumnIsDefined(ctx, indexColumn, columnsSet, allowUndefinedColumns)) {
return false;
}
}
for (const auto& dataColumn : index.DataColumns) {
- if (!allowUndefinedColumns && !columnsSet.contains(dataColumn.Name)) {
- ctx.Error(dataColumn.Pos) << "Undefined column: " << dataColumn.Name;
+ if (!ValidateColumnIsDefined(ctx, dataColumn, columnsSet, allowUndefinedColumns)) {
return false;
}
}
@@ -1222,10 +1253,29 @@ public:
THashSet<TString> cfNames;
for (const auto& cf : Params_.Changefeeds) {
- if (!cfNames.insert(cf.Name.Name).second) {
- ctx.Error(cf.Name.Pos) << "Changefeed " << cf.Name.Name << " must be defined once";
+ if (!ValidateNameIsUnique(ctx, cfNames, cf.Name, "Changefeed")) {
+ return false;
+ }
+ }
+
+ THashSet<TString> statisticsNames;
+ for (const auto& statistics : Params_.Statistics) {
+ if (!ValidateNameIsUnique(ctx, statisticsNames, statistics.Name, "Statistics")) {
+ return false;
+ }
+
+ if (statistics.Columns.empty()) {
+ ctx.Error(statistics.Name.Pos) << "Statistics " << statistics.Name.Name << " must have at least one column";
return false;
}
+
+ for (const auto& statisticsColumn : statistics.Columns) {
+ if (!ValidateColumnIsDefined(ctx, statisticsColumn, columnsSet, allowUndefinedColumns)) {
+ return false;
+ }
+ }
+
+ // statistics.Types may be empty: WITH is optional and its omission means "all supported statistic types"
}
}
@@ -1399,6 +1449,11 @@ public:
opts = L(opts, Q(Y(Q("index"), Q(desc))));
}
+ for (const auto& statistics : Params_.Statistics) {
+ const auto& desc = CreateStatisticsDesc(statistics, *this);
+ opts = L(opts, Q(Y(Q("statistics"), Q(desc))));
+ }
+
for (const auto& cf : Params_.Changefeeds) {
const auto& desc = CreateChangefeedDesc(cf, *this);
opts = L(opts, Q(Y(Q("changefeed"), Q(desc))));
@@ -1856,6 +1911,30 @@ public:
actions = L(actions, Q(Y(Q("dropIndex"), indexName)));
}
+ {
+ THashSet<TString> statisticsNames;
+ for (const auto& statistics : Params_.AddStatistics) {
+ if (!ValidateNameIsUnique(ctx, statisticsNames, statistics.Name, "Statistics")) {
+ return false;
+ }
+
+ if (statistics.Columns.empty()) {
+ ctx.Error(statistics.Name.Pos) << "Statistics " << statistics.Name.Name << " must have at least one column";
+ return false;
+ }
+
+ // statistics.Types may be empty: WITH is optional and its omission means "all supported statistic types"
+
+ const auto& desc = CreateStatisticsDesc(statistics, *this);
+ actions = L(actions, Q(Y(Q("addStatistics"), Q(desc))));
+ }
+ }
+
+ for (const auto& id : Params_.DropStatistics) {
+ auto statisticsName = BuildQuotedAtom(id.Pos, id.Name);
+ actions = L(actions, Q(Y(Q("dropStatistics"), statisticsName)));
+ }
+
if (Params_.RenameIndexTo) {
auto src = BuildQuotedAtom(Params_.RenameIndexTo->first.Pos, Params_.RenameIndexTo->first.Name);
auto dst = BuildQuotedAtom(Params_.RenameIndexTo->second.Pos, Params_.RenameIndexTo->second.Name);