diff options
author | vvvv <[email protected]> | 2025-10-06 13:26:25 +0300 |
---|---|---|
committer | vvvv <[email protected]> | 2025-10-06 14:06:25 +0300 |
commit | eca8ce9cb1613d5c983185c4e43c20651a9638aa (patch) | |
tree | 61ee5ae779948e61af9a7691d19eaa2c09869121 /yql/essentials/udfs/common/url_base/lib/url_query.cpp | |
parent | 4adf7eecae16a9b228b28cc5f64c27ef69ad5ec2 (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.cpp | 316 |
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 |