Browse Source

implemented syscache RELNAMENSP (#2387)

Vitaly Stoyan 1 year ago
parent
commit
0b229ad454

+ 3 - 0
ydb/library/yql/parser/pg_wrapper/parser.cpp

@@ -20,6 +20,7 @@ extern "C" {
 #include "postgres.h"
 #include "access/session.h"
 #include "access/xact.h"
+#include "catalog/namespace.h"
 #include "mb/pg_wchar.h"
 #include "nodes/pg_list.h"
 #include "nodes/parsenodes.h"
@@ -269,4 +270,6 @@ extern "C" void setup_pg_thread_cleanup() {
     work_mem = MAX_KILOBYTES; // a way to postpone spilling for tuple stores
     assign_max_stack_depth(1024, nullptr);
     MyDatabaseId = 3; // from catalog.pg_database
+    namespace_search_path = pstrdup("public");
+    InitializeSessionUserId(nullptr, 1);
 };

+ 1 - 1
ydb/library/yql/parser/pg_wrapper/postgresql/src/backend/utils/cache/syscache.c

@@ -1233,7 +1233,7 @@ SearchSysCacheExists(int cacheId,
  * No lock is retained on the syscache entry.
  */
 Oid
-GetSysCacheOid(int cacheId,
+GetSysCacheOid_original(int cacheId,
 			   AttrNumber oidcol,
 			   Datum key1,
 			   Datum key2,

+ 1 - 1
ydb/library/yql/parser/pg_wrapper/postgresql/src/backend/utils/misc/guc.c

@@ -3241,7 +3241,7 @@ set_config_option(const char *name, const char *value,
 				(errcode(ERRCODE_INVALID_TRANSACTION_STATE),
 				 errmsg("cannot set parameters during a parallel operation")));
 
-	record = find_option(name, true, false, elevel);
+	record = find_option(name, true, true, elevel);
 	if (record == NULL)
 		return 0;
 

+ 123 - 15
ydb/library/yql/parser/pg_wrapper/syscache.cpp

@@ -6,7 +6,9 @@
 extern "C" {
 #include "utils/syscache.h"
 #include "catalog/pg_database.h"
+#include "catalog/pg_class.h"
 #include "catalog/pg_proc.h"
+#include "catalog/pg_namespace.h"
 #include "catalog/pg_type.h"
 #include "catalog/pg_type_d.h"
 #include "catalog/pg_authid.h"
@@ -52,9 +54,30 @@ bool OidEquals1(const THeapTupleKey& key1, const THeapTupleKey& key2) {
     return (Oid)std::get<0>(key1) == (Oid)std::get<0>(key2);
 }
 
+size_t NsNameHasher(const THeapTupleKey& key) {
+    return CombineHashes(
+        std::hash<std::string_view>()((const char*)std::get<0>(key)),
+        std::hash<Oid>()((Oid)std::get<1>(key)));
+}
+
+bool NsNameEquals(const THeapTupleKey& key1, const THeapTupleKey& key2) {
+    return strcmp((const char*)std::get<0>(key1), (const char*)std::get<0>(key2)) == 0 &&
+        (Oid)std::get<1>(key1) == (Oid)std::get<1>(key2);
+}
+
+struct TSysCacheItem {
+    TSysCacheItem(THeapTupleHasher hasher, THeapTupleEquals equals, TupleDesc desc)
+        : Map(0, hasher, equals)
+        , Desc(desc)
+    {}
+
+    TSysCacheHashMap Map;
+    TupleDesc Desc;
+};
+
 struct TSysCache {
     TArenaMemoryContext Arena;
-    std::unique_ptr<TSysCacheHashMap> Maps[SysCacheSize];
+    std::unique_ptr<TSysCacheItem> Items[SysCacheSize];
 
     static const TSysCache& Instance() {
         return *Singleton<TSysCache>();
@@ -66,6 +89,7 @@ struct TSysCache {
         InitializeTypes();
         InitializeDatabase();
         InitializeAuthId();
+        InitializeNameNamespaces();
         Arena.Release();
     }
 
@@ -85,7 +109,6 @@ struct TSysCache {
     }
 
     void InitializeProcs() {
-        auto& map = Maps[PROCOID] = std::make_unique<TSysCacheHashMap>(0, OidHasher1, OidEquals1);
         TupleDesc tupleDesc = CreateTemplateTupleDesc(Natts_pg_proc);
         FillAttr(tupleDesc, Anum_pg_proc_oid, OIDOID);
         FillAttr(tupleDesc, Anum_pg_proc_proname, NAMEOID);
@@ -117,6 +140,8 @@ struct TSysCache {
         FillAttr(tupleDesc, Anum_pg_proc_prosqlbody, PG_NODE_TREEOID);
         FillAttr(tupleDesc, Anum_pg_proc_proconfig, TEXTARRAYOID);
         FillAttr(tupleDesc, Anum_pg_proc_proacl, ACLITEMARRAYOID);
+        auto& cacheItem = Items[PROCOID] = std::make_unique<TSysCacheItem>(OidHasher1, OidEquals1, tupleDesc);
+        auto& map = cacheItem->Map;
 
         NPg::EnumProc([&](ui32 oid, const NPg::TProcDesc& desc){
             auto key = THeapTupleKey(oid, 0, 0, 0);
@@ -128,19 +153,18 @@ struct TSysCache {
             std::fill_n(nulls, Anum_pg_proc_prorettype, false); // fixed part of Form_pg_proc
             FillDatum(Natts_pg_proc, values, nulls, Anum_pg_proc_oid, oid);
             FillDatum(Natts_pg_proc, values, nulls, Anum_pg_proc_prorettype, desc.ResultType);
-            auto name = MakeFixedString(desc.Name, NPg::LookupType(NAMEOID).TypeLen);
+            auto name = MakeFixedString(desc.Name, NAMEDATALEN);
             FillDatum(Natts_pg_proc, values, nulls, Anum_pg_proc_proname, (Datum)name);
             HeapTuple h = heap_form_tuple(tupleDesc, values, nulls);
             auto row = (Form_pg_proc)GETSTRUCT(h);
             Y_ENSURE(row->oid == oid);
             Y_ENSURE(row->prorettype == desc.ResultType);
             Y_ENSURE(NameStr(row->proname) == desc.Name);
-            map->emplace(key, h);
+            map.emplace(key, h);
         });
     }
 
     void InitializeTypes() {
-        auto& map = Maps[TYPEOID] = std::make_unique<TSysCacheHashMap>(0, OidHasher1, OidEquals1);
         TupleDesc tupleDesc = CreateTemplateTupleDesc(Natts_pg_type);
         FillAttr(tupleDesc, Anum_pg_type_oid, OIDOID);
         FillAttr(tupleDesc, Anum_pg_type_typname, NAMEOID);
@@ -174,6 +198,8 @@ struct TSysCache {
         FillAttr(tupleDesc, Anum_pg_type_typdefaultbin, PG_NODE_TREEOID);
         FillAttr(tupleDesc, Anum_pg_type_typdefault, TEXTOID);
         FillAttr(tupleDesc, Anum_pg_type_typacl, ACLITEMARRAYOID);
+        auto& cacheItems = Items[TYPEOID] = std::make_unique<TSysCacheItem>(OidHasher1, OidEquals1, tupleDesc);
+        auto& map = cacheItems->Map;
 
         NPg::EnumTypes([&](ui32 oid, const NPg::TTypeDesc& desc){
             auto key = THeapTupleKey(oid, 0, 0, 0);
@@ -226,13 +252,12 @@ struct TSysCache {
             Y_ENSURE(row->typmodout == desc.TypeModOutFuncId);
             Y_ENSURE(row->typalign == desc.TypeAlign);
             Y_ENSURE(row->typstorage == TYPSTORAGE_PLAIN);
-            map->emplace(key, h);
+            map.emplace(key, h);
         });
 
     }
 
     void InitializeDatabase() {
-        auto& map = Maps[DATABASEOID] = std::make_unique<TSysCacheHashMap>(0, OidHasher1, OidEquals1);
         TupleDesc tupleDesc = CreateTemplateTupleDesc(Natts_pg_database);
         FillAttr(tupleDesc, Anum_pg_database_oid, OIDOID);
         FillAttr(tupleDesc, Anum_pg_database_datname, NAMEOID);
@@ -248,6 +273,8 @@ struct TSysCache {
         FillAttr(tupleDesc, Anum_pg_database_datminmxid, XIDOID);
         FillAttr(tupleDesc, Anum_pg_database_dattablespace, OIDOID);
         FillAttr(tupleDesc, Anum_pg_database_datacl, ACLITEMARRAYOID);
+        auto& cacheItems = Items[DATABASEOID] = std::make_unique<TSysCacheItem>(OidHasher1, OidEquals1, tupleDesc);
+        auto& map = cacheItems->Map;
 
         for (ui32 oid = 1; oid <= 3; ++oid) {
             auto key = THeapTupleKey(oid, 0, 0, 0);
@@ -269,12 +296,11 @@ struct TSysCache {
             auto row = (Form_pg_database) GETSTRUCT(h);
             Y_ENSURE(row->oid == oid);
             Y_ENSURE(strcmp(NameStr(row->datname), name) == 0);
-            map->emplace(key, h);
+            map.emplace(key, h);
         }
     }
 
     void InitializeAuthId() {
-        auto& map = Maps[AUTHOID] = std::make_unique<TSysCacheHashMap>(0, OidHasher1, OidEquals1);
         TupleDesc tupleDesc = CreateTemplateTupleDesc(Natts_pg_authid);
         FillAttr(tupleDesc, Anum_pg_authid_oid, OIDOID);
         FillAttr(tupleDesc, Anum_pg_authid_rolname, NAMEOID);
@@ -288,6 +314,9 @@ struct TSysCache {
         FillAttr(tupleDesc, Anum_pg_authid_rolconnlimit, INT4OID);
         FillAttr(tupleDesc, Anum_pg_authid_rolpassword, TEXTOID);
         FillAttr(tupleDesc, Anum_pg_authid_rolvaliduntil, TIMESTAMPTZOID);
+        auto& cacheItems = Items[AUTHOID] = std::make_unique<TSysCacheItem>(OidHasher1, OidEquals1, tupleDesc);
+        auto& map = cacheItems->Map;
+
         auto key = THeapTupleKey(1, 0, 0, 0);
 
         const char* rolname = "postgres";
@@ -318,7 +347,69 @@ struct TSysCache {
         Y_ENSURE(row->rolreplication);
         Y_ENSURE(row->rolbypassrls);
         Y_ENSURE(row->rolconnlimit == -1);
-        map->emplace(key, h);
+        map.emplace(key, h);
+    }
+
+    void InitializeNameNamespaces() {
+        TupleDesc tupleDesc = CreateTemplateTupleDesc(Natts_pg_class);
+        FillAttr(tupleDesc, Anum_pg_class_oid, OIDOID);
+        FillAttr(tupleDesc, Anum_pg_class_relname, NAMEOID);
+        FillAttr(tupleDesc, Anum_pg_class_relnamespace, OIDOID);
+        FillAttr(tupleDesc, Anum_pg_class_reltype, OIDOID);
+        FillAttr(tupleDesc, Anum_pg_class_reloftype, OIDOID);
+        FillAttr(tupleDesc, Anum_pg_class_relowner, OIDOID);
+        FillAttr(tupleDesc, Anum_pg_class_relam, OIDOID);
+        FillAttr(tupleDesc, Anum_pg_class_relfilenode, OIDOID);
+        FillAttr(tupleDesc, Anum_pg_class_reltablespace, OIDOID);
+        FillAttr(tupleDesc, Anum_pg_class_relpages, INT4OID);
+        FillAttr(tupleDesc, Anum_pg_class_reltuples, FLOAT4OID);
+        FillAttr(tupleDesc, Anum_pg_class_relallvisible, INT4OID);
+        FillAttr(tupleDesc, Anum_pg_class_reltoastrelid, OIDOID);
+        FillAttr(tupleDesc, Anum_pg_class_relhasindex, BOOLOID);
+        FillAttr(tupleDesc, Anum_pg_class_relisshared, BOOLOID);
+        FillAttr(tupleDesc, Anum_pg_class_relpersistence, CHAROID);
+        FillAttr(tupleDesc, Anum_pg_class_relkind, CHAROID);
+        FillAttr(tupleDesc, Anum_pg_class_relnatts, INT2OID);
+        FillAttr(tupleDesc, Anum_pg_class_relchecks, INT2OID);
+        FillAttr(tupleDesc, Anum_pg_class_relhasrules, BOOLOID);
+        FillAttr(tupleDesc, Anum_pg_class_relhastriggers, BOOLOID);
+        FillAttr(tupleDesc, Anum_pg_class_relhassubclass, BOOLOID);
+        FillAttr(tupleDesc, Anum_pg_class_relrowsecurity, BOOLOID);
+        FillAttr(tupleDesc, Anum_pg_class_relforcerowsecurity, BOOLOID);
+        FillAttr(tupleDesc, Anum_pg_class_relispopulated, BOOLOID);
+        FillAttr(tupleDesc, Anum_pg_class_relreplident, CHAROID);
+        FillAttr(tupleDesc, Anum_pg_class_relispartition, BOOLOID);
+        FillAttr(tupleDesc, Anum_pg_class_relrewrite, OIDOID);
+        FillAttr(tupleDesc, Anum_pg_class_relfrozenxid, XIDOID);
+        FillAttr(tupleDesc, Anum_pg_class_relminmxid, XIDOID);
+        FillAttr(tupleDesc, Anum_pg_class_relacl, ACLITEMARRAYOID);
+        FillAttr(tupleDesc, Anum_pg_class_reloptions, TEXTARRAYOID);
+        FillAttr(tupleDesc, Anum_pg_class_relpartbound, PG_NODE_TREEOID);
+        auto& cacheItems = Items[RELNAMENSP] = std::make_unique<TSysCacheItem>(NsNameHasher, NsNameEquals, tupleDesc);
+        auto& map = cacheItems->Map;
+
+        Datum values[Natts_pg_class];
+        bool nulls[Natts_pg_class];
+        Zero(values);
+        std::fill_n(nulls, Natts_pg_class, true);
+        std::fill_n(nulls, Anum_pg_class_relminmxid, false); // fixed part of Form_pg_class
+        for (const auto& t : NPg::GetStaticTables()) {
+            auto name = (Datum)MakeFixedString(t.Name, NAMEDATALEN);
+            auto ns = (Datum)(t.Schema == "pg_catalog" ? PG_CATALOG_NAMESPACE : 1);
+            FillDatum(Natts_pg_class, values, nulls, Anum_pg_class_oid, (Datum)t.Oid);
+            FillDatum(Natts_pg_class, values, nulls, Anum_pg_class_relname, name);
+            FillDatum(Natts_pg_class, values, nulls, Anum_pg_class_relnamespace, ns);
+            FillDatum(Natts_pg_class, values, nulls, Anum_pg_class_relowner, (Datum)1);
+            HeapTuple h = heap_form_tuple(tupleDesc, values, nulls);
+            auto row = (Form_pg_class) GETSTRUCT(h);
+            Y_ENSURE(row->oid == t.Oid);
+            Y_ENSURE(strcmp(NameStr(row->relname), t.Name.c_str()) == 0);
+            Y_ENSURE(row->relowner == 1);
+            Y_ENSURE(row->relnamespace == ns);
+
+            auto key = THeapTupleKey(name, ns, 0, 0);
+            map.emplace(key, h);
+        }
     }
 };
 
@@ -327,14 +418,15 @@ struct TSysCache {
 
 
 HeapTuple SearchSysCache(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4) {
-	Y_ENSURE(cacheId >= 0 && cacheId < SysCacheSize);
-    const auto& map = NYql::TSysCache::Instance().Maps[cacheId];
-    if (!map) {
+    Y_ENSURE(cacheId >= 0 && cacheId < SysCacheSize);
+    const auto& cacheItem = NYql::TSysCache::Instance().Items[cacheId];
+    if (!cacheItem) {
         return nullptr;
     }
 
-    auto it = map->find(std::make_tuple(key1, key2, key3, key4));
-    if (it == map->end()) {
+    const auto& map = cacheItem->Map;
+    auto it = map.find(std::make_tuple(key1, key2, key3, key4));
+    if (it == map.end()) {
         return nullptr;
     }
 
@@ -361,4 +453,20 @@ void ReleaseSysCache(HeapTuple tuple) {
     Y_UNUSED(tuple);
 }
 
+Oid GetSysCacheOid(int cacheId, AttrNumber oidcol, Datum key1, Datum key2, Datum key3, Datum key4) {
+    Y_ENSURE(cacheId >= 0 && cacheId < SysCacheSize);
+    const auto& cacheItem = NYql::TSysCache::Instance().Items[cacheId];
+    HeapTuple tuple;
+    bool isNull;
+    Oid result;
+
+    tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
+    if (!HeapTupleIsValid(tuple))
+        return InvalidOid;
+    result = heap_getattr(tuple, oidcol, cacheItem->Desc, &isNull);
+    Y_ENSURE(!isNull); /* columns used as oids should never be NULL */
+    ReleaseSysCache(tuple);
+    return result;
+}
+
 

+ 4 - 0
ydb/library/yql/parser/pg_wrapper/ya.make

@@ -62,6 +62,10 @@ ELSE()
 CFLAGS(-DUSE_SLOW_PG_KERNELS)
 ENDIF()
 
+IF (BUILD_TYPE == "DEBUG")
+CFLAGS(-DDISABLE_COMPLEX_MACRO)
+ENDIF()
+
 PEERDIR(
     library/cpp/resource
     library/cpp/yson