summaryrefslogtreecommitdiffstats
path: root/yql/essentials/udfs/common/url_base/lib/url_query.cpp
diff options
context:
space:
mode:
authorvvvv <[email protected]>2025-10-06 13:26:25 +0300
committervvvv <[email protected]>2025-10-06 14:06:25 +0300
commiteca8ce9cb1613d5c983185c4e43c20651a9638aa (patch)
tree61ee5ae779948e61af9a7691d19eaa2c09869121 /yql/essentials/udfs/common/url_base/lib/url_query.cpp
parent4adf7eecae16a9b228b28cc5f64c27ef69ad5ec2 (diff)
YQL-20086 udfs
init commit_hash:f9684778bf1ea956965f2360b80b91edb7d4ffbe
Diffstat (limited to 'yql/essentials/udfs/common/url_base/lib/url_query.cpp')
-rw-r--r--yql/essentials/udfs/common/url_base/lib/url_query.cpp316
1 files changed, 161 insertions, 155 deletions
diff --git a/yql/essentials/udfs/common/url_base/lib/url_query.cpp b/yql/essentials/udfs/common/url_base/lib/url_query.cpp
index 885dc3b16e9..32dc2e34806 100644
--- a/yql/essentials/udfs/common/url_base/lib/url_query.cpp
+++ b/yql/essentials/udfs/common/url_base/lib/url_query.cpp
@@ -7,122 +7,125 @@
#include <library/cpp/string_utils/quote/quote.h>
namespace NUrlUdf {
- void TQueryStringParse::MakeSignature(IFunctionTypeInfoBuilder& builder,
- const TType* retType)
- {
- builder.Returns(retType).OptionalArgs(4);
- auto args = builder.Args();
- args->Add<TAutoMap<TQueryStr>>();
- args->Add<TKeepBlankValuesNArg>();
- args->Add<TStrictNArg>();
- args->Add<TMaxFieldsNArg>();
- args->Add<TSeparatorNArg>().Done();
+void TQueryStringParse::MakeSignature(IFunctionTypeInfoBuilder& builder,
+ const TType* retType)
+{
+ builder.Returns(retType).OptionalArgs(4);
+ auto args = builder.Args();
+ args->Add<TAutoMap<TQueryStr>>();
+ args->Add<TKeepBlankValuesNArg>();
+ args->Add<TStrictNArg>();
+ args->Add<TMaxFieldsNArg>();
+ args->Add<TSeparatorNArg>().Done();
+}
+
+std::vector<std::pair<TString, TString>>
+TQueryStringParse::RunImpl(const TUnboxedValuePod* args) const {
+ const std::string_view query(args[0].AsStringRef());
+ if (query.empty()) {
+ return {};
}
+ const bool keepBlankValues = args[1].GetOrDefault(false);
+ const bool strict = args[2].GetOrDefault(true);
+ const ui32 maxFieldCnt = args[3].GetOrDefault(Max<ui32>());
+ const std::string_view sep(args[4] ? args[4].AsStringRef() : "&");
- std::vector<std::pair<TString, TString>>
- TQueryStringParse::RunImpl(const TUnboxedValuePod* args) const {
- const std::string_view query(args[0].AsStringRef());
- if (query.empty())
- return {};
- const bool keepBlankValues = args[1].GetOrDefault(false);
- const bool strict = args[2].GetOrDefault(true);
- const ui32 maxFieldCnt = args[3].GetOrDefault(Max<ui32>());
- const std::string_view sep(args[4] ? args[4].AsStringRef() : "&");
+ std::vector<TStringBuf> parts;
+ StringSplitter(query).SplitByString(sep).Collect(&parts);
+ if (parts.size() > maxFieldCnt) {
+ UdfTerminate((TStringBuilder() << Pos_ << "Max number of fields (" << maxFieldCnt
+ << ") exceeded: got " << parts.size())
+ .c_str());
+ }
- std::vector<TStringBuf> parts;
- StringSplitter(query).SplitByString(sep).Collect(&parts);
- if (parts.size() > maxFieldCnt) {
- UdfTerminate((TStringBuilder() << Pos_ << "Max number of fields (" << maxFieldCnt
- << ") exceeded: got " << parts.size()).c_str());
+ std::vector<std::pair<TString, TString>> pairs;
+ for (const TStringBuf& part : parts) {
+ if (part.empty() && !strict) {
+ continue;
}
-
- std::vector<std::pair<TString, TString>> pairs;
- for (const TStringBuf& part: parts) {
- if (part.empty() && !strict) {
- continue;
- }
- TVector<TString> nvPair = StringSplitter(part).Split('=').Limit(2);
- if (nvPair.size() != 2) {
- if (strict) {
- UdfTerminate((TStringBuilder() << Pos_ << "Bad query field: \""
- << nvPair[0] << "\"").c_str());
- }
- if (keepBlankValues) {
- nvPair.emplace_back("");
- } else {
- continue;
- }
+ TVector<TString> nvPair = StringSplitter(part).Split('=').Limit(2);
+ if (nvPair.size() != 2) {
+ if (strict) {
+ UdfTerminate((TStringBuilder() << Pos_ << "Bad query field: \""
+ << nvPair[0] << "\"")
+ .c_str());
}
- if (!nvPair[1].empty() || keepBlankValues) {
- CGIUnescape(nvPair[0]);
- CGIUnescape(nvPair[1]);
- pairs.emplace_back(nvPair[0], nvPair[1]);
+ if (keepBlankValues) {
+ nvPair.emplace_back("");
+ } else {
+ continue;
}
}
- return pairs;
+ if (!nvPair[1].empty() || keepBlankValues) {
+ CGIUnescape(nvPair[0]);
+ CGIUnescape(nvPair[1]);
+ pairs.emplace_back(nvPair[0], nvPair[1]);
+ }
}
+ return pairs;
+}
- bool TQueryStringToList::DeclareSignature(const TStringRef& name,
- TType*,
- IFunctionTypeInfoBuilder& builder,
- bool typesOnly) {
- if (Name() == name) {
- MakeSignature(builder, GetListType(builder));
- if (!typesOnly) {
- builder.Implementation(new TQueryStringToList(builder.GetSourcePosition()));
- }
- return true;
+bool TQueryStringToList::DeclareSignature(const TStringRef& name,
+ TType*,
+ IFunctionTypeInfoBuilder& builder,
+ bool typesOnly) {
+ if (Name() == name) {
+ MakeSignature(builder, GetListType(builder));
+ if (!typesOnly) {
+ builder.Implementation(new TQueryStringToList(builder.GetSourcePosition()));
}
- return false;
+ return true;
}
+ return false;
+}
- TUnboxedValue TQueryStringToList::Run(const IValueBuilder* valueBuilder,
- const TUnboxedValuePod* args) const {
- const auto pairs = RunImpl(args);
- std::vector<TUnboxedValue> ret;
- for (const auto& nvPair : pairs) {
- TUnboxedValue* pair = nullptr;
- auto item = valueBuilder->NewArray(2U, pair);
- pair[0] = valueBuilder->NewString(nvPair.first);
- pair[1] = valueBuilder->NewString(nvPair.second);
- ret.push_back(item);
- }
- return valueBuilder->NewList(ret.data(), ret.size());
+TUnboxedValue TQueryStringToList::Run(const IValueBuilder* valueBuilder,
+ const TUnboxedValuePod* args) const {
+ const auto pairs = RunImpl(args);
+ std::vector<TUnboxedValue> ret;
+ for (const auto& nvPair : pairs) {
+ TUnboxedValue* pair = nullptr;
+ auto item = valueBuilder->NewArray(2U, pair);
+ pair[0] = valueBuilder->NewString(nvPair.first);
+ pair[1] = valueBuilder->NewString(nvPair.second);
+ ret.push_back(item);
}
+ return valueBuilder->NewList(ret.data(), ret.size());
+}
- bool TQueryStringToDict::DeclareSignature(const TStringRef& name,
- TType*,
- IFunctionTypeInfoBuilder& builder,
- bool typesOnly) {
- if (Name() == name) {
- auto dictType = GetDictType(builder);
- MakeSignature(builder, dictType);
- if (!typesOnly) {
- builder.Implementation(new TQueryStringToDict(dictType,
- builder.GetSourcePosition()));
- }
- return true;
+bool TQueryStringToDict::DeclareSignature(const TStringRef& name,
+ TType*,
+ IFunctionTypeInfoBuilder& builder,
+ bool typesOnly) {
+ if (Name() == name) {
+ auto dictType = GetDictType(builder);
+ MakeSignature(builder, dictType);
+ if (!typesOnly) {
+ builder.Implementation(new TQueryStringToDict(dictType,
+ builder.GetSourcePosition()));
}
- return false;
+ return true;
}
+ return false;
+}
- TUnboxedValue TQueryStringToDict::Run(const IValueBuilder* valueBuilder,
- const TUnboxedValuePod* args) const {
- const auto pairs = RunImpl(args);
- auto ret = valueBuilder->NewDict(DictType_, TDictFlags::Hashed | TDictFlags::Multi);
- for (const auto& nvPair : pairs) {
- ret->Add(valueBuilder->NewString(nvPair.first),
- valueBuilder->NewString(nvPair.second));
- }
- return ret->Build();
+TUnboxedValue TQueryStringToDict::Run(const IValueBuilder* valueBuilder,
+ const TUnboxedValuePod* args) const {
+ const auto pairs = RunImpl(args);
+ auto ret = valueBuilder->NewDict(DictType_, TDictFlags::Hashed | TDictFlags::Multi);
+ for (const auto& nvPair : pairs) {
+ ret->Add(valueBuilder->NewString(nvPair.first),
+ valueBuilder->NewString(nvPair.second));
}
+ return ret->Build();
+}
- TUnboxedValue TBuildQueryString::Run(const IValueBuilder* valueBuilder,
- const TUnboxedValuePod* args) const {
- const std::string_view sep(args[1] ? args[1].AsStringRef() : "&");
- TStringBuilder ret;
+TUnboxedValue TBuildQueryString::Run(const IValueBuilder* valueBuilder,
+ const TUnboxedValuePod* args) const {
+ const std::string_view sep(args[1] ? args[1].AsStringRef() : "&");
+ TStringBuilder ret;
- switch(FirstArgTypeId_) {
+ switch (FirstArgTypeId_) {
case EFirstArgTypeId::Dict: {
TUnboxedValue key, value;
const auto dictIt = args[0].GetDictIterator();
@@ -132,8 +135,9 @@ namespace NUrlUdf {
const auto listIt = value.GetListIterator();
TUnboxedValue item;
while (listIt.Next(item)) {
- if (wasItem++)
+ if (wasItem++) {
ret << sep;
+ }
if (item) {
ret << keyEscaped << '=' << CGIEscapeRet(item.AsStringRef());
} else {
@@ -148,8 +152,9 @@ namespace NUrlUdf {
const auto dictIt = args[0].GetDictIterator();
ui64 wasKey = 0;
while (dictIt.NextPair(key, value)) {
- if (wasKey++)
+ if (wasKey++) {
ret << sep;
+ }
if (value) {
ret << CGIEscapeRet(key.AsStringRef()) << '='
<< CGIEscapeRet(value.AsStringRef());
@@ -164,8 +169,9 @@ namespace NUrlUdf {
TUnboxedValue item;
const auto listIt = args[0].GetListIterator();
while (listIt.Next(item)) {
- if (wasItem++)
+ if (wasItem++) {
ret << sep;
+ }
TUnboxedValue key = item.GetElement(0), val = item.GetElement(1);
if (val) {
ret << CGIEscapeRet(key.AsStringRef()) << '='
@@ -178,66 +184,66 @@ namespace NUrlUdf {
}
default:
Y_ABORT("Current first parameter type is not yet implemented");
- }
- return valueBuilder->NewString(ret);
}
+ return valueBuilder->NewString(ret);
+}
- bool TBuildQueryString::DeclareSignature(const TStringRef& name,
- TType* userType,
- IFunctionTypeInfoBuilder& builder,
- bool typesOnly) {
- if (Name() == name) {
- if (!userType) {
- builder.SetError("Missing user type");
- return true;
- }
- builder.UserType(userType);
- const auto typeHelper = builder.TypeInfoHelper();
- const auto userTypeInspector = TTupleTypeInspector(*typeHelper, userType);
- if (!userTypeInspector || !userTypeInspector.GetElementsCount()) {
- builder.SetError("User type is not tuple");
- return true;
- }
- const auto argsTypeInspector = TTupleTypeInspector(*typeHelper,
- userTypeInspector.GetElementType(0));
- if (!argsTypeInspector || !argsTypeInspector.GetElementsCount()) {
- builder.SetError("Please provide at least one argument");
- return true;
- }
- const auto firstArgType = argsTypeInspector.GetElementType(0);
- EFirstArgTypeId firstArgTypeId = EFirstArgTypeId::None;
+bool TBuildQueryString::DeclareSignature(const TStringRef& name,
+ TType* userType,
+ IFunctionTypeInfoBuilder& builder,
+ bool typesOnly) {
+ if (Name() == name) {
+ if (!userType) {
+ builder.SetError("Missing user type");
+ return true;
+ }
+ builder.UserType(userType);
+ const auto typeHelper = builder.TypeInfoHelper();
+ const auto userTypeInspector = TTupleTypeInspector(*typeHelper, userType);
+ if (!userTypeInspector || !userTypeInspector.GetElementsCount()) {
+ builder.SetError("User type is not tuple");
+ return true;
+ }
+ const auto argsTypeInspector = TTupleTypeInspector(*typeHelper,
+ userTypeInspector.GetElementType(0));
+ if (!argsTypeInspector || !argsTypeInspector.GetElementsCount()) {
+ builder.SetError("Please provide at least one argument");
+ return true;
+ }
+ const auto firstArgType = argsTypeInspector.GetElementType(0);
+ EFirstArgTypeId firstArgTypeId = EFirstArgTypeId::None;
- if (typeHelper->IsSameType(GetDictType(builder), firstArgType) ||
- typeHelper->IsSameType(GetDictType(builder, true), firstArgType)) {
- firstArgTypeId = EFirstArgTypeId::Dict;
- } else if (typeHelper->IsSameType(GetListType(builder), firstArgType) ||
- typeHelper->IsSameType(GetListType(builder, true), firstArgType) ||
- typeHelper->GetTypeKind(firstArgType) == ETypeKind::EmptyList)
- {
- firstArgTypeId = EFirstArgTypeId::List;
- } else if (typeHelper->IsSameType(GetFlattenDictType(builder), firstArgType) ||
- typeHelper->IsSameType(GetFlattenDictType(builder, true), firstArgType) ||
- typeHelper->GetTypeKind(firstArgType) == ETypeKind::EmptyDict)
- {
- firstArgTypeId = EFirstArgTypeId::FlattenDict;
- }
- if (firstArgTypeId != EFirstArgTypeId::None) {
- builder.Returns<TQueryStr>().OptionalArgs(1);
- auto args = builder.Args();
- args->Add(firstArgType).Flags(ICallablePayload::TArgumentFlags::AutoMap);
- args->Add<TSeparatorNArg>().Done();
- if (!typesOnly) {
- builder.Implementation(new TBuildQueryString(builder.GetSourcePosition(),
- firstArgTypeId));
- }
- } else {
- TStringBuilder sb;
- sb << "Unsupported first argument type: ";
- TTypePrinter(*typeHelper, firstArgType).Out(sb.Out);
- builder.SetError(sb);
+ if (typeHelper->IsSameType(GetDictType(builder), firstArgType) ||
+ typeHelper->IsSameType(GetDictType(builder, true), firstArgType)) {
+ firstArgTypeId = EFirstArgTypeId::Dict;
+ } else if (typeHelper->IsSameType(GetListType(builder), firstArgType) ||
+ typeHelper->IsSameType(GetListType(builder, true), firstArgType) ||
+ typeHelper->GetTypeKind(firstArgType) == ETypeKind::EmptyList)
+ {
+ firstArgTypeId = EFirstArgTypeId::List;
+ } else if (typeHelper->IsSameType(GetFlattenDictType(builder), firstArgType) ||
+ typeHelper->IsSameType(GetFlattenDictType(builder, true), firstArgType) ||
+ typeHelper->GetTypeKind(firstArgType) == ETypeKind::EmptyDict)
+ {
+ firstArgTypeId = EFirstArgTypeId::FlattenDict;
+ }
+ if (firstArgTypeId != EFirstArgTypeId::None) {
+ builder.Returns<TQueryStr>().OptionalArgs(1);
+ auto args = builder.Args();
+ args->Add(firstArgType).Flags(ICallablePayload::TArgumentFlags::AutoMap);
+ args->Add<TSeparatorNArg>().Done();
+ if (!typesOnly) {
+ builder.Implementation(new TBuildQueryString(builder.GetSourcePosition(),
+ firstArgTypeId));
}
- return true;
+ } else {
+ TStringBuilder sb;
+ sb << "Unsupported first argument type: ";
+ TTypePrinter(*typeHelper, firstArgType).Out(sb.Out);
+ builder.SetError(sb);
}
- return false;
+ return true;
}
+ return false;
}
+} // namespace NUrlUdf