diff options
Diffstat (limited to 'yql/essentials/sql/pg')
| -rw-r--r-- | yql/essentials/sql/pg/pg_sql.cpp | 59 | ||||
| -rw-r--r-- | yql/essentials/sql/pg/pg_sql_ut.cpp | 28 | ||||
| -rw-r--r-- | yql/essentials/sql/pg/ya.make | 1 |
3 files changed, 74 insertions, 14 deletions
diff --git a/yql/essentials/sql/pg/pg_sql.cpp b/yql/essentials/sql/pg/pg_sql.cpp index 6990cbfefa7..81b9eb396ee 100644 --- a/yql/essentials/sql/pg/pg_sql.cpp +++ b/yql/essentials/sql/pg/pg_sql.cpp @@ -40,6 +40,7 @@ extern "C" { #include <yql/essentials/providers/common/provider/yql_provider_names.h> #include <yql/essentials/minikql/mkql_type_builder.h> #include <yql/essentials/core/issue/yql_issue.h> +#include <yql/essentials/core/langver/feature.gen.h> #include <yql/essentials/public/issue/yql_warning.h> #include <yql/essentials/core/sql_types/yql_callable_names.h> #include <yql/essentials/utils/log/log_level.h> @@ -2517,7 +2518,7 @@ public: return nullptr; } } else if (name == "warning") { - if (auto langver = NYql::MakeLangVersion(2026, 01); + if (auto langver = NYql::NFeature::PgPragmaWarning.MinLangVer; !NYql::IsBackwardCompatibleFeatureAvailable( Settings_.LangVer, langver, Settings_.BackportMode)) { @@ -3725,6 +3726,33 @@ public: return result; } + bool ExtractCollationName(const CollateClause* value, TString& name) { + auto len = ListLength(value->collname); + if (len == 0) { + AddError("CollateClause: missing collation name"); + return false; + } + + auto x = ListNodeNth(value->collname, len - 1); + if (NodeTag(x) != T_String) { + NodeNotImplemented(value, x); + return false; + } + + name = StrVal(x); + return true; + } + + TAstNode* ParseCollateClause(const CollateClause* value, const TExprSettings& settings) { + AT_LOCATION(value); + // Collation propagation through arbitrary expressions (COALESCE, CASE, plain + // projections, ...) is not implemented - only ParseFuncCall picks up an explicit + // COLLATE that directly wraps one of its arguments (see there). Elsewhere COLLATE + // only affects collation-sensitive semantics (comparison, case mapping), not the + // expression's runtime value, so we just parse through to the wrapped expression. + return ParseExpr(value->arg, settings); + } + TAstNode* ParseExpr(const Node* node, const TExprSettings& settings) { switch (NodeTag(node)) { case T_A_Const: { @@ -3742,6 +3770,9 @@ public: case T_TypeCast: { return ParseTypeCast(CAST_NODE(TypeCast, node), settings); } + case T_CollateClause: { + return ParseCollateClause(CAST_NODE(CollateClause, node), settings); + } case T_BoolExpr: { return ParseBoolExpr(CAST_NODE(BoolExpr, node), settings); } @@ -4267,6 +4298,32 @@ public: callSettings.push_back(QL(QA("range"))); } + if (!value->agg_star) { + TMaybe<TString> collation; + for (int i = 0; i < ListLength(value->args); ++i) { + auto x = ListNodeNth(value->args, i); + if (NodeTag(x) != T_CollateClause) { + continue; + } + + TString collationName; + if (!ExtractCollationName(CAST_NODE(CollateClause, x), collationName)) { + return nullptr; + } + + if (collation && *collation != collationName) { + AddError(TStringBuilder() << "FuncCall: conflicting explicit collations: " << *collation << " and " << collationName); + return nullptr; + } + + collation = collationName; + } + + if (collation) { + callSettings.push_back(QL(QA("collation"), QAX(*collation))); + } + } + args.push_back(QVL(callSettings.data(), callSettings.size())); if (value->agg_star) { if (name != "count") { diff --git a/yql/essentials/sql/pg/pg_sql_ut.cpp b/yql/essentials/sql/pg/pg_sql_ut.cpp index 2d07350d6ea..18477d3a807 100644 --- a/yql/essentials/sql/pg/pg_sql_ut.cpp +++ b/yql/essentials/sql/pg/pg_sql_ut.cpp @@ -1,5 +1,7 @@ #include "ut/util.h" +#include <yql/essentials/core/langver/feature.gen.h> + #include <library/cpp/testing/unittest/registar.h> #include <yql/essentials/parser/pg_wrapper/interface/parser.h> @@ -1138,7 +1140,7 @@ Y_UNIT_TEST(WarningAsError) { )sql"; TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2026, 01); + settings.LangVer = NYql::NFeature::PgPragmaWarning.MinLangVer; auto res = SqlToYqlWithMode(query, NSQLTranslation::ESqlMode::QUERY, 10, {}, EDebugOutput::None, /*ansiLexer=*/false, settings); UNIT_ASSERT(!res.Root); UNIT_ASSERT(res.Issues.Size() > 0); @@ -1155,7 +1157,7 @@ Y_UNIT_TEST(WarningDisable) { )sql"; TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2026, 01); + settings.LangVer = NYql::NFeature::PgPragmaWarning.MinLangVer; auto res = SqlToYqlWithMode(query, NSQLTranslation::ESqlMode::QUERY, 10, {}, EDebugOutput::None, /*ansiLexer=*/false, settings); UNIT_ASSERT(res.Root); UNIT_ASSERT_EQUAL(res.Issues.Size(), 0); @@ -1168,7 +1170,7 @@ Y_UNIT_TEST(WarningDefault) { )sql"; TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2026, 01); + settings.LangVer = NYql::NFeature::PgPragmaWarning.MinLangVer; auto res = SqlToYqlWithMode(query, NSQLTranslation::ESqlMode::QUERY, 10, {}, EDebugOutput::None, /*ansiLexer=*/false, settings); UNIT_ASSERT(res.Root); UNIT_ASSERT(res.Issues.Size() > 0); @@ -1184,7 +1186,7 @@ Y_UNIT_TEST(WarningInvalidAction) { )sql"; TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2026, 01); + settings.LangVer = NYql::NFeature::PgPragmaWarning.MinLangVer; auto res = SqlToYqlWithMode(query, NSQLTranslation::ESqlMode::QUERY, 10, {}, EDebugOutput::None, /*ansiLexer=*/false, settings); UNIT_ASSERT(!res.Root); UNIT_ASSERT(res.Issues.Size() > 0); @@ -1200,7 +1202,7 @@ Y_UNIT_TEST(WarningInvalidPattern) { )sql"; TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2026, 01); + settings.LangVer = NYql::NFeature::PgPragmaWarning.MinLangVer; auto res = SqlToYqlWithMode(query, NSQLTranslation::ESqlMode::QUERY, 10, {}, EDebugOutput::None, /*ansiLexer=*/false, settings); UNIT_ASSERT(!res.Root); UNIT_ASSERT(res.Issues.Size() > 0); @@ -1216,7 +1218,7 @@ Y_UNIT_TEST(WarningMissingArguments) { )sql"; TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2026, 01); + settings.LangVer = NYql::NFeature::PgPragmaWarning.MinLangVer; auto res = SqlToYqlWithMode(query, NSQLTranslation::ESqlMode::QUERY, 10, {}, EDebugOutput::None, /*ansiLexer=*/false, settings); UNIT_ASSERT(!res.Root); UNIT_ASSERT(res.Issues.Size() > 0); @@ -1232,7 +1234,7 @@ Y_UNIT_TEST(WarningTooManyArguments) { )sql"; TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2026, 01); + settings.LangVer = NYql::NFeature::PgPragmaWarning.MinLangVer; auto res = SqlToYqlWithMode(query, NSQLTranslation::ESqlMode::QUERY, 10, {}, EDebugOutput::None, /*ansiLexer=*/false, settings); UNIT_ASSERT(!res.Root); UNIT_ASSERT(res.Issues.Size() > 0); @@ -1249,7 +1251,7 @@ Y_UNIT_TEST(WarningSpecificCode) { )sql"; TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2026, 01); + settings.LangVer = NYql::NFeature::PgPragmaWarning.MinLangVer; auto res = SqlToYqlWithMode(query, NSQLTranslation::ESqlMode::QUERY, 10, {}, EDebugOutput::None, /*ansiLexer=*/false, settings); UNIT_ASSERT(!res.Root); UNIT_ASSERT(res.Issues.Size() > 0); @@ -1266,7 +1268,7 @@ Y_UNIT_TEST(WarningSpecificCodeDisable) { )sql"; TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2026, 01); + settings.LangVer = NYql::NFeature::PgPragmaWarning.MinLangVer; auto res = SqlToYqlWithMode(query, NSQLTranslation::ESqlMode::QUERY, 10, {}, EDebugOutput::None, /*ansiLexer=*/false, settings); UNIT_ASSERT(res.Root); UNIT_ASSERT_EQUAL(res.Issues.Size(), 0); @@ -1278,7 +1280,7 @@ Y_UNIT_TEST(WarningNonStringAction) { )sql"; TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2026, 01); + settings.LangVer = NYql::NFeature::PgPragmaWarning.MinLangVer; auto res = SqlToYqlWithMode(query, NSQLTranslation::ESqlMode::QUERY, 10, {}, EDebugOutput::None, /*ansiLexer=*/false, settings); UNIT_ASSERT(!res.Root); UNIT_ASSERT(res.Issues.Size() > 0); @@ -1294,7 +1296,7 @@ Y_UNIT_TEST(WarningNonStringPattern) { )sql"; TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2026, 01); + settings.LangVer = NYql::NFeature::PgPragmaWarning.MinLangVer; auto res = SqlToYqlWithMode(query, NSQLTranslation::ESqlMode::QUERY, 10, {}, EDebugOutput::None, /*ansiLexer=*/false, settings); UNIT_ASSERT(!res.Root); UNIT_ASSERT(res.Issues.Size() > 0); @@ -1312,7 +1314,7 @@ Y_UNIT_TEST(WarningMultipleRules) { )sql"; TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2026, 01); + settings.LangVer = NYql::NFeature::PgPragmaWarning.MinLangVer; auto res = SqlToYqlWithMode(query, NSQLTranslation::ESqlMode::QUERY, 10, {}, EDebugOutput::None, /*ansiLexer=*/false, settings); UNIT_ASSERT(!res.Root); UNIT_ASSERT(res.Issues.Size() > 0); @@ -1328,7 +1330,7 @@ Y_UNIT_TEST(WarningNoArguments) { )sql"; TTranslationSettings settings; - settings.LangVer = NYql::MakeLangVersion(2026, 01); + settings.LangVer = NYql::NFeature::PgPragmaWarning.MinLangVer; auto res = SqlToYqlWithMode(query, NSQLTranslation::ESqlMode::QUERY, 10, {}, EDebugOutput::None, /*ansiLexer=*/false, settings); UNIT_ASSERT(!res.Root); UNIT_ASSERT(res.Issues.Size() > 0); diff --git a/yql/essentials/sql/pg/ya.make b/yql/essentials/sql/pg/ya.make index ab493603bf5..edbcfa2aa30 100644 --- a/yql/essentials/sql/pg/ya.make +++ b/yql/essentials/sql/pg/ya.make @@ -6,6 +6,7 @@ PROVIDES( PEERDIR( yql/essentials/ast + yql/essentials/core/langver yql/essentials/core/sql_types yql/essentials/parser/pg_catalog yql/essentials/minikql |
