summaryrefslogtreecommitdiffstats
path: root/yql/essentials/sql/pg
diff options
context:
space:
mode:
Diffstat (limited to 'yql/essentials/sql/pg')
-rw-r--r--yql/essentials/sql/pg/pg_sql.cpp59
-rw-r--r--yql/essentials/sql/pg/pg_sql_ut.cpp28
-rw-r--r--yql/essentials/sql/pg/ya.make1
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