diff options
author | vvvv <vvvv@yandex-team.ru> | 2022-02-28 17:11:47 +0300 |
---|---|---|
committer | vvvv <vvvv@yandex-team.ru> | 2022-02-28 17:11:47 +0300 |
commit | 6ac6c4437f83290eda1016f9ab6b95fc8ab4649b (patch) | |
tree | b1cdca5ff4e986601e6e6c459fbf41e5ac902877 | |
parent | a416bd196ecff50852933f545a8f6457799a707f (diff) | |
download | ydb-6ac6c4437f83290eda1016f9ab6b95fc8ab4649b.tar.gz |
YQL-13710 [pg_catalog] pg_cast
ref:e52812aa7033eca23750524503d18e980159b548
-rw-r--r-- | ydb/library/yql/parser/pg_catalog/CMakeLists.txt | 8 | ||||
-rw-r--r-- | ydb/library/yql/parser/pg_catalog/catalog.cpp | 163 | ||||
-rw-r--r-- | ydb/library/yql/parser/pg_catalog/catalog.h | 19 | ||||
-rw-r--r-- | ydb/library/yql/parser/pg_catalog/pg_cast.dat | 533 | ||||
-rw-r--r-- | ydb/library/yql/parser/pg_catalog/ut/catalog_ut.cpp | 30 | ||||
-rw-r--r-- | ydb/library/yql/parser/pg_catalog/ya.make | 1 |
6 files changed, 744 insertions, 10 deletions
diff --git a/ydb/library/yql/parser/pg_catalog/CMakeLists.txt b/ydb/library/yql/parser/pg_catalog/CMakeLists.txt index 9f384a0b97..a7641bfb71 100644 --- a/ydb/library/yql/parser/pg_catalog/CMakeLists.txt +++ b/ydb/library/yql/parser/pg_catalog/CMakeLists.txt @@ -18,6 +18,7 @@ target_sources(yql-parser-pg_catalog.global PRIVATE ${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/9bfc0ed24fcfb8e096ec43a8430d7185.cpp ${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/03528211297024b3dbd6ad7bd8089f55.cpp ${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/4bdffcfe6e5c28b12f6f249d751c6cc5.cpp + ${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/13089390d5c6426a6f6417928fe4445c.cpp ) resources(yql-parser-pg_catalog.global ${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/9bfc0ed24fcfb8e096ec43a8430d7185.cpp @@ -40,3 +41,10 @@ resources(yql-parser-pg_catalog.global KEYS pg_type.dat ) +resources(yql-parser-pg_catalog.global + ${CMAKE_BINARY_DIR}/ydb/library/yql/parser/pg_catalog/13089390d5c6426a6f6417928fe4445c.cpp + INPUTS + ${CMAKE_SOURCE_DIR}/ydb/library/yql/parser/pg_catalog/pg_cast.dat + KEYS + pg_cast.dat +) diff --git a/ydb/library/yql/parser/pg_catalog/catalog.cpp b/ydb/library/yql/parser/pg_catalog/catalog.cpp index 0202c39fec..fe1a164ca9 100644 --- a/ydb/library/yql/parser/pg_catalog/catalog.cpp +++ b/ydb/library/yql/parser/pg_catalog/catalog.cpp @@ -14,6 +14,8 @@ using TProcs = THashMap<ui32, TProcDesc>; using TTypes = THashMap<ui32, TTypeDesc>; +using TCasts = THashMap<ui32, TCastDesc>; + class TParser { public: void Do(const TString& dat) { @@ -209,8 +211,9 @@ private: class TTypesParser : public TParser { public: - TTypesParser(TTypes& types) + TTypesParser(TTypes& types, THashMap<ui32, TString>& elementTypes) : Types(types) + , ElementTypes(elementTypes) {} void OnKey(const TString& key, const TString& value) override { @@ -221,7 +224,7 @@ public: } else if (key == "typname") { LastType.Name = value; } else if (key == "typelem") { - LastType.ElementType = value; + LastElementType = value; // resolve later } else if (key == "typbyval") { if (value == "f") { LastType.PassByValue = false; @@ -240,12 +243,112 @@ public: Types[LastType.ArrayTypeId] = LastType; } + if (LastElementType) { + ElementTypes[LastType.TypeId] = LastElementType; + } + LastType = TTypeDesc(); + LastElementType = TString(); } private: TTypes& Types; + THashMap<ui32, TString>& ElementTypes; TTypeDesc LastType; + TString LastElementType; +}; + +class TCastsParser : public TParser { +public: + TCastsParser(TCasts& casts, const THashMap<TString, ui32>& typeByName, + const THashMap<TString, TVector<ui32>>& procByName, const TProcs& procs) + : Casts(casts) + , TypeByName(typeByName) + , ProcByName(procByName) + , Procs(procs) + {} + + void OnKey(const TString& key, const TString& value) override { + if (key == "castsource") { + auto typePtr = TypeByName.FindPtr(value); + Y_ENSURE(typePtr); + LastCast.SourceId = *typePtr; + } else if (key == "casttarget") { + auto typePtr = TypeByName.FindPtr(value); + Y_ENSURE(typePtr); + 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('(')) { + auto pos1 = value.find('('); + auto pos2 = value.find(')'); + Y_ENSURE(pos1 != TString::npos); + Y_ENSURE(pos2 != TString::npos); + auto funcName = value.substr(0, pos1); + auto inputType = value.substr(pos1 + 1, pos2 - pos1 - 1); + auto inputTypeIdPtr = TypeByName.FindPtr(inputType); + Y_ENSURE(inputTypeIdPtr); + auto procIdPtr = ProcByName.FindPtr(funcName); + Y_ENSURE(procIdPtr); + bool found = false; + for (const auto& procId : *procIdPtr) { + auto procPtr = Procs.FindPtr(procId); + Y_ENSURE(procPtr); + if (procPtr->ArgTypes.size() != 1) { + continue; + } + + if (procPtr->ArgTypes.at(0) == *inputTypeIdPtr) { + LastCast.FunctionId = procPtr->ProcId; + found = true; + break; + } + } + + if (!found) { + // e.g. convert circle to 12-vertex polygon, used sql proc + IsSupported = false; + } + } else { + auto procIdPtr = ProcByName.FindPtr(value); + Y_ENSURE(procIdPtr); + Y_ENSURE(procIdPtr->size() == 1); + LastCast.FunctionId = procIdPtr->at(0); + } + } + } else if (key == "castmethod") { + if (value == "f") { + LastCast.Method = ECastMethod::Function; + } else if (value == "i") { + LastCast.Method = ECastMethod::InOut; + } else if (value == "b") { + LastCast.Method = ECastMethod::Binary; + } else { + ythrow yexception() << "Unknown castmethod value: " << value; + } + } + } + + void OnFinish() override { + if (IsSupported) { + LastCast.CastId = 1 + Casts.size(); + Casts[LastCast.CastId] = LastCast; + } + + LastCast = TCastDesc(); + IsSupported = true; + } + +private: + TCasts& Casts; + const THashMap<TString, ui32>& TypeByName; + const THashMap<TString, TVector<ui32>>& ProcByName; + const TProcs& Procs; + TCastDesc LastCast; + bool IsSupported = true; }; TOperators ParseOperators(const TString& dat, const THashMap<TString, ui32>& typeByName) { @@ -262,9 +365,17 @@ TProcs ParseProcs(const TString& dat, const THashMap<TString, ui32>& typeByName) return ret; } -TTypes ParseTypes(const TString& dat) { +TTypes ParseTypes(const TString& dat, THashMap<ui32, TString>& elementTypes) { TTypes ret; - TTypesParser parser(ret); + TTypesParser parser(ret, elementTypes); + parser.Do(dat); + return ret; +} + +TCasts ParseCasts(const TString& dat, const THashMap<TString, ui32>& typeByName, + const THashMap<TString, TVector<ui32>>& procByName, const TProcs& procs) { + TCasts ret; + TCastsParser parser(ret, typeByName, procByName, procs); parser.Do(dat); return ret; } @@ -277,8 +388,11 @@ struct TCatalog { Y_ENSURE(NResource::FindExact("pg_operator.dat", &opData)); TString procData; Y_ENSURE(NResource::FindExact("pg_proc.dat", &procData)); - Types = ParseTypes(typeData); - for (const auto&[k, v] : Types) { + TString castData; + Y_ENSURE(NResource::FindExact("pg_cast.dat", &castData)); + THashMap<ui32, TString> elementTypes; + Types = ParseTypes(typeData, elementTypes); + for (const auto& [k, v] : Types) { if (k == v.TypeId) { Y_ENSURE(TypeByName.insert(std::make_pair(v.Name, k)).second); } @@ -288,12 +402,25 @@ struct TCatalog { } } + for (const auto& [k, v]: elementTypes) { + auto elemTypePtr = TypeByName.FindPtr(v); + Y_ENSURE(elemTypePtr); + auto typePtr = Types.FindPtr(k); + Y_ENSURE(typePtr); + typePtr->ElementTypeId = *elemTypePtr; + } + Operators = ParseOperators(opData, TypeByName); Procs = ParseProcs(procData, TypeByName); for (const auto& [k, v]: Procs) { ProcByName[v.Name].push_back(k); } + + Casts = ParseCasts(castData, TypeByName, ProcByName, Procs); + for (const auto&[k, v] : Casts) { + Y_ENSURE(CastsByDir.insert(std::make_pair(std::make_pair(v.SourceId, v.TargetId), k)).second); + } } static const TCatalog& Instance() { @@ -303,8 +430,10 @@ struct TCatalog { TOperators Operators; TProcs Procs; TTypes Types; + TCasts Casts; THashMap<TString, TVector<ui32>> ProcByName; THashMap<TString, ui32> TypeByName; + THashMap<std::pair<ui32, ui32>, ui32> CastsByDir; }; bool ValidateArgs(const TProcDesc& d, const TVector<ui32>& argTypeIds) { @@ -393,4 +522,26 @@ const TTypeDesc& LookupType(ui32 typeId) { return *typePtr; } +const TCastDesc& LookupCast(ui32 sourceId, ui32 targetId) { + const auto& catalog = TCatalog::Instance(); + auto castByDirPtr = catalog.CastsByDir.FindPtr(std::make_pair(sourceId, targetId)); + if (!castByDirPtr) { + throw yexception() << "No such cast"; + } + + auto castPtr = catalog.Casts.FindPtr(*castByDirPtr); + Y_ENSURE(castPtr); + return *castPtr; +} + +const TCastDesc& LookupCast(ui32 castId) { + const auto& catalog = TCatalog::Instance(); + auto castPtr = catalog.Casts.FindPtr(castId); + if (!castPtr) { + throw yexception() << "No such cast: " << castId; + } + + return *castPtr; +} + } diff --git a/ydb/library/yql/parser/pg_catalog/catalog.h b/ydb/library/yql/parser/pg_catalog/catalog.h index 13437887c5..9ae80704fd 100644 --- a/ydb/library/yql/parser/pg_catalog/catalog.h +++ b/ydb/library/yql/parser/pg_catalog/catalog.h @@ -34,10 +34,24 @@ struct TTypeDesc { ui32 TypeId = 0; ui32 ArrayTypeId = 0; TString Name; - TString ElementType; + ui32 ElementTypeId = 0; bool PassByValue = false; }; +enum class ECastMethod { + Function, + InOut, + Binary +}; + +struct TCastDesc { + ui32 CastId = 0; + ui32 SourceId = 0; + ui32 TargetId = 0; + ECastMethod Method = ECastMethod::Function; + ui32 FunctionId = 0; +}; + const TProcDesc& LookupProc(const TString& name, const TVector<ui32>& argTypeIds); const TProcDesc& LookupProc(ui32 procId, const TVector<ui32>& argTypeIds); const TProcDesc& LookupProc(ui32 procId); @@ -45,4 +59,7 @@ const TProcDesc& LookupProc(ui32 procId); const TTypeDesc& LookupType(const TString& name); const TTypeDesc& LookupType(ui32 typeId); +const TCastDesc& LookupCast(ui32 sourceId, ui32 targetId); +const TCastDesc& LookupCast(ui32 castId); + } diff --git a/ydb/library/yql/parser/pg_catalog/pg_cast.dat b/ydb/library/yql/parser/pg_catalog/pg_cast.dat new file mode 100644 index 0000000000..5a58f50fbb --- /dev/null +++ b/ydb/library/yql/parser/pg_catalog/pg_cast.dat @@ -0,0 +1,533 @@ +#---------------------------------------------------------------------- +# +# pg_cast.dat +# Initial contents of the pg_cast system catalog. +# +# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group +# Portions Copyright (c) 1994, Regents of the University of California +# +# src/include/catalog/pg_cast.dat +# +#---------------------------------------------------------------------- + +[ + +# Note: this table has OIDs, but we don't bother to assign them manually, +# since nothing needs to know the specific OID of any built-in cast. + +# Numeric category: implicit casts are allowed in the direction +# int2->int4->int8->numeric->float4->float8, while casts in the +# reverse direction are assignment-only. +{ castsource => 'int8', casttarget => 'int2', castfunc => 'int2(int8)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'int8', casttarget => 'int4', castfunc => 'int4(int8)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'int8', casttarget => 'float4', castfunc => 'float4(int8)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int8', casttarget => 'float8', castfunc => 'float8(int8)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int8', casttarget => 'numeric', castfunc => 'numeric(int8)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int2', casttarget => 'int8', castfunc => 'int8(int2)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int2', casttarget => 'int4', castfunc => 'int4(int2)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int2', casttarget => 'float4', castfunc => 'float4(int2)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int2', casttarget => 'float8', castfunc => 'float8(int2)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int2', casttarget => 'numeric', castfunc => 'numeric(int2)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int4', casttarget => 'int8', castfunc => 'int8(int4)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int4', casttarget => 'int2', castfunc => 'int2(int4)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'int4', casttarget => 'float4', castfunc => 'float4(int4)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int4', casttarget => 'float8', castfunc => 'float8(int4)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int4', casttarget => 'numeric', castfunc => 'numeric(int4)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'float4', casttarget => 'int8', castfunc => 'int8(float4)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'float4', casttarget => 'int2', castfunc => 'int2(float4)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'float4', casttarget => 'int4', castfunc => 'int4(float4)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'float4', casttarget => 'float8', castfunc => 'float8(float4)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'float4', casttarget => 'numeric', + castfunc => 'numeric(float4)', castcontext => 'a', castmethod => 'f' }, +{ castsource => 'float8', casttarget => 'int8', castfunc => 'int8(float8)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'float8', casttarget => 'int2', castfunc => 'int2(float8)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'float8', casttarget => 'int4', castfunc => 'int4(float8)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'float8', casttarget => 'float4', castfunc => 'float4(float8)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'float8', casttarget => 'numeric', + castfunc => 'numeric(float8)', castcontext => 'a', castmethod => 'f' }, +{ castsource => 'numeric', casttarget => 'int8', castfunc => 'int8(numeric)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'numeric', casttarget => 'int2', castfunc => 'int2(numeric)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'numeric', casttarget => 'int4', castfunc => 'int4(numeric)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'numeric', casttarget => 'float4', + castfunc => 'float4(numeric)', castcontext => 'i', castmethod => 'f' }, +{ castsource => 'numeric', casttarget => 'float8', + castfunc => 'float8(numeric)', castcontext => 'i', castmethod => 'f' }, +{ castsource => 'money', casttarget => 'numeric', castfunc => 'numeric(money)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'numeric', casttarget => 'money', castfunc => 'money(numeric)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'int4', casttarget => 'money', castfunc => 'money(int4)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'int8', casttarget => 'money', castfunc => 'money(int8)', + castcontext => 'a', castmethod => 'f' }, + +# Allow explicit coercions between int4 and bool +{ castsource => 'int4', casttarget => 'bool', castfunc => 'bool(int4)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'bool', casttarget => 'int4', castfunc => 'int4(bool)', + castcontext => 'e', castmethod => 'f' }, + +# Allow explicit coercions between xid8 and xid +{ castsource => 'xid8', casttarget => 'xid', castfunc => 'xid(xid8)', + castcontext => 'e', castmethod => 'f' }, + +# OID category: allow implicit conversion from any integral type (including +# int8, to support OID literals > 2G) to OID, as well as assignment coercion +# from OID to int4 or int8. Similarly for each OID-alias type. Also allow +# implicit coercions between OID and each OID-alias type, as well as +# regproc<->regprocedure and regoper<->regoperator. (Other coercions +# between alias types must pass through OID.) Lastly, there are implicit +# casts from text and varchar to regclass, which exist mainly to support +# legacy forms of nextval() and related functions. +{ castsource => 'int8', casttarget => 'oid', castfunc => 'oid', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int2', casttarget => 'oid', castfunc => 'int4(int2)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int4', casttarget => 'oid', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'oid', casttarget => 'int8', castfunc => 'int8(oid)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'oid', casttarget => 'int4', castfunc => '0', + castcontext => 'a', castmethod => 'b' }, +{ castsource => 'oid', casttarget => 'regproc', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regproc', casttarget => 'oid', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'int8', casttarget => 'regproc', castfunc => 'oid', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int2', casttarget => 'regproc', castfunc => 'int4(int2)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int4', casttarget => 'regproc', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regproc', casttarget => 'int8', castfunc => 'int8(oid)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'regproc', casttarget => 'int4', castfunc => '0', + castcontext => 'a', castmethod => 'b' }, +{ castsource => 'regproc', casttarget => 'regprocedure', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regprocedure', casttarget => 'regproc', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'oid', casttarget => 'regprocedure', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regprocedure', casttarget => 'oid', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'int8', casttarget => 'regprocedure', castfunc => 'oid', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int2', casttarget => 'regprocedure', castfunc => 'int4(int2)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int4', casttarget => 'regprocedure', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regprocedure', casttarget => 'int8', castfunc => 'int8(oid)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'regprocedure', casttarget => 'int4', castfunc => '0', + castcontext => 'a', castmethod => 'b' }, +{ castsource => 'oid', casttarget => 'regoper', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regoper', casttarget => 'oid', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'int8', casttarget => 'regoper', castfunc => 'oid', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int2', casttarget => 'regoper', castfunc => 'int4(int2)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int4', casttarget => 'regoper', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regoper', casttarget => 'int8', castfunc => 'int8(oid)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'regoper', casttarget => 'int4', castfunc => '0', + castcontext => 'a', castmethod => 'b' }, +{ castsource => 'regoper', casttarget => 'regoperator', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regoperator', casttarget => 'regoper', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'oid', casttarget => 'regoperator', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regoperator', casttarget => 'oid', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'int8', casttarget => 'regoperator', castfunc => 'oid', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int2', casttarget => 'regoperator', castfunc => 'int4(int2)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int4', casttarget => 'regoperator', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regoperator', casttarget => 'int8', castfunc => 'int8(oid)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'regoperator', casttarget => 'int4', castfunc => '0', + castcontext => 'a', castmethod => 'b' }, +{ castsource => 'oid', casttarget => 'regclass', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regclass', casttarget => 'oid', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'int8', casttarget => 'regclass', castfunc => 'oid', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int2', casttarget => 'regclass', castfunc => 'int4(int2)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int4', casttarget => 'regclass', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regclass', casttarget => 'int8', castfunc => 'int8(oid)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'regclass', casttarget => 'int4', castfunc => '0', + castcontext => 'a', castmethod => 'b' }, +{ castsource => 'oid', casttarget => 'regcollation', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regcollation', casttarget => 'oid', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'int8', casttarget => 'regcollation', castfunc => 'oid', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int2', casttarget => 'regcollation', castfunc => 'int4(int2)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int4', casttarget => 'regcollation', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regcollation', casttarget => 'int8', castfunc => 'int8(oid)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'regcollation', casttarget => 'int4', castfunc => '0', + castcontext => 'a', castmethod => 'b' }, +{ castsource => 'oid', casttarget => 'regtype', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regtype', casttarget => 'oid', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'int8', casttarget => 'regtype', castfunc => 'oid', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int2', casttarget => 'regtype', castfunc => 'int4(int2)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int4', casttarget => 'regtype', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regtype', casttarget => 'int8', castfunc => 'int8(oid)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'regtype', casttarget => 'int4', castfunc => '0', + castcontext => 'a', castmethod => 'b' }, +{ castsource => 'oid', casttarget => 'regconfig', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regconfig', casttarget => 'oid', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'int8', casttarget => 'regconfig', castfunc => 'oid', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int2', casttarget => 'regconfig', castfunc => 'int4(int2)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int4', casttarget => 'regconfig', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regconfig', casttarget => 'int8', castfunc => 'int8(oid)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'regconfig', casttarget => 'int4', castfunc => '0', + castcontext => 'a', castmethod => 'b' }, +{ castsource => 'oid', casttarget => 'regdictionary', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regdictionary', casttarget => 'oid', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'int8', casttarget => 'regdictionary', castfunc => 'oid', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int2', casttarget => 'regdictionary', castfunc => 'int4(int2)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int4', casttarget => 'regdictionary', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regdictionary', casttarget => 'int8', castfunc => 'int8(oid)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'regdictionary', casttarget => 'int4', castfunc => '0', + castcontext => 'a', castmethod => 'b' }, +{ castsource => 'text', casttarget => 'regclass', castfunc => 'regclass', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'varchar', casttarget => 'regclass', castfunc => 'regclass', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'oid', casttarget => 'regrole', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regrole', casttarget => 'oid', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'int8', casttarget => 'regrole', castfunc => 'oid', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int2', casttarget => 'regrole', castfunc => 'int4(int2)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int4', casttarget => 'regrole', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regrole', casttarget => 'int8', castfunc => 'int8(oid)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'regrole', casttarget => 'int4', castfunc => '0', + castcontext => 'a', castmethod => 'b' }, +{ castsource => 'oid', casttarget => 'regnamespace', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regnamespace', casttarget => 'oid', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'int8', casttarget => 'regnamespace', castfunc => 'oid', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int2', casttarget => 'regnamespace', castfunc => 'int4(int2)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'int4', casttarget => 'regnamespace', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'regnamespace', casttarget => 'int8', castfunc => 'int8(oid)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'regnamespace', casttarget => 'int4', castfunc => '0', + castcontext => 'a', castmethod => 'b' }, + +# String category +{ castsource => 'text', casttarget => 'bpchar', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'text', casttarget => 'varchar', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'bpchar', casttarget => 'text', castfunc => 'text(bpchar)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'bpchar', casttarget => 'varchar', castfunc => 'text(bpchar)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'varchar', casttarget => 'text', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'varchar', casttarget => 'bpchar', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'char', casttarget => 'text', castfunc => 'text(char)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'char', casttarget => 'bpchar', castfunc => 'bpchar(char)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'char', casttarget => 'varchar', castfunc => 'text(char)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'name', casttarget => 'text', castfunc => 'text(name)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'name', casttarget => 'bpchar', castfunc => 'bpchar(name)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'name', casttarget => 'varchar', castfunc => 'varchar(name)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'text', casttarget => 'char', castfunc => 'char(text)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'bpchar', casttarget => 'char', castfunc => 'char(text)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'varchar', casttarget => 'char', castfunc => 'char(text)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'text', casttarget => 'name', castfunc => 'name(text)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'bpchar', casttarget => 'name', castfunc => 'name(bpchar)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'varchar', casttarget => 'name', castfunc => 'name(varchar)', + castcontext => 'i', castmethod => 'f' }, + +# Allow explicit coercions between int4 and "char" +{ castsource => 'char', casttarget => 'int4', castfunc => 'int4(char)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'int4', casttarget => 'char', castfunc => 'char(int4)', + castcontext => 'e', castmethod => 'f' }, + +# pg_node_tree can be coerced to, but not from, text +{ castsource => 'pg_node_tree', casttarget => 'text', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, + +# pg_ndistinct can be coerced to, but not from, bytea and text +{ castsource => 'pg_ndistinct', casttarget => 'bytea', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'pg_ndistinct', casttarget => 'text', castfunc => '0', + castcontext => 'i', castmethod => 'i' }, + +# pg_dependencies can be coerced to, but not from, bytea and text +{ castsource => 'pg_dependencies', casttarget => 'bytea', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'pg_dependencies', casttarget => 'text', castfunc => '0', + castcontext => 'i', castmethod => 'i' }, + +# pg_mcv_list can be coerced to, but not from, bytea and text +{ castsource => 'pg_mcv_list', casttarget => 'bytea', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'pg_mcv_list', casttarget => 'text', castfunc => '0', + castcontext => 'i', castmethod => 'i' }, + +# Datetime category +{ castsource => 'date', casttarget => 'timestamp', + castfunc => 'timestamp(date)', castcontext => 'i', castmethod => 'f' }, +{ castsource => 'date', casttarget => 'timestamptz', + castfunc => 'timestamptz(date)', castcontext => 'i', castmethod => 'f' }, +{ castsource => 'time', casttarget => 'interval', castfunc => 'interval(time)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'time', casttarget => 'timetz', castfunc => 'timetz(time)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'timestamp', casttarget => 'date', + castfunc => 'date(timestamp)', castcontext => 'a', castmethod => 'f' }, +{ castsource => 'timestamp', casttarget => 'time', + castfunc => 'time(timestamp)', castcontext => 'a', castmethod => 'f' }, +{ castsource => 'timestamp', casttarget => 'timestamptz', + castfunc => 'timestamptz(timestamp)', castcontext => 'i', castmethod => 'f' }, +{ castsource => 'timestamptz', casttarget => 'date', + castfunc => 'date(timestamptz)', castcontext => 'a', castmethod => 'f' }, +{ castsource => 'timestamptz', casttarget => 'time', + castfunc => 'time(timestamptz)', castcontext => 'a', castmethod => 'f' }, +{ castsource => 'timestamptz', casttarget => 'timestamp', + castfunc => 'timestamp(timestamptz)', castcontext => 'a', castmethod => 'f' }, +{ castsource => 'timestamptz', casttarget => 'timetz', + castfunc => 'timetz(timestamptz)', castcontext => 'a', castmethod => 'f' }, +{ castsource => 'interval', casttarget => 'time', castfunc => 'time(interval)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'timetz', casttarget => 'time', castfunc => 'time(timetz)', + castcontext => 'a', castmethod => 'f' }, + +# Geometric category +{ castsource => 'point', casttarget => 'box', castfunc => 'box(point)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'lseg', casttarget => 'point', castfunc => 'point(lseg)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'path', casttarget => 'point', castfunc => 'point(path)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'path', casttarget => 'polygon', castfunc => 'polygon(path)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'box', casttarget => 'point', castfunc => 'point(box)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'box', casttarget => 'lseg', castfunc => 'lseg(box)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'box', casttarget => 'polygon', castfunc => 'polygon(box)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'box', casttarget => 'circle', castfunc => 'circle(box)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'polygon', casttarget => 'point', castfunc => 'point(polygon)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'polygon', casttarget => 'path', castfunc => 'path', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'polygon', casttarget => 'box', castfunc => 'box(polygon)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'polygon', casttarget => 'circle', + castfunc => 'circle(polygon)', castcontext => 'e', castmethod => 'f' }, +{ castsource => 'circle', casttarget => 'point', castfunc => 'point(circle)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'circle', casttarget => 'box', castfunc => 'box(circle)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'circle', casttarget => 'polygon', + castfunc => 'polygon(circle)', castcontext => 'e', castmethod => 'f' }, + +# MAC address category +{ castsource => 'macaddr', casttarget => 'macaddr8', castfunc => 'macaddr8', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'macaddr8', casttarget => 'macaddr', castfunc => 'macaddr', + castcontext => 'i', castmethod => 'f' }, + +# INET category +{ castsource => 'cidr', casttarget => 'inet', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'inet', casttarget => 'cidr', castfunc => 'cidr', + castcontext => 'a', castmethod => 'f' }, + +# BitString category +{ castsource => 'bit', casttarget => 'varbit', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, +{ castsource => 'varbit', casttarget => 'bit', castfunc => '0', + castcontext => 'i', castmethod => 'b' }, + +# Cross-category casts between bit and int4, int8 +{ castsource => 'int8', casttarget => 'bit', castfunc => 'bit(int8,int4)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'int4', casttarget => 'bit', castfunc => 'bit(int4,int4)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'bit', casttarget => 'int8', castfunc => 'int8(bit)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'bit', casttarget => 'int4', castfunc => 'int4(bit)', + castcontext => 'e', castmethod => 'f' }, + +# Cross-category casts to and from TEXT +# We need entries here only for a few specialized cases where the behavior +# of the cast function differs from the datatype's I/O functions. Otherwise, +# parse_coerce.c will generate CoerceViaIO operations without any prompting. +# Note that the castcontext values specified here should be no stronger than +# parse_coerce.c's automatic casts ('a' to text, 'e' from text) else odd +# behavior will ensue when the automatic cast is applied instead of the +# pg_cast entry! +{ castsource => 'cidr', casttarget => 'text', castfunc => 'text(inet)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'inet', casttarget => 'text', castfunc => 'text(inet)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'bool', casttarget => 'text', castfunc => 'text(bool)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'xml', casttarget => 'text', castfunc => '0', + castcontext => 'a', castmethod => 'b' }, +{ castsource => 'text', casttarget => 'xml', castfunc => 'xml', + castcontext => 'e', castmethod => 'f' }, + +# Cross-category casts to and from VARCHAR +# We support all the same casts as for TEXT. +{ castsource => 'cidr', casttarget => 'varchar', castfunc => 'text(inet)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'inet', casttarget => 'varchar', castfunc => 'text(inet)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'bool', casttarget => 'varchar', castfunc => 'text(bool)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'xml', casttarget => 'varchar', castfunc => '0', + castcontext => 'a', castmethod => 'b' }, +{ castsource => 'varchar', casttarget => 'xml', castfunc => 'xml', + castcontext => 'e', castmethod => 'f' }, + +# Cross-category casts to and from BPCHAR +# We support all the same casts as for TEXT. +{ castsource => 'cidr', casttarget => 'bpchar', castfunc => 'text(inet)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'inet', casttarget => 'bpchar', castfunc => 'text(inet)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'bool', casttarget => 'bpchar', castfunc => 'text(bool)', + castcontext => 'a', castmethod => 'f' }, +{ castsource => 'xml', casttarget => 'bpchar', castfunc => '0', + castcontext => 'a', castmethod => 'b' }, +{ castsource => 'bpchar', casttarget => 'xml', castfunc => 'xml', + castcontext => 'e', castmethod => 'f' }, + +# Length-coercion functions +{ castsource => 'bpchar', casttarget => 'bpchar', + castfunc => 'bpchar(bpchar,int4,bool)', castcontext => 'i', + castmethod => 'f' }, +{ castsource => 'varchar', casttarget => 'varchar', + castfunc => 'varchar(varchar,int4,bool)', castcontext => 'i', + castmethod => 'f' }, +{ castsource => 'time', casttarget => 'time', castfunc => 'time(time,int4)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'timestamp', casttarget => 'timestamp', + castfunc => 'timestamp(timestamp,int4)', castcontext => 'i', + castmethod => 'f' }, +{ castsource => 'timestamptz', casttarget => 'timestamptz', + castfunc => 'timestamptz(timestamptz,int4)', castcontext => 'i', + castmethod => 'f' }, +{ castsource => 'interval', casttarget => 'interval', + castfunc => 'interval(interval,int4)', castcontext => 'i', + castmethod => 'f' }, +{ castsource => 'timetz', casttarget => 'timetz', + castfunc => 'timetz(timetz,int4)', castcontext => 'i', castmethod => 'f' }, +{ castsource => 'bit', casttarget => 'bit', castfunc => 'bit(bit,int4,bool)', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'varbit', casttarget => 'varbit', castfunc => 'varbit', + castcontext => 'i', castmethod => 'f' }, +{ castsource => 'numeric', casttarget => 'numeric', + castfunc => 'numeric(numeric,int4)', castcontext => 'i', castmethod => 'f' }, + +# json to/from jsonb +{ castsource => 'json', casttarget => 'jsonb', castfunc => '0', + castcontext => 'a', castmethod => 'i' }, +{ castsource => 'jsonb', casttarget => 'json', castfunc => '0', + castcontext => 'a', castmethod => 'i' }, + +# jsonb to numeric and bool types +{ castsource => 'jsonb', casttarget => 'bool', castfunc => 'bool(jsonb)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'jsonb', casttarget => 'numeric', castfunc => 'numeric(jsonb)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'jsonb', casttarget => 'int2', castfunc => 'int2(jsonb)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'jsonb', casttarget => 'int4', castfunc => 'int4(jsonb)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'jsonb', casttarget => 'int8', castfunc => 'int8(jsonb)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'jsonb', casttarget => 'float4', castfunc => 'float4(jsonb)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'jsonb', casttarget => 'float8', castfunc => 'float8(jsonb)', + castcontext => 'e', castmethod => 'f' }, + +] diff --git a/ydb/library/yql/parser/pg_catalog/ut/catalog_ut.cpp b/ydb/library/yql/parser/pg_catalog/ut/catalog_ut.cpp index bf3b3aa360..17d50ed0ae 100644 --- a/ydb/library/yql/parser/pg_catalog/ut/catalog_ut.cpp +++ b/ydb/library/yql/parser/pg_catalog/ut/catalog_ut.cpp @@ -25,19 +25,19 @@ Y_UNIT_TEST_SUITE(TTypesTests) { UNIT_ASSERT_VALUES_EQUAL(ret.TypeId, 25); UNIT_ASSERT_VALUES_EQUAL(ret.ArrayTypeId, 1009); UNIT_ASSERT_VALUES_EQUAL(ret.Name, "text"); - UNIT_ASSERT_VALUES_EQUAL(ret.ElementType, ""); + UNIT_ASSERT_VALUES_EQUAL(ret.ElementTypeId, 0); ret = LookupType("point"); UNIT_ASSERT_VALUES_EQUAL(ret.TypeId, 600); UNIT_ASSERT_VALUES_EQUAL(ret.ArrayTypeId, 1017); UNIT_ASSERT_VALUES_EQUAL(ret.Name, "point"); - UNIT_ASSERT_VALUES_EQUAL(ret.ElementType, "float8"); + UNIT_ASSERT_VALUES_EQUAL(ret.ElementTypeId, LookupType("float8").TypeId); ret = LookupType(1009); UNIT_ASSERT_VALUES_EQUAL(ret.TypeId, 25); UNIT_ASSERT_VALUES_EQUAL(ret.ArrayTypeId, 1009); UNIT_ASSERT_VALUES_EQUAL(ret.Name, "text"); - UNIT_ASSERT_VALUES_EQUAL(ret.ElementType, ""); + UNIT_ASSERT_VALUES_EQUAL(ret.ElementTypeId, 0); } } @@ -75,3 +75,27 @@ Y_UNIT_TEST_SUITE(TFunctionsTests) { } } +Y_UNIT_TEST_SUITE(TCastsTests) { + Y_UNIT_TEST(TestMissing) { + UNIT_ASSERT_EXCEPTION(LookupCast(LookupType("circle").TypeId, LookupType("int8").TypeId), yexception); + } + + Y_UNIT_TEST(TestOk) { + auto ret = LookupCast(LookupType("int8").TypeId, LookupType("int4").TypeId); + UNIT_ASSERT_VALUES_EQUAL(ret.SourceId, LookupType("int8").TypeId); + UNIT_ASSERT_VALUES_EQUAL(ret.TargetId, LookupType("int4").TypeId); + UNIT_ASSERT(ret.Method == ECastMethod::Function); + UNIT_ASSERT_VALUES_UNEQUAL(ret.FunctionId, 0); + + ret = LookupCast(LookupType("int4").TypeId, LookupType("oid").TypeId); + UNIT_ASSERT_VALUES_EQUAL(ret.SourceId, LookupType("int4").TypeId); + UNIT_ASSERT_VALUES_EQUAL(ret.TargetId, LookupType("oid").TypeId); + UNIT_ASSERT(ret.Method == ECastMethod::Binary); + UNIT_ASSERT_VALUES_EQUAL(ret.FunctionId, 0); + + ret = LookupCast(LookupType("json").TypeId, LookupType("jsonb").TypeId); + UNIT_ASSERT_VALUES_EQUAL(ret.SourceId, LookupType("json").TypeId); + UNIT_ASSERT_VALUES_EQUAL(ret.TargetId, LookupType("jsonb").TypeId); + UNIT_ASSERT_VALUES_EQUAL(ret.FunctionId, 0); + } +} diff --git a/ydb/library/yql/parser/pg_catalog/ya.make b/ydb/library/yql/parser/pg_catalog/ya.make index c221747637..edd9301f9c 100644 --- a/ydb/library/yql/parser/pg_catalog/ya.make +++ b/ydb/library/yql/parser/pg_catalog/ya.make @@ -5,6 +5,7 @@ OWNER(g:yql) RESOURCE(pg_operator.dat pg_operator.dat) RESOURCE(pg_proc.dat pg_proc.dat) RESOURCE(pg_type.dat pg_type.dat) +RESOURCE(pg_cast.dat pg_cast.dat) SRCS( catalog.cpp |