aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvvvv <vvvv@yandex-team.ru>2022-02-28 17:11:47 +0300
committervvvv <vvvv@yandex-team.ru>2022-02-28 17:11:47 +0300
commit6ac6c4437f83290eda1016f9ab6b95fc8ab4649b (patch)
treeb1cdca5ff4e986601e6e6c459fbf41e5ac902877
parenta416bd196ecff50852933f545a8f6457799a707f (diff)
downloadydb-6ac6c4437f83290eda1016f9ab6b95fc8ab4649b.tar.gz
YQL-13710 [pg_catalog] pg_cast
ref:e52812aa7033eca23750524503d18e980159b548
-rw-r--r--ydb/library/yql/parser/pg_catalog/CMakeLists.txt8
-rw-r--r--ydb/library/yql/parser/pg_catalog/catalog.cpp163
-rw-r--r--ydb/library/yql/parser/pg_catalog/catalog.h19
-rw-r--r--ydb/library/yql/parser/pg_catalog/pg_cast.dat533
-rw-r--r--ydb/library/yql/parser/pg_catalog/ut/catalog_ut.cpp30
-rw-r--r--ydb/library/yql/parser/pg_catalog/ya.make1
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