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"
@@ -15,6 +16,7 @@ extern "C" {
15
16
#include " access/htup_details.h"
16
17
#include " utils/fmgroids.h"
17
18
#include " utils/array.h"
19
+ #include " utils/builtins.h"
18
20
}
19
21
20
22
#undef TypeName
@@ -47,6 +49,13 @@ using THeapTupleHasher = std::function<size_t(const THeapTupleKey&)>;
47
49
using THeapTupleEquals = std::function<bool (const THeapTupleKey&, const THeapTupleKey&)>;
48
50
using TSysCacheHashMap = std::unordered_map<THeapTupleKey, HeapTuple, THeapTupleHasher, THeapTupleEquals>;
49
51
52
+ struct TRangeItem {
53
+ TVector<HeapTuple> Items;
54
+ CatCList* CList = nullptr ;
55
+ };
56
+
57
+ using TSysCacheRangeMap = std::unordered_map<THeapTupleKey, TRangeItem, THeapTupleHasher, THeapTupleEquals>;
58
+
50
59
size_t OidHasher1 (const THeapTupleKey& key) {
51
60
return std::hash<Oid>()((Oid)std::get<0 >(key));
52
61
}
@@ -66,14 +75,112 @@ bool NsNameEquals(const THeapTupleKey& key1, const THeapTupleKey& key2) {
66
75
(Oid)std::get<1 >(key1) == (Oid)std::get<1 >(key2);
67
76
}
68
77
78
+ size_t OidVectorHash (Datum d) {
79
+ oidvector *v = (oidvector *)d;
80
+ Y_DEBUG_ABORT_UNLESS (v->ndim == 1 );
81
+ size_t hash = v->dim1 ;
82
+ for (int i = 0 ; i < v->dim1 ; ++i) {
83
+ hash = CombineHashes (hash, std::hash<Oid>()(v->values [i]));
84
+ }
85
+
86
+ return hash;
87
+ }
88
+
89
+ bool OidVectorEquals (Datum d1, Datum d2) {
90
+ oidvector *v1 = (oidvector *)d1;
91
+ oidvector *v2 = (oidvector *)d2;
92
+ Y_DEBUG_ABORT_UNLESS (v1->ndim == 1 && v2->ndim == 1 );
93
+ if (v1->dim1 != v2->dim1 ) {
94
+ return false ;
95
+ }
96
+
97
+ for (int i = 0 ; i < v1->dim1 ; ++i) {
98
+ if (v1->values [i] != v2->values [i]) {
99
+ return false ;
100
+ }
101
+ }
102
+
103
+ return true ;
104
+ }
105
+
106
+ size_t ByNameProcHasher1 (const THeapTupleKey& key) {
107
+ return std::hash<std::string_view>()((const char *)std::get<0 >(key));
108
+ }
109
+
110
+ size_t ByNameProcHasher3 (const THeapTupleKey& key) {
111
+ return CombineHashes (CombineHashes (std::hash<std::string_view>()((const char *)std::get<0 >(key)),
112
+ OidVectorHash (std::get<1 >(key))),
113
+ std::hash<Oid>()((Oid)std::get<2 >(key)));
114
+ }
115
+
116
+ bool ByNameProcEquals1 (const THeapTupleKey& key1, const THeapTupleKey& key2) {
117
+ return strcmp ((const char *)std::get<0 >(key1), (const char *)std::get<0 >(key2)) == 0 ;
118
+ }
119
+
120
+ bool ByNameProcEquals3 (const THeapTupleKey& key1, const THeapTupleKey& key2) {
121
+ return strcmp ((const char *)std::get<0 >(key1), (const char *)std::get<0 >(key2)) == 0 &&
122
+ OidVectorEquals (std::get<1 >(key1), std::get<1 >(key2)) &&
123
+ (Oid)std::get<2 >(key1) == (Oid)std::get<2 >(key2);
124
+ }
125
+
69
126
struct TSysCacheItem {
70
- TSysCacheItem (THeapTupleHasher hasher, THeapTupleEquals equals, TupleDesc desc)
71
- : Map(0 , hasher, equals)
127
+ TSysCacheItem (THeapTupleHasher hasher, THeapTupleEquals equals, TupleDesc desc, ui32 numKeys = 1 ,
128
+ THeapTupleHasher hasherRange1 = {}, THeapTupleEquals equalsRange1 = {})
129
+ : NumKeys(numKeys)
130
+ , LookupMap(0 , hasher, equals)
131
+ , RangeMap1(numKeys > 1 ? TMaybe<TSysCacheRangeMap>(TSysCacheRangeMap(0 , hasherRange1, equalsRange1)) : Nothing())
72
132
, Desc(desc)
73
133
{}
74
134
75
- TSysCacheHashMap Map;
135
+ CatCList* BuildCList (const TVector<HeapTuple>& items) {
136
+ auto cl = (CatCList *)palloc (offsetof (CatCList, members) + items.size () * sizeof (CatCTup *));
137
+ cl->cl_magic = CL_MAGIC;
138
+ cl->my_cache = nullptr ;
139
+ cl->refcount = 0 ;
140
+ cl->dead = false ;
141
+ cl->ordered = false ;
142
+ cl->nkeys = NumKeys;
143
+ cl->hash_value = 0 ;
144
+ cl->n_members = items.size ();
145
+ for (size_t i = 0 ; i < items.size (); ++i) {
146
+ auto dtp = items[i];
147
+ auto ct = (CatCTup *) palloc (sizeof (CatCTup) + MAXIMUM_ALIGNOF + dtp->t_len );
148
+ ct->ct_magic = CT_MAGIC;
149
+ ct->my_cache = nullptr ;
150
+ ct->c_list = NULL ;
151
+ ct->refcount = 0 ;
152
+ ct->dead = false ;
153
+ ct->negative = false ;
154
+ ct->hash_value = 0 ;
155
+ Zero (ct->keys );
156
+
157
+ ct->tuple .t_len = dtp->t_len ;
158
+ ct->tuple .t_self = dtp->t_self ;
159
+ ct->tuple .t_tableOid = dtp->t_tableOid ;
160
+ ct->tuple .t_data = (HeapTupleHeader)MAXALIGN (((char *) ct) + sizeof (CatCTup));
161
+ /* copy tuple contents */
162
+ std::memcpy ((char *) ct->tuple .t_data , (const char *) dtp->t_data , dtp->t_len );
163
+ cl->members [i] = ct;
164
+ }
165
+
166
+ return cl;
167
+ }
168
+
169
+ void FinalizeRangeMaps () {
170
+ if (RangeMap1) {
171
+ for (auto & x : *RangeMap1) {
172
+ x.second .CList = BuildCList (x.second .Items );
173
+ }
174
+ }
175
+
176
+ EmptyCList = BuildCList ({});
177
+ }
178
+
179
+ const ui32 NumKeys;
180
+ TSysCacheHashMap LookupMap;
181
+ TMaybe<TSysCacheRangeMap> RangeMap1;
76
182
TupleDesc Desc;
183
+ CatCList* EmptyCList = nullptr ;
77
184
};
78
185
79
186
struct TSysCache {
@@ -91,6 +198,12 @@ struct TSysCache {
91
198
InitializeDatabase ();
92
199
InitializeAuthId ();
93
200
InitializeNameNamespaces ();
201
+ for (auto & item : Items) {
202
+ if (item) {
203
+ item->FinalizeRangeMaps ();
204
+ }
205
+ }
206
+
94
207
Arena.Release ();
95
208
}
96
209
@@ -142,7 +255,11 @@ struct TSysCache {
142
255
FillAttr (tupleDesc, Anum_pg_proc_proconfig, TEXTARRAYOID);
143
256
FillAttr (tupleDesc, Anum_pg_proc_proacl, ACLITEMARRAYOID);
144
257
auto & cacheItem = Items[PROCOID] = std::make_unique<TSysCacheItem>(OidHasher1, OidEquals1, tupleDesc);
145
- auto & map = cacheItem->Map ;
258
+ auto & lookupMap = cacheItem->LookupMap ;
259
+
260
+ auto & byNameCacheItem = Items[PROCNAMEARGSNSP] = std::make_unique<TSysCacheItem>(ByNameProcHasher3, ByNameProcEquals3, tupleDesc, 3 , ByNameProcHasher1, ByNameProcEquals1);
261
+ auto & byNameLookupMap = byNameCacheItem->LookupMap ;
262
+ auto & byNameRangeMap1 = *byNameCacheItem->RangeMap1 ;
146
263
147
264
const auto & oidDesc = NPg::LookupType (OIDOID);
148
265
const auto & charDesc = NPg::LookupType (CHAROID);
@@ -162,33 +279,18 @@ struct TSysCache {
162
279
FillDatum (Natts_pg_proc, values, nulls, Anum_pg_proc_proname, (Datum)name);
163
280
FillDatum (Natts_pg_proc, values, nulls, Anum_pg_proc_pronargs, (Datum)desc.ArgTypes .size ());
164
281
{
165
- int dims[MAXDIM];
166
- int lbs[MAXDIM];
167
- dims[0 ] = desc.ArgTypes .size ();
168
- lbs[0 ] = 1 ;
169
- std::unique_ptr<Datum[]> dvalues (new Datum[desc.ArgTypes .size ()]);
170
- std::unique_ptr<bool []> dnulls (new bool [desc.ArgTypes .size ()]);
171
- std::copy (desc.ArgTypes .begin (), desc.ArgTypes .end (), dvalues.get ());
172
- std::fill_n (dnulls.get (), desc.ArgTypes .size (), false );
173
-
174
- auto arr = construct_md_array (dvalues.get (), dnulls.get (), 1 , dims, lbs, OIDOID, oidDesc.TypeLen , oidDesc.PassByValue , oidDesc.TypeAlign );
282
+ auto arr = buildoidvector (desc.ArgTypes .data (), (int )desc.ArgTypes .size ());
175
283
FillDatum (Natts_pg_proc, values, nulls, Anum_pg_proc_proargtypes, (Datum)arr);
176
284
}
177
285
178
286
const ui32 fullArgsCount = desc.ArgTypes .size () + desc.OutputArgTypes .size ();
179
287
if (!desc.OutputArgTypes .empty ())
180
288
{
181
- int dims[MAXDIM];
182
- int lbs[MAXDIM];
183
- dims[0 ] = fullArgsCount;
184
- lbs[0 ] = 1 ;
185
- std::unique_ptr<Datum[]> dvalues (new Datum[fullArgsCount]);
186
- std::unique_ptr<bool []> dnulls (new bool [fullArgsCount]);
187
- std::copy (desc.ArgTypes .begin (), desc.ArgTypes .end (), dvalues.get ());
188
- std::copy (desc.OutputArgTypes .begin (), desc.OutputArgTypes .end (), dvalues.get () + desc.ArgTypes .size ());
189
- std::fill_n (dnulls.get (), fullArgsCount, false );
289
+ std::unique_ptr<Oid[]> allOids (new Oid[fullArgsCount]);
290
+ std::copy (desc.ArgTypes .begin (), desc.ArgTypes .end (), allOids.get ());
291
+ std::copy (desc.OutputArgTypes .begin (), desc.OutputArgTypes .end (), allOids.get () + desc.ArgTypes .size ());
190
292
191
- auto arr = construct_md_array (dvalues .get (), dnulls. get (), 1 , dims, lbs, OIDOID, oidDesc. TypeLen , oidDesc. PassByValue , oidDesc. TypeAlign );
293
+ auto arr = buildoidvector (allOids .get (), ( int )fullArgsCount );
192
294
FillDatum (Natts_pg_proc, values, nulls, Anum_pg_proc_proallargtypes, (Datum)arr);
193
295
}
194
296
if (!desc.OutputArgTypes .empty ())
@@ -236,7 +338,13 @@ struct TSysCache {
236
338
Y_ENSURE (row->prorettype == desc.ResultType );
237
339
Y_ENSURE (NameStr (row->proname ) == desc.Name );
238
340
Y_ENSURE (row->pronargs == desc.ArgTypes .size ());
239
- map.emplace (key, h);
341
+ lookupMap.emplace (key, h);
342
+
343
+ THeapTupleKey byNameLookupKey ((Datum)name, (Datum)&row->proargtypes , PG_CATALOG_NAMESPACE, 0 );
344
+ THeapTupleKey byNameRangeKey1 ((Datum)name, 0 , 0 , 0 );
345
+
346
+ byNameLookupMap.emplace (byNameLookupKey, h);
347
+ byNameRangeMap1[byNameRangeKey1].Items .push_back (h);
240
348
});
241
349
}
242
350
@@ -274,8 +382,8 @@ struct TSysCache {
274
382
FillAttr (tupleDesc, Anum_pg_type_typdefaultbin, PG_NODE_TREEOID);
275
383
FillAttr (tupleDesc, Anum_pg_type_typdefault, TEXTOID);
276
384
FillAttr (tupleDesc, Anum_pg_type_typacl, ACLITEMARRAYOID);
277
- auto & cacheItems = Items[TYPEOID] = std::make_unique<TSysCacheItem>(OidHasher1, OidEquals1, tupleDesc);
278
- auto & map = cacheItems-> Map ;
385
+ auto & cacheItem = Items[TYPEOID] = std::make_unique<TSysCacheItem>(OidHasher1, OidEquals1, tupleDesc);
386
+ auto & lookupMap = cacheItem-> LookupMap ;
279
387
280
388
NPg::EnumTypes ([&](ui32 oid, const NPg::TTypeDesc& desc){
281
389
auto key = THeapTupleKey (oid, 0 , 0 , 0 );
@@ -329,7 +437,7 @@ struct TSysCache {
329
437
Y_ENSURE (row->typmodout == desc.TypeModOutFuncId );
330
438
Y_ENSURE (row->typalign == desc.TypeAlign );
331
439
Y_ENSURE (row->typstorage == storage);
332
- map .emplace (key, h);
440
+ lookupMap .emplace (key, h);
333
441
});
334
442
335
443
}
@@ -350,8 +458,8 @@ struct TSysCache {
350
458
FillAttr (tupleDesc, Anum_pg_database_datminmxid, XIDOID);
351
459
FillAttr (tupleDesc, Anum_pg_database_dattablespace, OIDOID);
352
460
FillAttr (tupleDesc, Anum_pg_database_datacl, ACLITEMARRAYOID);
353
- auto & cacheItems = Items[DATABASEOID] = std::make_unique<TSysCacheItem>(OidHasher1, OidEquals1, tupleDesc);
354
- auto & map = cacheItems-> Map ;
461
+ auto & cacheItem = Items[DATABASEOID] = std::make_unique<TSysCacheItem>(OidHasher1, OidEquals1, tupleDesc);
462
+ auto & lookupMap = cacheItem-> LookupMap ;
355
463
356
464
for (ui32 oid = 1 ; oid <= 3 ; ++oid) {
357
465
auto key = THeapTupleKey (oid, 0 , 0 , 0 );
@@ -373,7 +481,7 @@ struct TSysCache {
373
481
auto row = (Form_pg_database) GETSTRUCT (h);
374
482
Y_ENSURE (row->oid == oid);
375
483
Y_ENSURE (strcmp (NameStr (row->datname ), name) == 0 );
376
- map .emplace (key, h);
484
+ lookupMap .emplace (key, h);
377
485
}
378
486
}
379
487
@@ -391,8 +499,8 @@ struct TSysCache {
391
499
FillAttr (tupleDesc, Anum_pg_authid_rolconnlimit, INT4OID);
392
500
FillAttr (tupleDesc, Anum_pg_authid_rolpassword, TEXTOID);
393
501
FillAttr (tupleDesc, Anum_pg_authid_rolvaliduntil, TIMESTAMPTZOID);
394
- auto & cacheItems = Items[AUTHOID] = std::make_unique<TSysCacheItem>(OidHasher1, OidEquals1, tupleDesc);
395
- auto & map = cacheItems-> Map ;
502
+ auto & cacheItem = Items[AUTHOID] = std::make_unique<TSysCacheItem>(OidHasher1, OidEquals1, tupleDesc);
503
+ auto & lookupMap = cacheItem-> LookupMap ;
396
504
397
505
auto key = THeapTupleKey (1 , 0 , 0 , 0 );
398
506
@@ -424,7 +532,7 @@ struct TSysCache {
424
532
Y_ENSURE (row->rolreplication );
425
533
Y_ENSURE (row->rolbypassrls );
426
534
Y_ENSURE (row->rolconnlimit == -1 );
427
- map .emplace (key, h);
535
+ lookupMap .emplace (key, h);
428
536
}
429
537
430
538
void InitializeNameNamespaces () {
@@ -462,8 +570,8 @@ struct TSysCache {
462
570
FillAttr (tupleDesc, Anum_pg_class_relacl, ACLITEMARRAYOID);
463
571
FillAttr (tupleDesc, Anum_pg_class_reloptions, TEXTARRAYOID);
464
572
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 ;
573
+ auto & cacheItem = Items[RELNAMENSP] = std::make_unique<TSysCacheItem>(NsNameHasher, NsNameEquals, tupleDesc);
574
+ auto & lookupMap = cacheItem-> LookupMap ;
467
575
468
576
Datum values[Natts_pg_class];
469
577
bool nulls[Natts_pg_class];
@@ -485,7 +593,7 @@ struct TSysCache {
485
593
Y_ENSURE (row->relnamespace == ns);
486
594
487
595
auto key = THeapTupleKey (name, ns, 0 , 0 );
488
- map .emplace (key, h);
596
+ lookupMap .emplace (key, h);
489
597
}
490
598
}
491
599
};
@@ -501,9 +609,9 @@ HeapTuple SearchSysCache(int cacheId, Datum key1, Datum key2, Datum key3, Datum
501
609
return nullptr ;
502
610
}
503
611
504
- const auto & map = cacheItem->Map ;
505
- auto it = map .find (std::make_tuple (key1, key2, key3, key4));
506
- if (it == map .end ()) {
612
+ const auto & lookupMap = cacheItem->LookupMap ;
613
+ auto it = lookupMap .find (std::make_tuple (key1, key2, key3, key4));
614
+ if (it == lookupMap .end ()) {
507
615
return nullptr ;
508
616
}
509
617
@@ -554,3 +662,21 @@ Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bo
554
662
Y_ENSURE (cacheItem);
555
663
return heap_getattr (tup, attributeNumber, cacheItem->Desc , isNull);
556
664
}
665
+
666
+ struct catclist * SearchSysCacheList (int cacheId, int nkeys, Datum key1, Datum key2, Datum key3) {
667
+ Y_ENSURE (cacheId >= 0 && cacheId < SysCacheSize);
668
+ const auto & cacheItem = NYql::TSysCache::Instance ().Items [cacheId];
669
+ Y_ENSURE (cacheItem);
670
+ if (nkeys == 1 && cacheItem->NumKeys > 1 ) {
671
+ const auto & rangeMap1 = *cacheItem->RangeMap1 ;
672
+ auto it = rangeMap1.find (std::make_tuple (key1, 0 , 0 , 0 ));
673
+ if (it == rangeMap1.end ()) {
674
+ return cacheItem->EmptyCList ;
675
+ }
676
+
677
+ return it->second .CList ;
678
+ }
679
+
680
+ return cacheItem->EmptyCList ;
681
+ }
682
+
0 commit comments