aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvvvv <vvvv@ydb.tech>2022-09-05 18:12:18 +0300
committervvvv <vvvv@ydb.tech>2022-09-05 18:12:18 +0300
commit403e692d99369c6a0feeab2d690adefcd69a13b4 (patch)
treef6cddaaae200b99a5f5cad2fc54482d7759f3903
parentb016e5ad8257fa631b2d7aaa4b7111a3256027de (diff)
downloadydb-403e692d99369c6a0feeab2d690adefcd69a13b4.tar.gz
support of length-related casts
-rw-r--r--ydb/library/yql/core/type_ann/type_ann_pg.cpp11
-rw-r--r--ydb/library/yql/parser/pg_catalog/catalog.cpp12
-rw-r--r--ydb/library/yql/parser/pg_wrapper/comp_factory.cpp59
-rw-r--r--ydb/library/yql/providers/common/mkql/yql_provider_mkql.cpp24
-rw-r--r--ydb/library/yql/sql/pg/pg_sql.cpp12
-rw-r--r--ydb/library/yql/sql/v1/builtin.cpp5
6 files changed, 90 insertions, 33 deletions
diff --git a/ydb/library/yql/core/type_ann/type_ann_pg.cpp b/ydb/library/yql/core/type_ann/type_ann_pg.cpp
index bc36a0077f..f744a6a7fe 100644
--- a/ydb/library/yql/core/type_ann/type_ann_pg.cpp
+++ b/ydb/library/yql/core/type_ann/type_ann_pg.cpp
@@ -4078,7 +4078,12 @@ IGraphTransformer::TStatus PgTypeModWrapper(const TExprNode::TPtr& input, TExprN
auto pgType = input->Child(0)->GetTypeAnn()->Cast<TTypeExprType>()->GetType()->Cast<TPgExprType>();
const auto& typeDesc = NPg::LookupType(pgType->GetId());
- if (!typeDesc.TypeModInFuncId) {
+ auto funcId = typeDesc.TypeModInFuncId;
+ if (typeDesc.TypeId == typeDesc.ArrayTypeId) {
+ funcId = NPg::LookupType(typeDesc.ElementTypeId).TypeModInFuncId;
+ }
+
+ if (!funcId) {
ctx.Expr.AddError(TIssue(ctx.Expr.GetPosition(input->Pos()),
TStringBuilder() << "No modifiers for type: " << pgType->GetName()));
return IGraphTransformer::TStatus::Error;
@@ -4093,7 +4098,7 @@ IGraphTransformer::TStatus PgTypeModWrapper(const TExprNode::TPtr& input, TExprN
mods.push_back(TString(input->Child(i)->Content()));
}
- if (pgType->GetName() == "interval") {
+ if (pgType->GetName() == "interval" || pgType->GetName() == "_interval") {
if (mods.size() != 1) {
ctx.Expr.AddError(TIssue(ctx.Expr.GetPosition(input->Pos()), "Exactly one modidifer is expected for pginterval"));
return IGraphTransformer::TStatus::Error;
@@ -4124,7 +4129,7 @@ IGraphTransformer::TStatus PgTypeModWrapper(const TExprNode::TPtr& input, TExprN
auto arr = ctx.Expr.NewCallable(input->Pos(), "PgArray", std::move(args));
output = ctx.Expr.Builder(input->Pos())
.Callable("PgCall")
- .Atom(0, NPg::LookupProc(typeDesc.TypeModInFuncId, { 0 }).Name)
+ .Atom(0, NPg::LookupProc(funcId, { 0 }).Name)
.List(1)
.Seal()
.Add(2, arr)
diff --git a/ydb/library/yql/parser/pg_catalog/catalog.cpp b/ydb/library/yql/parser/pg_catalog/catalog.cpp
index 26cb20c620..1b992efa5c 100644
--- a/ydb/library/yql/parser/pg_catalog/catalog.cpp
+++ b/ydb/library/yql/parser/pg_catalog/catalog.cpp
@@ -446,14 +446,16 @@ public:
LastCast.TargetId = *typePtr;
} else if (key == "castfunc") {
if (value != "0") {
- if (value.Contains(',')) {
- // e.g. castfunc => 'bit(int8,int4)'
- IsSupported = false;
- } else if (value.Contains('(')) {
+ if (value.Contains('(')) {
auto pos1 = value.find('(');
auto pos2 = value.find(')');
+ auto pos3 = value.find(',');
Y_ENSURE(pos1 != TString::npos);
Y_ENSURE(pos2 != TString::npos);
+ if (pos3 != TString::npos) {
+ pos2 = pos3;
+ }
+
auto funcName = value.substr(0, pos1);
auto inputType = value.substr(pos1 + 1, pos2 - pos1 - 1);
auto inputTypeIdPtr = TypeByName.FindPtr(inputType);
@@ -464,7 +466,7 @@ public:
for (const auto& procId : *procIdPtr) {
auto procPtr = Procs.FindPtr(procId);
Y_ENSURE(procPtr);
- if (procPtr->ArgTypes.size() != 1) {
+ if (procPtr->ArgTypes.size() < 1) {
continue;
}
diff --git a/ydb/library/yql/parser/pg_wrapper/comp_factory.cpp b/ydb/library/yql/parser/pg_wrapper/comp_factory.cpp
index cc56ac04a1..3ca55e206c 100644
--- a/ydb/library/yql/parser/pg_wrapper/comp_factory.cpp
+++ b/ydb/library/yql/parser/pg_wrapper/comp_factory.cpp
@@ -738,28 +738,38 @@ public:
Zero(FInfo1);
Zero(FInfo2);
+ if (TypeMod && SourceId == TargetId && NPg::HasCast(TargetElemDesc.TypeId, TargetElemDesc.TypeId)) {
+ const auto& cast = NPg::LookupCast(TargetElemDesc.TypeId, TargetElemDesc.TypeId);
+
+ Y_ENSURE(cast.FunctionId);
+ fmgr_info(cast.FunctionId, &FInfo1);
+ Y_ENSURE(!FInfo1.fn_retset);
+ Y_ENSURE(FInfo1.fn_addr);
+ Y_ENSURE(FInfo1.fn_nargs >= 2 && FInfo1.fn_nargs <= 3);
+ ConvertLength = true;
+ ArrayCast = IsSourceArray;
+ return;
+ }
+
if (SourceId == 0 || SourceId == TargetId) {
return;
}
ui32 funcId;
ui32 funcId2 = 0;
- if (!NPg::HasCast(SourceElemDesc.TypeId, TargetElemDesc.TypeId)) {
- if (SourceElemDesc.Category == 'S') {
- ArrayCast = IsSourceArray;
- if (!IsTargetArray || IsSourceArray) {
- funcId = TargetElemDesc.InFuncId;
- } else {
- funcId = NPg::LookupProc("array_in", { 0,0,0 }).ProcId;
- }
+ if (!NPg::HasCast(SourceElemDesc.TypeId, TargetElemDesc.TypeId) || (IsSourceArray != IsTargetArray)) {
+ ArrayCast = IsSourceArray && IsTargetArray;
+ if (IsSourceArray && !IsTargetArray) {
+ Y_ENSURE(TargetTypeDesc.Category == 'S');
+ funcId = NPg::LookupProc("array_out", { 0 }).ProcId;
+ } else if (IsTargetArray && !IsSourceArray) {
+ Y_ENSURE(SourceElemDesc.Category == 'S');
+ funcId = NPg::LookupProc("array_in", { 0,0,0 }).ProcId;
+ } else if (SourceElemDesc.Category == 'S') {
+ funcId = TargetElemDesc.InFuncId;
} else {
Y_ENSURE(TargetTypeDesc.Category == 'S');
- ArrayCast = IsTargetArray;
- if (!IsSourceArray || IsTargetArray) {
- funcId = SourceElemDesc.OutFuncId;
- } else {
- funcId = NPg::LookupProc("array_out", { 0 }).ProcId;
- }
+ funcId = SourceElemDesc.OutFuncId;
}
} else {
Y_ENSURE(IsSourceArray == IsTargetArray);
@@ -922,16 +932,26 @@ private:
auto& callInfo1 = state.CallInfo1.Ref();
callInfo1.isnull = false;
NullableDatum argDatum = { datum, false };
+ void* freeCString = nullptr;
+ Y_DEFER {
+ if (freeCString) {
+ pfree(freeCString);
+ }
+ };
+
if (ConvertArgToCString) {
argDatum.value = (Datum)MakeCString(GetVarBuf((const text*)argDatum.value));
- Y_DEFER {
- pfree((void*)argDatum.value);
- };
+ freeCString = (void*)argDatum.value;
}
callInfo1.args[0] = argDatum;
- callInfo1.args[1] = { ObjectIdGetDatum(TypeIOParam), false };
- callInfo1.args[2] = { Int32GetDatum(typeMod), false };
+ if (ConvertLength) {
+ callInfo1.args[1] = { Int32GetDatum(typeMod), false };
+ callInfo1.args[2] = { BoolGetDatum(true), false };
+ } else {
+ callInfo1.args[1] = { ObjectIdGetDatum(TypeIOParam), false };
+ callInfo1.args[2] = { Int32GetDatum(typeMod), false };
+ }
void* freeMem = nullptr;
void* freeMem2 = nullptr;
@@ -1005,6 +1025,7 @@ private:
bool ConvertResFromCString2 = false;
ui32 TypeIOParam = 0;
bool ArrayCast = false;
+ bool ConvertLength = false;
};
diff --git a/ydb/library/yql/providers/common/mkql/yql_provider_mkql.cpp b/ydb/library/yql/providers/common/mkql/yql_provider_mkql.cpp
index bcf3894a94..ff3790cb77 100644
--- a/ydb/library/yql/providers/common/mkql/yql_provider_mkql.cpp
+++ b/ydb/library/yql/providers/common/mkql/yql_provider_mkql.cpp
@@ -2245,7 +2245,17 @@ TMkqlCommonCallableCompiler::TShared::TShared() {
typeMod = MkqlBuildExpr(*node.Child(2), ctx);
}
- return ctx.ProgramBuilder.PgConst(type, node.Head().Content(), typeMod);
+ auto typeMod1 = typeMod;
+ if (node.GetTypeAnn()->Cast<TPgExprType>()->GetName() != "interval" && node.GetTypeAnn()->Cast<TPgExprType>()->GetName() != "_interval") {
+ typeMod1 = TRuntimeNode();
+ }
+
+ auto ret = ctx.ProgramBuilder.PgConst(type, node.Head().Content(), typeMod1);
+ if (node.ChildrenSize() >= 3) {
+ return ctx.ProgramBuilder.PgCast(ret, type, typeMod);
+ } else {
+ return ret;
+ }
});
AddCallable("PgInternal0", [](const TExprNode& node, TMkqlBuildContext& ctx) {
@@ -2288,7 +2298,17 @@ TMkqlCommonCallableCompiler::TShared::TShared() {
typeMod = MkqlBuildExpr(*node.Child(2), ctx);
}
- return ctx.ProgramBuilder.PgCast(input, returnType, typeMod);
+ auto typeMod1 = typeMod;
+ if (node.GetTypeAnn()->Cast<TPgExprType>()->GetName() != "interval" && node.GetTypeAnn()->Cast<TPgExprType>()->GetName() != "_interval") {
+ typeMod1 = TRuntimeNode();
+ }
+
+ auto cast = ctx.ProgramBuilder.PgCast(input, returnType, typeMod1);
+ if (node.ChildrenSize() >= 3) {
+ return ctx.ProgramBuilder.PgCast(cast, returnType, typeMod);
+ } else {
+ return cast;
+ }
});
AddCallable("FromPg", [](const TExprNode& node, TMkqlBuildContext& ctx) {
diff --git a/ydb/library/yql/sql/pg/pg_sql.cpp b/ydb/library/yql/sql/pg/pg_sql.cpp
index a1acfeadd9..73157becee 100644
--- a/ydb/library/yql/sql/pg/pg_sql.cpp
+++ b/ydb/library/yql/sql/pg/pg_sql.cpp
@@ -1842,12 +1842,20 @@ public:
return L(A("PgCast"), input, L(A("PgType"), QAX(finalType)));
} else {
const auto& typeDesc = NPg::LookupType(finalType);
- if (!typeDesc.TypeModInFuncId) {
+ ui32 typeModInFuncId;
+ if (typeDesc.ArrayTypeId == typeDesc.TypeId) {
+ const auto& typeDescElem = NPg::LookupType(typeDesc.ElementTypeId);
+ typeModInFuncId = typeDescElem.TypeModInFuncId;
+ } else {
+ typeModInFuncId = typeDesc.TypeModInFuncId;
+ }
+
+ if (!typeModInFuncId) {
AddError(TStringBuilder() << "Type " << finalType << " doesn't support modifiers");
return nullptr;
}
- const auto& procDesc = NPg::LookupProc(typeDesc.TypeModInFuncId);
+ const auto& procDesc = NPg::LookupProc(typeModInFuncId);
TAstNode* typeMod;
if (typeName->typemod != -1) {
diff --git a/ydb/library/yql/sql/v1/builtin.cpp b/ydb/library/yql/sql/v1/builtin.cpp
index 27e5448af6..9fa9334047 100644
--- a/ydb/library/yql/sql/v1/builtin.cpp
+++ b/ydb/library/yql/sql/v1/builtin.cpp
@@ -3305,11 +3305,12 @@ TNodePtr BuildBuiltinFunc(TContext& ctx, TPosition pos, TString name, const TVec
return new TYqlData(pos, type, args);
}
- if (type.StartsWith("pg")) {
+ if (type.StartsWith("pg") || type.StartsWith("_pg")) {
TVector<TNodePtr> pgConstArgs;
if (!args.empty()) {
pgConstArgs.push_back(args.front());
- pgConstArgs.push_back(new TCallNodeImpl(pos, "PgType", { BuildQuotedAtom(pos, type.substr(2), TNodeFlags::Default) }));
+ pgConstArgs.push_back(new TCallNodeImpl(pos, "PgType", { BuildQuotedAtom(pos,
+ TString(type.StartsWith("pg") ? "" : "_") + type.substr(type.StartsWith("pg") ? 2 : 3), TNodeFlags::Default) }));
pgConstArgs.insert(pgConstArgs.end(), args.begin() + 1, args.end());
}
return new TYqlPgConst(pos, pgConstArgs);