diff options
author | vvvv <vvvv@ydb.tech> | 2022-09-05 18:12:18 +0300 |
---|---|---|
committer | vvvv <vvvv@ydb.tech> | 2022-09-05 18:12:18 +0300 |
commit | 403e692d99369c6a0feeab2d690adefcd69a13b4 (patch) | |
tree | f6cddaaae200b99a5f5cad2fc54482d7759f3903 | |
parent | b016e5ad8257fa631b2d7aaa4b7111a3256027de (diff) | |
download | ydb-403e692d99369c6a0feeab2d690adefcd69a13b4.tar.gz |
support of length-related casts
-rw-r--r-- | ydb/library/yql/core/type_ann/type_ann_pg.cpp | 11 | ||||
-rw-r--r-- | ydb/library/yql/parser/pg_catalog/catalog.cpp | 12 | ||||
-rw-r--r-- | ydb/library/yql/parser/pg_wrapper/comp_factory.cpp | 59 | ||||
-rw-r--r-- | ydb/library/yql/providers/common/mkql/yql_provider_mkql.cpp | 24 | ||||
-rw-r--r-- | ydb/library/yql/sql/pg/pg_sql.cpp | 12 | ||||
-rw-r--r-- | ydb/library/yql/sql/v1/builtin.cpp | 5 |
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); |