5
5
6
6
extern " C" {
7
7
#include " utils/syscache.h"
8
+ #include " utils/catcache.h"
8
9
#include " catalog/pg_database.h"
9
10
#include " catalog/pg_class.h"
10
11
#include " catalog/pg_proc.h"
@@ -47,6 +48,13 @@ using THeapTupleHasher = std::function<size_t(const THeapTupleKey&)>;
47
48
using THeapTupleEquals = std::function<bool (const THeapTupleKey&, const THeapTupleKey&)>;
48
49
using TSysCacheHashMap = std::unordered_map<THeapTupleKey, HeapTuple, THeapTupleHasher, THeapTupleEquals>;
49
50
51
+ struct TRangeItem {
52
+ TVector<HeapTuple> Items;
53
+ CatCList* CList = nullptr ;
54
+ };
55
+
56
+ using TSysCacheRangeMap = std::unordered_map<THeapTupleKey, TRangeItem, THeapTupleHasher, THeapTupleEquals>;
57
+
50
58
size_t OidHasher1 (const THeapTupleKey& key) {
51
59
return std::hash<Oid>()((Oid)std::get<0 >(key));
52
60
}
@@ -66,14 +74,124 @@ bool NsNameEquals(const THeapTupleKey& key1, const THeapTupleKey& key2) {
66
74
(Oid)std::get<1 >(key1) == (Oid)std::get<1 >(key2);
67
75
}
68
76
77
+ size_t OidVectorHash (Datum d) {
78
+ oidvector *v = (oidvector *)d;
79
+ if (!v->ndim ) {
80
+ return 0 ;
81
+ }
82
+
83
+ Y_DEBUG_ABORT_UNLESS (v->ndim == 1 );
84
+ size_t hash = v->dim1 ;
85
+ for (int i = 0 ; i < v->dim1 ; ++i) {
86
+ hash = CombineHashes (hash, std::hash<Oid>()(v->values [i]));
87
+ }
88
+
89
+ return hash;
90
+ }
91
+
92
+ bool OidVectorEquals (Datum d1, Datum d2) {
93
+ oidvector *v1 = (oidvector *)d1;
94
+ oidvector *v2 = (oidvector *)d2;
95
+ if (v1->ndim != v2->ndim ) {
96
+ return false ;
97
+ }
98
+
99
+ if (v1->ndim == 0 ) {
100
+ return true ;
101
+ }
102
+
103
+ Y_DEBUG_ABORT_UNLESS (v1->ndim == 1 );
104
+ if (v1->dim1 != v2->dim1 ) {
105
+ return false ;
106
+ }
107
+
108
+ for (int i = 0 ; i < v1->dim1 ; ++i) {
109
+ if (v1->values [i] != v2->values [i]) {
110
+ return false ;
111
+ }
112
+ }
113
+
114
+ return true ;
115
+ }
116
+
117
+ size_t ByNameProcHasher1 (const THeapTupleKey& key) {
118
+ return std::hash<std::string_view>()((const char *)std::get<0 >(key));
119
+ }
120
+
121
+ size_t ByNameProcHasher3 (const THeapTupleKey& key) {
122
+ return CombineHashes (CombineHashes (std::hash<std::string_view>()((const char *)std::get<0 >(key)),
123
+ OidVectorHash (std::get<1 >(key))),
124
+ std::hash<Oid>()((Oid)std::get<2 >(key)));
125
+ }
126
+
127
+ bool ByNameProcEquals1 (const THeapTupleKey& key1, const THeapTupleKey& key2) {
128
+ return strcmp ((const char *)std::get<0 >(key1), (const char *)std::get<0 >(key2)) == 0 ;
129
+ }
130
+
131
+ bool ByNameProcEquals3 (const THeapTupleKey& key1, const THeapTupleKey& key2) {
132
+ return strcmp ((const char *)std::get<0 >(key1), (const char *)std::get<0 >(key2)) == 0 &&
133
+ OidVectorEquals (std::get<1 >(key1), std::get<1 >(key2)) &&
134
+ (Oid)std::get<2 >(key1) == (Oid)std::get<2 >(key2);
135
+ }
136
+
69
137
struct TSysCacheItem {
70
- TSysCacheItem (THeapTupleHasher hasher, THeapTupleEquals equals, TupleDesc desc)
71
- : Map(0 , hasher, equals)
138
+ TSysCacheItem (THeapTupleHasher hasher, THeapTupleEquals equals, TupleDesc desc, ui32 numKeys = 1 ,
139
+ THeapTupleHasher hasherRange1 = {}, THeapTupleEquals equalsRange1 = {})
140
+ : NumKeys(numKeys)
141
+ , LookupMap(0 , hasher, equals)
142
+ , RangeMap1(numKeys > 1 ? TMaybe<TSysCacheRangeMap>(TSysCacheRangeMap(0 , hasherRange1, equalsRange1)) : Nothing())
72
143
, Desc(desc)
73
144
{}
74
145
75
- TSysCacheHashMap Map;
146
+ CatCList* BuildCList (const TVector<HeapTuple>& items) {
147
+ auto cl = (CatCList *)palloc (offsetof (CatCList, members) + items.size () * sizeof (CatCTup *));
148
+ cl->cl_magic = CL_MAGIC;
149
+ cl->my_cache = nullptr ;
150
+ cl->refcount = 0 ;
151
+ cl->dead = false ;
152
+ cl->ordered = false ;
153
+ cl->nkeys = NumKeys;
154
+ cl->hash_value = 0 ;
155
+ cl->n_members = items.size ();
156
+ for (size_t i = 0 ; i < items.size (); ++i) {
157
+ auto dtp = items[i];
158
+ auto ct = (CatCTup *) palloc (sizeof (CatCTup) + MAXIMUM_ALIGNOF + dtp->t_len );
159
+ ct->ct_magic = CT_MAGIC;
160
+ ct->my_cache = nullptr ;
161
+ ct->c_list = NULL ;
162
+ ct->refcount = 0 ;
163
+ ct->dead = false ;
164
+ ct->negative = false ;
165
+ ct->hash_value = 0 ;
166
+ Zero (ct->keys );
167
+
168
+ ct->tuple .t_len = dtp->t_len ;
169
+ ct->tuple .t_self = dtp->t_self ;
170
+ ct->tuple .t_tableOid = dtp->t_tableOid ;
171
+ ct->tuple .t_data = (HeapTupleHeader)MAXALIGN (((char *) ct) + sizeof (CatCTup));
172
+ /* copy tuple contents */
173
+ std::memcpy ((char *) ct->tuple .t_data , (const char *) dtp->t_data , dtp->t_len );
174
+ cl->members [i] = ct;
175
+ }
176
+
177
+ return cl;
178
+ }
179
+
180
+ void FinalizeRangeMaps () {
181
+ if (RangeMap1) {
182
+ for (auto & x : *RangeMap1) {
183
+ x.second .CList = BuildCList (x.second .Items );
184
+ }
185
+ }
186
+
187
+ EmptyCList = BuildCList ({});
188
+ }
189
+
190
+ const ui32 NumKeys;
191
+ TSysCacheHashMap LookupMap;
192
+ TMaybe<TSysCacheRangeMap> RangeMap1;
76
193
TupleDesc Desc;
194
+ CatCList* EmptyCList = nullptr ;
77
195
};
78
196
79
197
struct TSysCache {
@@ -91,6 +209,12 @@ struct TSysCache {
91
209
InitializeDatabase ();
92
210
InitializeAuthId ();
93
211
InitializeNameNamespaces ();
212
+ for (auto & item : Items) {
213
+ if (item) {
214
+ item->FinalizeRangeMaps ();
215
+ }
216
+ }
217
+
94
218
Arena.Release ();
95
219
}
96
220
@@ -142,7 +266,11 @@ struct TSysCache {
142
266
FillAttr (tupleDesc, Anum_pg_proc_proconfig, TEXTARRAYOID);
143
267
FillAttr (tupleDesc, Anum_pg_proc_proacl, ACLITEMARRAYOID);
144
268
auto & cacheItem = Items[PROCOID] = std::make_unique<TSysCacheItem>(OidHasher1, OidEquals1, tupleDesc);
145
- auto & map = cacheItem->Map ;
269
+ auto & lookupMap = cacheItem->LookupMap ;
270
+
271
+ auto & byNameCacheItem = Items[PROCNAMEARGSNSP] = std::make_unique<TSysCacheItem>(ByNameProcHasher3, ByNameProcEquals3, tupleDesc, 3 , ByNameProcHasher1, ByNameProcEquals1);
272
+ auto & byNameLookupMap = byNameCacheItem->LookupMap ;
273
+ auto & byNameRangeMap1 = *byNameCacheItem->RangeMap1 ;
146
274
147
275
const auto & oidDesc = NPg::LookupType (OIDOID);
148
276
const auto & charDesc = NPg::LookupType (CHAROID);
@@ -236,7 +364,13 @@ struct TSysCache {
236
364
Y_ENSURE (row->prorettype == desc.ResultType );
237
365
Y_ENSURE (NameStr (row->proname ) == desc.Name );
238
366
Y_ENSURE (row->pronargs == desc.ArgTypes .size ());
239
- map.emplace (key, h);
367
+ lookupMap.emplace (key, h);
368
+
369
+ THeapTupleKey byNameLookupKey ((Datum)name, (Datum)&row->proargtypes , PG_CATALOG_NAMESPACE, 0 );
370
+ THeapTupleKey byNameRangeKey1 ((Datum)name, 0 , 0 , 0 );
371
+
372
+ byNameLookupMap.emplace (byNameLookupKey, h);
373
+ byNameRangeMap1[byNameRangeKey1].Items .push_back (h);
240
374
});
241
375
}
242
376
@@ -274,8 +408,8 @@ struct TSysCache {
274
408
FillAttr (tupleDesc, Anum_pg_type_typdefaultbin, PG_NODE_TREEOID);
275
409
FillAttr (tupleDesc, Anum_pg_type_typdefault, TEXTOID);
276
410
FillAttr (tupleDesc, Anum_pg_type_typacl, ACLITEMARRAYOID);
277
- auto & cacheItems = Items[TYPEOID] = std::make_unique<TSysCacheItem>(OidHasher1, OidEquals1, tupleDesc);
278
- auto & map = cacheItems-> Map ;
411
+ auto & cacheItem = Items[TYPEOID] = std::make_unique<TSysCacheItem>(OidHasher1, OidEquals1, tupleDesc);
412
+ auto & lookupMap = cacheItem-> LookupMap ;
279
413
280
414
NPg::EnumTypes ([&](ui32 oid, const NPg::TTypeDesc& desc){
281
415
auto key = THeapTupleKey (oid, 0 , 0 , 0 );
@@ -329,7 +463,7 @@ struct TSysCache {
329
463
Y_ENSURE (row->typmodout == desc.TypeModOutFuncId );
330
464
Y_ENSURE (row->typalign == desc.TypeAlign );
331
465
Y_ENSURE (row->typstorage == storage);
332
- map .emplace (key, h);
466
+ lookupMap .emplace (key, h);
333
467
});
334
468
335
469
}
@@ -350,8 +484,8 @@ struct TSysCache {
350
484
FillAttr (tupleDesc, Anum_pg_database_datminmxid, XIDOID);
351
485
FillAttr (tupleDesc, Anum_pg_database_dattablespace, OIDOID);
352
486
FillAttr (tupleDesc, Anum_pg_database_datacl, ACLITEMARRAYOID);
353
- auto & cacheItems = Items[DATABASEOID] = std::make_unique<TSysCacheItem>(OidHasher1, OidEquals1, tupleDesc);
354
- auto & map = cacheItems-> Map ;
487
+ auto & cacheItem = Items[DATABASEOID] = std::make_unique<TSysCacheItem>(OidHasher1, OidEquals1, tupleDesc);
488
+ auto & lookupMap = cacheItem-> LookupMap ;
355
489
356
490
for (ui32 oid = 1 ; oid <= 3 ; ++oid) {
357
491
auto key = THeapTupleKey (oid, 0 , 0 , 0 );
@@ -373,7 +507,7 @@ struct TSysCache {
373
507
auto row = (Form_pg_database) GETSTRUCT (h);
374
508
Y_ENSURE (row->oid == oid);
375
509
Y_ENSURE (strcmp (NameStr (row->datname ), name) == 0 );
376
- map .emplace (key, h);
510
+ lookupMap .emplace (key, h);
377
511
}
378
512
}
379
513
@@ -391,8 +525,8 @@ struct TSysCache {
391
525
FillAttr (tupleDesc, Anum_pg_authid_rolconnlimit, INT4OID);
392
526
FillAttr (tupleDesc, Anum_pg_authid_rolpassword, TEXTOID);
393
527
FillAttr (tupleDesc, Anum_pg_authid_rolvaliduntil, TIMESTAMPTZOID);
394
- auto & cacheItems = Items[AUTHOID] = std::make_unique<TSysCacheItem>(OidHasher1, OidEquals1, tupleDesc);
395
- auto & map = cacheItems-> Map ;
528
+ auto & cacheItem = Items[AUTHOID] = std::make_unique<TSysCacheItem>(OidHasher1, OidEquals1, tupleDesc);
529
+ auto & lookupMap = cacheItem-> LookupMap ;
396
530
397
531
auto key = THeapTupleKey (1 , 0 , 0 , 0 );
398
532
@@ -424,7 +558,7 @@ struct TSysCache {
424
558
Y_ENSURE (row->rolreplication );
425
559
Y_ENSURE (row->rolbypassrls );
426
560
Y_ENSURE (row->rolconnlimit == -1 );
427
- map .emplace (key, h);
561
+ lookupMap .emplace (key, h);
428
562
}
429
563
430
564
void InitializeNameNamespaces () {
@@ -462,8 +596,8 @@ struct TSysCache {
462
596
FillAttr (tupleDesc, Anum_pg_class_relacl, ACLITEMARRAYOID);
463
597
FillAttr (tupleDesc, Anum_pg_class_reloptions, TEXTARRAYOID);
464
598
FillAttr (tupleDesc, Anum_pg_class_relpartbound, PG_NODE_TREEOID);
465
- auto & cacheItems = Items[RELNAMENSP] = std::make_unique<TSysCacheItem>(NsNameHasher, NsNameEquals, tupleDesc);
466
- auto & map = cacheItems-> Map ;
599
+ auto & cacheItem = Items[RELNAMENSP] = std::make_unique<TSysCacheItem>(NsNameHasher, NsNameEquals, tupleDesc);
600
+ auto & lookupMap = cacheItem-> LookupMap ;
467
601
468
602
Datum values[Natts_pg_class];
469
603
bool nulls[Natts_pg_class];
@@ -485,7 +619,7 @@ struct TSysCache {
485
619
Y_ENSURE (row->relnamespace == ns);
486
620
487
621
auto key = THeapTupleKey (name, ns, 0 , 0 );
488
- map .emplace (key, h);
622
+ lookupMap .emplace (key, h);
489
623
}
490
624
}
491
625
};
@@ -501,9 +635,9 @@ HeapTuple SearchSysCache(int cacheId, Datum key1, Datum key2, Datum key3, Datum
501
635
return nullptr ;
502
636
}
503
637
504
- const auto & map = cacheItem->Map ;
505
- auto it = map .find (std::make_tuple (key1, key2, key3, key4));
506
- if (it == map .end ()) {
638
+ const auto & lookupMap = cacheItem->LookupMap ;
639
+ auto it = lookupMap .find (std::make_tuple (key1, key2, key3, key4));
640
+ if (it == lookupMap .end ()) {
507
641
return nullptr ;
508
642
}
509
643
@@ -554,3 +688,21 @@ Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bo
554
688
Y_ENSURE (cacheItem);
555
689
return heap_getattr (tup, attributeNumber, cacheItem->Desc , isNull);
556
690
}
691
+
692
+ struct catclist * SearchSysCacheList (int cacheId, int nkeys, Datum key1, Datum key2, Datum key3) {
693
+ Y_ENSURE (cacheId >= 0 && cacheId < SysCacheSize);
694
+ const auto & cacheItem = NYql::TSysCache::Instance ().Items [cacheId];
695
+ Y_ENSURE (cacheItem);
696
+ if (nkeys == 1 && cacheItem->NumKeys > 1 ) {
697
+ const auto & rangeMap1 = *cacheItem->RangeMap1 ;
698
+ auto it = rangeMap1.find (std::make_tuple (key1, 0 , 0 , 0 ));
699
+ if (it == rangeMap1.end ()) {
700
+ return cacheItem->EmptyCList ;
701
+ }
702
+
703
+ return it->second .CList ;
704
+ }
705
+
706
+ return cacheItem->EmptyCList ;
707
+ }
708
+
0 commit comments