1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357 |
- #include "catalog.h"
- #include <yql/essentials/parser/pg_catalog/proto/pg_catalog.pb.h>
- #include <yql/essentials/utils/log/profile.h>
- #include <util/generic/array_size.h>
- #include <util/generic/utility.h>
- #include <util/generic/hash.h>
- #include <util/generic/hash_set.h>
- #include <util/string/builder.h>
- #include <util/string/cast.h>
- #include <util/string/split.h>
- #include <util/stream/file.h>
- #include <util/system/env.h>
- #include <util/system/mutex.h>
- #include <util/system/tempfile.h>
- #include <library/cpp/resource/resource.h>
- #include <library/cpp/digest/md5/md5.h>
- namespace NYql::NPg {
- const ui32 MaximumExtensionsCount = 64; // see TTypeAnnotationNode::GetUsedPgExtensions
- constexpr ui32 FuncMaxArgs = 100;
- constexpr ui32 InvalidOid = 0;
- constexpr ui32 Int2VectorOid = 22;
- constexpr ui32 RegProcOid = 24;
- constexpr ui32 OidOid = 26;
- constexpr ui32 OidVectorOid = 30;
- constexpr ui32 RegProcedureOid = 2202;
- constexpr ui32 RegOperOid = 2203;
- constexpr ui32 RegOperatorOid = 2204;
- constexpr ui32 RegClassOid = 2205;
- constexpr ui32 RegTypeOid = 2206;
- //constexpr ui32 AnyElementOid = 2283;
- //constexpr ui32 AnyNonArrayOid = 2776;
- constexpr ui32 RegConfigOid = 3734;
- constexpr ui32 RegDictionaryOid = 3769;
- constexpr ui32 RegNamespaceOid = 4089;
- constexpr ui32 RegRoleOid = 4096;
- //constexpr ui32 AnyCompatibleOid = 5077;
- //constexpr ui32 AnyCompatibleArrayOid = 5078;
- //constexpr ui32 AnyCompatibleNonArrayOid = 5079;
- // See GetCCHashEqFuncs in PG sources
- // https://doxygen.postgresql.org/catcache_8c.html#a8a2dc395011dba02c083bfbf6b87ce6c
- const THashSet<ui32> regClasses({
- RegProcOid, RegProcedureOid, RegOperOid, RegOperatorOid, RegClassOid, RegTypeOid,
- RegConfigOid, RegDictionaryOid, RegRoleOid, RegNamespaceOid});
- using TOperators = THashMap<ui32, TOperDesc>;
- using TProcs = THashMap<ui32, TProcDesc>;
- using TTypes = THashMap<ui32, TTypeDesc>;
- using TCasts = THashMap<ui32, TCastDesc>;
- using TAggregations = THashMap<ui32, TAggregateDesc>;
- using TAms = THashMap<ui32, TAmDesc>;
- using TNamespaces = THashMap<decltype(TNamespaceDesc::Oid), TNamespaceDesc>;
- using TOpFamilies = THashMap<TString, TOpFamilyDesc>;
- using TOpClasses = THashMap<std::pair<EOpClassMethod, ui32>, TOpClassDesc>;
- using TAmOps = THashMap<std::tuple<ui32, ui32, ui32, ui32>, TAmOpDesc>;
- using TAmProcs = THashMap<std::tuple<ui32, ui32, ui32, ui32>, TAmProcDesc>;
- using TConversions = THashMap<std::pair<TString, TString>, TConversionDesc>;
- using TLanguages = THashMap<ui32, TLanguageDesc>;
- using TExtensions = TVector<TExtensionDesc>;
- using TExtensionsByName = THashMap<TString, ui32>;
- bool IsCompatibleTo(ui32 actualTypeId, ui32 expectedTypeId, const TTypes& types) {
- if (actualTypeId == expectedTypeId) {
- return true;
- }
- if (actualTypeId == InvalidOid) {
- return true;
- }
- if (actualTypeId == UnknownOid) {
- return true;
- }
- if (expectedTypeId == AnyOid) {
- return true;
- }
- // TODO: add checks for polymorphic types
- if (expectedTypeId == UnknownOid) {
- return true;
- }
- if (expectedTypeId == AnyArrayOid) {
- const auto& actualDescPtr = types.FindPtr(actualTypeId);
- Y_ENSURE(actualDescPtr);
- return actualDescPtr->ArrayTypeId && actualDescPtr->ArrayTypeId == actualDescPtr->TypeId;
- }
- if (expectedTypeId == AnyNonArrayOid) {
- const auto& actualDescPtr = types.FindPtr(actualTypeId);
- Y_ENSURE(actualDescPtr);
- return actualDescPtr->ArrayTypeId && actualDescPtr->ArrayTypeId != actualDescPtr->TypeId;
- }
- return false;
- }
- TString ArgTypesList(const TVector<ui32>& ids) {
- TStringBuilder str;
- str << '(';
- for (ui32 i = 0; i < ids.size(); ++i) {
- if (i > 0) {
- str << ',';
- }
- str << (ids[i] ? LookupType(ids[i]).Name : "NULL");
- }
- str << ')';
- return str;
- }
- TStringBuf GetCanonicalTypeName(TStringBuf name) {
- if (name == "boolean") {
- return "bool";
- }
- if (name == "character") {
- return "bpchar";
- }
- if (name == "charactervarying") {
- return "varchar";
- }
- if (name == "bitvarying") {
- return "varbit";
- }
- if (name == "real") {
- return "float4";
- }
- if (name == "doubleprecision") {
- return "float8";
- }
- if (name == "smallint") {
- return "int2";
- }
- if (name == "integer" || name == "int") {
- return "int4";
- }
- if (name == "bigint") {
- return "int8";
- }
- if (name == "timewithouttimezone") {
- return "time";
- }
- if (name == "timewithtimezone") {
- return "timetz";
- }
- if (name == "timestampwithouttimezone") {
- return "timestamp";
- }
- if (name == "timestampwithtimezone") {
- return "timestamptz";
- }
- if (name == "decimal") {
- return "numeric";
- }
- return name;
- }
- bool ValidateArgs(const TVector<ui32>& descArgTypeIds, const TVector<ui32>& argTypeIds, const TTypes& types, ui32 variadicArgType = 0) {
- if (argTypeIds.size() > FuncMaxArgs) {
- return false;
- }
- if (argTypeIds.size() < descArgTypeIds.size()) {
- return false;
- }
- if (!variadicArgType && argTypeIds.size() > descArgTypeIds.size()) {
- return false;
- }
- if (variadicArgType && argTypeIds.size() == descArgTypeIds.size()) {
- // at least one variadic argument is required
- return false;
- }
- for (size_t i = 0; i < descArgTypeIds.size(); ++i) {
- if (!IsCompatibleTo(argTypeIds[i], descArgTypeIds[i], types)) {
- return false;
- }
- }
- for (size_t i = descArgTypeIds.size(); i < argTypeIds.size(); ++i) {
- if (!IsCompatibleTo(argTypeIds[i], variadicArgType, types)) {
- return false;
- }
- }
- return true;
- }
- class TParser {
- public:
- virtual ~TParser() = default;
- void Do(const TString& dat) {
- enum class EState {
- WaitBracket,
- InsideBrackets,
- WaitForEndOfKey,
- WaitForValue,
- WaitForEndOfValue
- };
- EState state = EState::WaitBracket;
- bool AfterBackSlash = false;
- TStringBuilder key;
- TStringBuilder value;
- for (char c : dat) {
- switch (state) {
- case EState::WaitBracket: {
- if (c == '{') {
- state = EState::InsideBrackets;
- }
- break;
- }
- case EState::InsideBrackets: {
- if (c == '}') {
- state = EState::WaitBracket;
- OnFinish();
- continue;
- }
- if (c == ' ' || c == ',' || c == '\n') {
- continue;
- }
- key.clear();
- key << c;
- state = EState::WaitForEndOfKey;
- break;
- }
- case EState::WaitForEndOfKey: {
- if (c != ' ') {
- key << c;
- continue;
- }
- state = EState::WaitForValue;
- break;
- }
- case EState::WaitForValue: {
- if (c != '\'') {
- continue;
- }
- state = EState::WaitForEndOfValue;
- value.clear();
- break;
- }
- case EState::WaitForEndOfValue: {
- if (c == '\\' && !AfterBackSlash) {
- AfterBackSlash = true;
- continue;
- }
- if (AfterBackSlash) {
- AfterBackSlash = false;
- value << c;
- continue;
- }
- if (c != '\'') {
- value << c;
- continue;
- }
- state = EState::InsideBrackets;
- OnKey(key, value);
- break;
- }
- }
- }
- }
- virtual void OnFinish() = 0;
- virtual void OnKey(const TString& key, const TString& value) = 0;
- };
- bool ValidateOperArgs(const TOperDesc& d, const TVector<ui32>& argTypeIds, const TTypes& types) {
- ui32 size = d.Kind == EOperKind::Binary ? 2 : 1;
- if (argTypeIds.size() != size) {
- return false;
- }
- for (size_t i = 0; i < argTypeIds.size(); ++i) {
- ui32 expectedArgType;
- if (d.Kind == EOperKind::RightUnary || (d.Kind == EOperKind::Binary && i == 0)) {
- expectedArgType = d.LeftType;
- }
- else {
- expectedArgType = d.RightType;
- }
- if (!IsCompatibleTo(argTypeIds[i], expectedArgType, types)) {
- return false;
- }
- }
- return true;
- }
- struct TLazyOperInfo {
- TString Com;
- TString Negate;
- };
- class TOperatorsParser : public TParser {
- public:
- TOperatorsParser(TOperators& operators, const THashMap<TString, ui32>& typeByName, const TTypes& types,
- const THashMap<TString, TVector<ui32>>& procByName, const TProcs& procs, THashMap<ui32, TLazyOperInfo>& lazyInfos)
- : Operators(operators)
- , TypeByName(typeByName)
- , Types(types)
- , ProcByName(procByName)
- , Procs(procs)
- , LazyInfos(lazyInfos)
- {}
- void OnKey(const TString& key, const TString& value) override {
- if (key == "oid") {
- LastOperator.OperId = FromString<ui32>(value);
- } else if (key == "oprname") {
- LastOperator.Name = value;
- } else if (key == "descr") {
- LastOperator.Descr = value;
- } else if (key == "oprkind") {
- if (value == "r") {
- LastOperator.Kind = EOperKind::RightUnary;
- } else if (value == "l") {
- LastOperator.Kind = EOperKind::LeftUnary;
- }
- } else if (key == "oprleft") {
- if (value != "0") {
- auto typeIdPtr = TypeByName.FindPtr(value);
- Y_ENSURE(typeIdPtr);
- LastOperator.LeftType = *typeIdPtr;
- }
- } else if (key == "oprright") {
- if (value != "0") {
- auto typeIdPtr = TypeByName.FindPtr(value);
- Y_ENSURE(typeIdPtr);
- LastOperator.RightType = *typeIdPtr;
- }
- } else if (key == "oprresult") {
- auto typeIdPtr = TypeByName.FindPtr(value);
- Y_ENSURE(typeIdPtr);
- LastOperator.ResultType = *typeIdPtr;
- } else if (key == "oprcode") {
- LastCode = value;
- } else if (key == "oprnegate") {
- LastNegate = value;
- } else if (key == "oprcom") {
- LastCom = value;
- }
- }
- void OnFinish() override {
- if (IsSupported) {
- auto pos = LastCode.find('(');
- auto code = LastCode.substr(0, pos);
- auto procIdPtr = ProcByName.FindPtr(code);
- // skip operator if proc isn't builtin, e.g. path_contain_pt
- if (!procIdPtr) {
- IsSupported = false;
- } else {
- for (auto procId : *procIdPtr) {
- auto procPtr = Procs.FindPtr(procId);
- Y_ENSURE(procPtr);
- if (ValidateOperArgs(LastOperator, procPtr->ArgTypes, Types)) {
- Y_ENSURE(!LastOperator.ProcId);
- LastOperator.ProcId = procId;
- }
- }
- // can be missing for example jsonb - _text
- if (LastOperator.ProcId) {
- Y_ENSURE(!LastOperator.Name.empty());
- Operators[LastOperator.OperId] = LastOperator;
- }
- if (!LastCom.empty()) {
- LazyInfos[LastOperator.OperId].Com = LastCom;
- }
- if (!LastNegate.empty()) {
- LazyInfos[LastOperator.OperId].Negate = LastNegate;
- }
- }
- }
- LastOperator = TOperDesc();
- LastCode = "";
- LastNegate = "";
- LastCom = "";
- IsSupported = true;
- }
- private:
- TOperators& Operators;
- const THashMap<TString, ui32>& TypeByName;
- const TTypes& Types;
- const THashMap<TString, TVector<ui32>>& ProcByName;
- const TProcs& Procs;
- THashMap<ui32, TLazyOperInfo>& LazyInfos;
- TOperDesc LastOperator;
- bool IsSupported = true;
- TString LastCode;
- TString LastNegate;
- TString LastCom;
- };
- class TProcsParser : public TParser {
- public:
- TProcsParser(TProcs& procs, const THashMap<TString, ui32>& typeByName)
- : Procs(procs)
- , TypeByName(typeByName)
- {}
- void OnKey(const TString& key, const TString& value) override {
- if (key == "oid") {
- LastProc.ProcId = FromString<ui32>(value);
- } else if (key == "provariadic") {
- auto idPtr = TypeByName.FindPtr(value);
- Y_ENSURE(idPtr);
- LastProc.VariadicType = *idPtr;
- } else if (key == "descr") {
- LastProc.Descr = value;
- } else if (key == "prokind") {
- if (value == "f") {
- LastProc.Kind = EProcKind::Function;
- } else if (value == "a") {
- LastProc.Kind = EProcKind::Aggregate;
- } else if (value == "w") {
- LastProc.Kind = EProcKind::Window;
- } else {
- IsSupported = false;
- }
- } else if (key == "prorettype") {
- auto idPtr = TypeByName.FindPtr(value);
- Y_ENSURE(idPtr);
- LastProc.ResultType = *idPtr;
- } else if (key == "proname") {
- LastProc.Name = value;
- } else if (key == "prosrc") {
- LastProc.Src = value;
- } else if (key == "prolang") {
- if (value == "sql") {
- LastProc.Lang = LangSQL;
- } else if (value == "c") {
- LastProc.Lang = LangC;
- } else {
- IsSupported = false;
- }
- } else if (key == "proargtypes") {
- TVector<TString> strArgs;
- Split(value, " ", strArgs);
- LastProc.ArgTypes.reserve(strArgs.size());
- for (const auto& s : strArgs) {
- auto idPtr = TypeByName.FindPtr(s);
- Y_ENSURE(idPtr);
- LastProc.ArgTypes.push_back(*idPtr);
- }
- } else if (key == "proisstrict") {
- LastProc.IsStrict = (value == "t");
- } else if (key == "proretset") {
- LastProc.ReturnSet = (value == "t");
- } else if (key == "proallargtypes") {
- AllArgTypesStr = value;
- } else if (key == "proargmodes") {
- ArgModesStr = value;
- } else if (key == "proargnames") {
- ArgNamesStr = value;
- }
- }
- void OnFinish() override {
- if (IsSupported) {
- if (LastProc.VariadicType) {
- Y_ENSURE(!ArgModesStr.empty());
- }
- if (!ArgModesStr.empty()) {
- Y_ENSURE(ArgModesStr.front() == '{');
- Y_ENSURE(ArgModesStr.back() == '}');
- TVector<TString> modes;
- Split(ArgModesStr.substr(1, ArgModesStr.size() - 2), ",", modes);
- Y_ENSURE(modes.size() >= LastProc.ArgTypes.size());
- ui32 inputArgsCount = 0;
- bool startedVarArgs = false;
- bool startedOutArgs = false;
- for (size_t i = 0; i < modes.size(); ++i) {
- if (modes[i] == "i") {
- Y_ENSURE(!startedVarArgs && !startedOutArgs);
- inputArgsCount = i + 1;
- } else if (modes[i] == "o") {
- startedOutArgs = true;
- } else {
- Y_ENSURE(!startedVarArgs && !startedOutArgs);
- Y_ENSURE(modes[i] == "v");
- Y_ENSURE(LastProc.VariadicType);
- startedVarArgs = true;
- }
- }
- if (LastProc.VariadicType) {
- Y_ENSURE(LastProc.ArgTypes.size() > inputArgsCount);
- LastProc.VariadicArgType = LastProc.ArgTypes[inputArgsCount];
- Y_ENSURE(LastProc.VariadicArgType);
- }
- LastProc.ArgTypes.resize(inputArgsCount);
- }
- }
- if (IsSupported) {
- auto variadicDelta = LastProc.VariadicType ? 1 : 0;
- if (!ArgNamesStr.empty()) {
- Y_ENSURE(ArgNamesStr.front() == '{');
- Y_ENSURE(ArgNamesStr.back() == '}');
- TVector<TString> names;
- Split(ArgNamesStr.substr(1, ArgNamesStr.size() - 2), ",", names);
- Y_ENSURE(names.size() >= LastProc.ArgTypes.size() + variadicDelta);
- LastProc.OutputArgNames.insert(LastProc.OutputArgNames.begin(), names.begin() + LastProc.ArgTypes.size() + variadicDelta, names.end());
- if (LastProc.VariadicType) {
- LastProc.VariadicArgName = names[LastProc.ArgTypes.size()];
- }
- LastProc.InputArgNames.insert(LastProc.InputArgNames.begin(), names.begin(), names.begin() + LastProc.ArgTypes.size());
- }
- if (!AllArgTypesStr.empty()) {
- Y_ENSURE(!ArgModesStr.empty());
- Y_ENSURE(AllArgTypesStr.front() == '{');
- Y_ENSURE(AllArgTypesStr.back() == '}');
- TVector<TString> types;
- Split(AllArgTypesStr.substr(1, AllArgTypesStr.size() - 2), ",", types);
- Y_ENSURE(types.size() >= LastProc.ArgTypes.size() + variadicDelta);
- for (size_t i = LastProc.ArgTypes.size() + variadicDelta; i < types.size(); ++i) {
- auto idPtr = TypeByName.FindPtr(types[i]);
- Y_ENSURE(idPtr);
- LastProc.OutputArgTypes.push_back(*idPtr);
- }
- }
- }
- if (IsSupported) {
- Y_ENSURE(!LastProc.Name.empty());
- Procs[LastProc.ProcId] = LastProc;
- }
- IsSupported = true;
- LastProc = TProcDesc();
- AllArgTypesStr = "";
- ArgModesStr = "";
- ArgNamesStr = "";
- }
- private:
- TProcs& Procs;
- const THashMap<TString, ui32>& TypeByName;
- TProcDesc LastProc;
- bool IsSupported = true;
- TString AllArgTypesStr;
- TString ArgModesStr;
- TString ArgNamesStr;
- };
- struct TLazyTypeInfo {
- TString ElementType;
- TString InFunc;
- TString OutFunc;
- TString SendFunc;
- TString ReceiveFunc;
- TString ModInFunc;
- TString ModOutFunc;
- TString SubscriptFunc;
- };
- class TTypesParser : public TParser {
- public:
- TTypesParser(TTypes& types, THashMap<ui32, TLazyTypeInfo>& lazyInfos)
- : Types(types)
- , LazyInfos(lazyInfos)
- {}
- void OnKey(const TString& key, const TString& value) override {
- if (key == "oid") {
- LastType.TypeId = FromString<ui32>(value);
- } else if (key == "array_type_oid") {
- LastType.ArrayTypeId = FromString<ui32>(value);
- } else if (key == "descr") {
- LastType.Descr = value;
- } else if (key == "typname") {
- LastType.Name = value;
- } else if (key == "typcategory") {
- Y_ENSURE(value.size() == 1);
- LastType.Category = value[0];
- } else if (key == "typlen") {
- if (value == "NAMEDATALEN") {
- LastType.TypeLen = 64;
- } else if (value == "SIZEOF_POINTER") {
- LastType.TypeLen = 8;
- } else {
- LastType.TypeLen = FromString<i32>(value);
- }
- } else if (key == "typalign") {
- if (value == "ALIGNOF_POINTER") {
- LastType.TypeAlign = 'i'; // doesn't matter for pointers
- } else {
- Y_ENSURE(value.size() == 1);
- LastType.TypeAlign = value[0];
- }
- } else if (key == "typdelim") {
- Y_ENSURE(value.size() == 1);
- LastType.TypeDelim = value[0];
- } else if (key == "typtype") {
- Y_ENSURE(value.size() == 1);
- const auto typType = value[0];
- LastType.TypType =
- (typType == 'b') ? ETypType::Base :
- (typType == 'c') ? ETypType::Composite :
- (typType == 'd') ? ETypType::Domain :
- (typType == 'e') ? ETypType::Enum :
- (typType == 'm') ? ETypType::Multirange :
- (typType == 'p') ? ETypType::Pseudo :
- (typType == 'r') ? ETypType::Range :
- ythrow yexception() << "Unknown typtype value: " << value;
- } else if (key == "typcollation") {
- // hardcode collations for now. There are only three of 'em in .dat file
- LastType.TypeCollation =
- (value == "default") ? DefaultCollationOid :
- (value == "C") ? C_CollationOid :
- (value == "POSIX") ? PosixCollationOid :
- ythrow yexception() << "Unknown typcollation value: " << value;
- } else if (key == "typelem") {
- LastLazyTypeInfo.ElementType = value; // resolve later
- } else if (key == "typinput") {
- LastLazyTypeInfo.InFunc = value; // resolve later
- } else if (key == "typoutput") {
- LastLazyTypeInfo.OutFunc = value; // resolve later
- } else if (key == "typsend") {
- LastLazyTypeInfo.SendFunc = value; // resolve later
- } else if (key == "typreceive") {
- LastLazyTypeInfo.ReceiveFunc = value; // resolve later
- } else if (key == "typmodin") {
- LastLazyTypeInfo.ModInFunc = value; // resolve later
- } else if (key == "typmodout") {
- LastLazyTypeInfo.ModOutFunc = value; // resolve later
- } else if (key == "typsubscript") {
- LastLazyTypeInfo.SubscriptFunc = value; // resolve later
- } else if (key == "typbyval") {
- if (value == "f") {
- LastType.PassByValue = false;
- } else if (value == "t" || value == "FLOAT8PASSBYVAL") {
- LastType.PassByValue = true;
- } else {
- ythrow yexception() << "Unknown typbyval value: " << value;
- }
- } else if (key == "typispreferred") {
- LastType.IsPreferred = (value == "t");
- }
- }
- void OnFinish() override {
- Y_ENSURE(!LastType.Name.empty());
- Y_ENSURE(LastType.TypeLen != 0);
- if (LastType.TypeLen < 0 || LastType.TypeLen > 8) {
- Y_ENSURE(!LastType.PassByValue);
- }
- Types[LastType.TypeId] = LastType;
- if (LastType.ArrayTypeId) {
- auto arrayType = LastType;
- arrayType.Name = "_" + arrayType.Name;
- arrayType.ElementTypeId = arrayType.TypeId;
- arrayType.TypeId = LastType.ArrayTypeId;
- arrayType.PassByValue = false;
- arrayType.TypeLen = -1;
- Types[LastType.ArrayTypeId] = arrayType;
- }
- LazyInfos[LastType.TypeId] = LastLazyTypeInfo;
- if (LastType.ArrayTypeId) {
- LastLazyTypeInfo.OutFunc = "array_out";
- LastLazyTypeInfo.InFunc = "array_in";
- LastLazyTypeInfo.SendFunc = "array_send";
- LastLazyTypeInfo.ReceiveFunc = "array_recv";
- LastLazyTypeInfo.ElementType = "";
- LazyInfos[LastType.ArrayTypeId] = LastLazyTypeInfo;
- }
- LastType = TTypeDesc();
- LastLazyTypeInfo = TLazyTypeInfo();
- }
- private:
- TTypes& Types;
- THashMap<ui32, TLazyTypeInfo>& LazyInfos;
- TTypeDesc LastType;
- TLazyTypeInfo LastLazyTypeInfo;
- };
- class TCastsParser : public TParser {
- public:
- TCastsParser(TCasts& casts, const THashMap<TString, ui32>& typeByName, const TTypes& types,
- const THashMap<TString, TVector<ui32>>& procByName, const TProcs& procs)
- : Casts(casts)
- , TypeByName(typeByName)
- , Types(types)
- , 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('(')) {
- auto pos1 = value.find('(');
- auto pos2 = value.find(')');
- auto pos3 = value.find(',');
- Y_ENSURE(pos1 != TString::npos);
- Y_ENSURE(pos2 != TString::npos);
- if (pos3 != TString::npos) {
- pos2 = pos3;
- }
- 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 (IsCompatibleTo(*inputTypeIdPtr, procPtr->ArgTypes[0], Types)) {
- 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;
- }
- } else if (key == "castcontext") {
- Y_ENSURE(value.size() == 1);
- const auto castCtx = value[0];
- LastCast.CoercionCode =
- (castCtx == 'i') ? ECoercionCode::Implicit :
- (castCtx == 'a') ? ECoercionCode::Assignment :
- (castCtx == 'e') ? ECoercionCode::Explicit :
- ythrow yexception() << "Unknown castcontext value: " << value;
- }
- }
- void OnFinish() override {
- if (IsSupported) {
- auto id = 1 + Casts.size();
- Casts[id] = LastCast;
- }
- LastCast = TCastDesc();
- IsSupported = true;
- }
- private:
- TCasts& Casts;
- const THashMap<TString, ui32>& TypeByName;
- const TTypes& Types;
- const THashMap<TString, TVector<ui32>>& ProcByName;
- const TProcs& Procs;
- TCastDesc LastCast;
- bool IsSupported = true;
- };
- class TAggregationsParser : public TParser {
- public:
- TAggregationsParser(TAggregations& aggregations, const THashMap<TString, ui32>& typeByName,
- const TTypes& types, const THashMap<TString, TVector<ui32>>& procByName, const TProcs& procs)
- : Aggregations(aggregations)
- , TypeByName(typeByName)
- , Types(types)
- , ProcByName(procByName)
- , Procs(procs)
- {}
- void OnKey(const TString& key, const TString& value) override {
- Y_UNUSED(ProcByName);
- if (key == "aggtranstype") {
- auto typeId = TypeByName.FindPtr(value);
- Y_ENSURE(typeId);
- LastAggregation.TransTypeId = *typeId;
- } else if (key == "aggfnoid") {
- LastOid = value;
- } else if (key == "aggtransfn") {
- LastTransFunc = value;
- } else if (key == "aggfinalfn") {
- LastFinalFunc = value;
- } else if (key == "aggcombinefn") {
- LastCombineFunc = value;
- } else if (key == "aggserialfn") {
- LastSerializeFunc = value;
- } else if (key == "aggdeserialfn") {
- LastDeserializeFunc = value;
- } else if (key == "aggkind") {
- if (value == "n") {
- LastAggregation.Kind = EAggKind::Normal;
- } else if (value == "o") {
- LastAggregation.Kind = EAggKind::OrderedSet;
- } else if (value == "h") {
- LastAggregation.Kind = EAggKind::Hypothetical;
- } else {
- ythrow yexception() << "Unknown aggkind value: " << value;
- }
- } else if (key == "agginitval") {
- LastAggregation.InitValue = value;
- } else if (key == "aggfinalextra") {
- LastAggregation.FinalExtra = (value == "t");;
- } else if (key == "aggnumdirectargs") {
- LastAggregation.NumDirectArgs = FromString<ui32>(value);
- }
- }
- void OnFinish() override {
- if (IsSupported) {
- if (FillSupported()) {
- Aggregations[LastAggregation.AggId] = LastAggregation;
- }
- }
- LastAggregation = TAggregateDesc();
- IsSupported = true;
- LastOid = "";
- LastTransFunc = "";
- LastFinalFunc = "";
- LastCombineFunc = "";
- LastSerializeFunc = "";
- LastDeserializeFunc = "";
- }
- bool FillSupported() {
- Y_ENSURE(LastAggregation.TransTypeId);
- Y_ENSURE(LastOid);
- Y_ENSURE(LastTransFunc);
- auto transFuncIdsPtr = ProcByName.FindPtr(LastTransFunc);
- if (!transFuncIdsPtr) {
- // e.g. variadic ordered_set_transition_multi
- return false;
- }
- for (const auto id : *transFuncIdsPtr) {
- auto procPtr = Procs.FindPtr(id);
- Y_ENSURE(procPtr);
- if (procPtr->ArgTypes.size() >= 1 &&
- IsCompatibleTo(LastAggregation.TransTypeId, procPtr->ArgTypes[0], Types)) {
- Y_ENSURE(!LastAggregation.TransFuncId);
- LastAggregation.TransFuncId = id;
- }
- }
- Y_ENSURE(LastAggregation.TransFuncId);
- // oid format: name(arg1,arg2...)
- auto pos1 = LastOid.find('(');
- if (pos1 != TString::npos) {
- LastAggregation.Name = LastOid.substr(0, pos1);
- auto pos = pos1 + 1;
- for (;;) {
- auto nextPos = Min(LastOid.find(',', pos), LastOid.find(')', pos));
- Y_ENSURE(nextPos != TString::npos);
- if (pos == nextPos) {
- break;
- }
- auto arg = LastOid.substr(pos, nextPos - pos);
- auto argTypeId = TypeByName.FindPtr(arg);
- Y_ENSURE(argTypeId);
- LastAggregation.ArgTypes.push_back(*argTypeId);
- pos = nextPos;
- if (LastOid[pos] == ')') {
- break;
- } else {
- ++pos;
- }
- }
- } else {
- // no signature in oid, use transfunc
- LastAggregation.Name = LastOid;
- auto procPtr = Procs.FindPtr(LastAggregation.TransFuncId);
- Y_ENSURE(procPtr);
- LastAggregation.ArgTypes = procPtr->ArgTypes;
- Y_ENSURE(LastAggregation.ArgTypes.size() >= 1);
- Y_ENSURE(IsCompatibleTo(LastAggregation.TransTypeId, LastAggregation.ArgTypes[0], Types));
- LastAggregation.ArgTypes.erase(LastAggregation.ArgTypes.begin());
- }
- Y_ENSURE(!LastAggregation.Name.empty());
- auto funcIdsPtr = ProcByName.FindPtr(LastAggregation.Name);
- Y_ENSURE(funcIdsPtr);
- if (funcIdsPtr->size() == 1) {
- LastAggregation.AggId = funcIdsPtr->front();
- } else {
- for (const auto id : *funcIdsPtr) {
- auto procPtr = Procs.FindPtr(id);
- Y_ENSURE(procPtr);
- if (ValidateArgs(procPtr->ArgTypes, LastAggregation.ArgTypes, Types, procPtr->VariadicType)) {
- LastAggregation.AggId = id;
- break;
- }
- }
- }
- Y_ENSURE(LastAggregation.AggId);
- if (!ResolveFunc(LastFinalFunc, LastAggregation.FinalFuncId, 1)) {
- return false;
- }
- if (!ResolveFunc(LastCombineFunc, LastAggregation.CombineFuncId, 2)) {
- return false;
- }
- if (!ResolveFunc(LastSerializeFunc, LastAggregation.SerializeFuncId, 1)) {
- return false;
- }
- if (!ResolveFunc(LastDeserializeFunc, LastAggregation.DeserializeFuncId, 0)) {
- return false;
- }
- return true;
- }
- bool ResolveFunc(const TString& name, ui32& funcId, ui32 stateArgsCount) {
- if (name) {
- auto funcIdsPtr = ProcByName.FindPtr(name);
- if (!funcIdsPtr) {
- return false;
- }
- if (!stateArgsCount) {
- Y_ENSURE(funcIdsPtr->size() == 1);
- }
- for (const auto id : *funcIdsPtr) {
- auto procPtr = Procs.FindPtr(id);
- Y_ENSURE(procPtr);
- bool found = true;
- if (stateArgsCount > 0 && procPtr->ArgTypes.size() == stateArgsCount) {
- for (ui32 i = 0; i < stateArgsCount; ++i) {
- if (!IsCompatibleTo(LastAggregation.TransTypeId, procPtr->ArgTypes[i], Types)) {
- found = false;
- break;
- }
- }
- }
- if (found) {
- Y_ENSURE(!funcId);
- funcId = id;
- }
- }
- Y_ENSURE(funcId);
- }
- return true;
- }
- private:
- TAggregations& Aggregations;
- const THashMap<TString, ui32>& TypeByName;
- const TTypes& Types;
- const THashMap<TString, TVector<ui32>>& ProcByName;
- const TProcs& Procs;
- TAggregateDesc LastAggregation;
- bool IsSupported = true;
- TString LastOid;
- TString LastTransFunc;
- TString LastFinalFunc;
- TString LastCombineFunc;
- TString LastSerializeFunc;
- TString LastDeserializeFunc;
- };
- class TOpFamiliesParser : public TParser {
- public:
- TOpFamiliesParser(TOpFamilies& opFamilies)
- : OpFamilies(opFamilies)
- {}
- void OnKey(const TString& key, const TString& value) override {
- if (key == "oid") {
- LastOpfId = FromString<ui32>(value);
- } else if (key == "opfmethod") {
- if (value == "btree" || value == "hash") {
- LastOpfMethod = value;
- } else {
- IsSupported = false;
- }
- } else if (key == "opfname") {
- LastOpfName = value;
- }
- }
- void OnFinish() override {
- if (IsSupported) {
- Y_ENSURE(LastOpfId != InvalidOid);
- // opfamily references have opf_method/opf_name format in PG catalogs
- TOpFamilyDesc desc;
- desc.Name = LastOpfMethod + "/" + LastOpfName;
- desc.FamilyId = LastOpfId;
- Y_ENSURE(OpFamilies.emplace(desc.Name, desc).second);
- }
- IsSupported = true;
- LastOpfId = InvalidOid;
- LastOpfMethod.clear();
- LastOpfName.clear();
- }
- private:
- TOpFamilies& OpFamilies;
- ui32 LastOpfId = InvalidOid;
- TString LastOpfMethod;
- TString LastOpfName;
- bool IsSupported = true;
- };
- class TOpClassesParser : public TParser {
- public:
- TOpClassesParser(TOpClasses& opClasses, const THashMap<TString, ui32>& typeByName,
- const TOpFamilies &opFamilies)
- : OpClasses(opClasses)
- , TypeByName(typeByName)
- , OpFamilies(opFamilies)
- {}
- void OnKey(const TString& key, const TString& value) override {
- if (key == "opcmethod") {
- if (value == "btree") {
- LastOpClass.Method = EOpClassMethod::Btree;
- } else if (value == "hash") {
- LastOpClass.Method = EOpClassMethod::Hash;
- } else {
- IsSupported = false;
- }
- } else if (key == "opcintype") {
- auto idPtr = TypeByName.FindPtr(value);
- Y_ENSURE(idPtr);
- LastOpClass.TypeId = *idPtr;
- } else if (key == "opcname") {
- LastOpClass.Name = value;
- } else if (key == "opcfamily") {
- LastOpClass.Family = value;
- auto opFamilyPtr = OpFamilies.FindPtr(value);
- if (opFamilyPtr) {
- LastOpClass.FamilyId = opFamilyPtr->FamilyId;
- } else {
- IsSupported = false;
- }
- } else if (key == "opcdefault") {
- IsDefault = (value[0] != 'f');
- }
- }
- void OnFinish() override {
- // Only default opclasses are used so far
- if (IsSupported && IsDefault) {
- Y_ENSURE(!LastOpClass.Name.empty());
- const auto key = std::make_pair(LastOpClass.Method, LastOpClass.TypeId);
- if (OpClasses.contains(key)) {
- throw yexception() << "Duplicate opclass: (" << (key.first == EOpClassMethod::Btree ? "btree" : "hash")
- << ", " << key.second << ")";
- }
- OpClasses[key] = LastOpClass;
- }
- IsSupported = true;
- IsDefault = true;
- LastOpClass = TOpClassDesc();
- }
- private:
- TOpClasses& OpClasses;
- const THashMap<TString, ui32>& TypeByName;
- const TOpFamilies OpFamilies;
- TOpClassDesc LastOpClass;
- bool IsSupported = true;
- bool IsDefault = true;
- };
- class TAmOpsParser : public TParser {
- public:
- TAmOpsParser(TAmOps& amOps, const THashMap<TString, ui32>& typeByName, const TTypes& types,
- const THashMap<TString, TVector<ui32>>& operatorsByName, const TOperators& operators,
- const TOpFamilies &opFamilies)
- : AmOps(amOps)
- , TypeByName(typeByName)
- , Types(types)
- , OperatorsByName(operatorsByName)
- , Operators(operators)
- , OpFamilies(opFamilies)
- {}
- void OnKey(const TString& key, const TString& value) override {
- if (key == "amopfamily") {
- LastAmOp.Family = value;
- auto opFamilyPtr = OpFamilies.FindPtr(value);
- if (opFamilyPtr) {
- LastAmOp.FamilyId = opFamilyPtr->FamilyId;
- } else {
- IsSupported = false;
- }
- } else if (key == "amoplefttype") {
- auto leftTypePtr = TypeByName.FindPtr(value);
- Y_ENSURE(leftTypePtr);
- LastAmOp.LeftType = *leftTypePtr;
- } else if (key == "amoprighttype") {
- auto rightTypePtr = TypeByName.FindPtr(value);
- Y_ENSURE(rightTypePtr);
- LastAmOp.RightType = *rightTypePtr;
- } else if (key == "amopstrategy") {
- LastAmOp.Strategy = FromString<ui32>(value);
- } else if (key == "amopopr") {
- auto pos = value.find('(');
- Y_ENSURE(pos != TString::npos);
- LastOp = value.substr(0, pos);
- }
- }
- void OnFinish() override {
- if (IsSupported) {
- auto operIdPtr = OperatorsByName.FindPtr(LastOp);
- Y_ENSURE(operIdPtr);
- for (const auto& id : *operIdPtr) {
- const auto& d = Operators.FindPtr(id);
- Y_ENSURE(d);
- if (d->Kind == EOperKind::Binary &&
- IsCompatibleTo(LastAmOp.LeftType, d->LeftType, Types) &&
- IsCompatibleTo(LastAmOp.RightType, d->RightType, Types)) {
- Y_ENSURE(!LastAmOp.OperId);
- LastAmOp.OperId = d->OperId;
- }
- }
- Y_ENSURE(LastAmOp.OperId);
- AmOps[std::make_tuple(LastAmOp.FamilyId, LastAmOp.Strategy, LastAmOp.LeftType, LastAmOp.RightType)] = LastAmOp;
- }
- LastAmOp = TAmOpDesc();
- LastOp = "";
- IsSupported = true;
- }
- private:
- TAmOps& AmOps;
- const THashMap<TString, ui32>& TypeByName;
- const TTypes& Types;
- const THashMap<TString, TVector<ui32>>& OperatorsByName;
- const TOperators& Operators;
- const TOpFamilies& OpFamilies;
- TAmOpDesc LastAmOp;
- TString LastOp;
- bool IsSupported = true;
- };
- class TAmsParser : public TParser {
- public:
- TAmsParser(TAms& ams) : Ams_(ams) {}
- void OnKey(const TString& key, const TString& value) override {
- if (key == "oid") {
- CurrDesc_.Oid = FromString<ui32>(value);
- } else if (key == "descr") {
- CurrDesc_.Descr = value;
- } else if (key == "amname") {
- CurrDesc_.AmName = value;
- } else if (key == "amtype") {
- Y_ENSURE(value.size() == 1);
- if ((char)EAmType::Index == value[0]) {
- CurrDesc_.AmType = EAmType::Index;
- } else if ((char)EAmType::Table == value[0]) {
- CurrDesc_.AmType = EAmType::Table;
- } else {
- Y_ENSURE(false, "Expected correct AmType");
- }
- }
- }
- void OnFinish() override {
- Ams_[CurrDesc_.Oid] = std::move(CurrDesc_);
- CurrDesc_ = TAmDesc();
- }
- private:
- TAmDesc CurrDesc_;
- TAms& Ams_;
- };
- class TAmProcsParser : public TParser {
- public:
- TAmProcsParser(TAmProcs& amProcs, const THashMap<TString, ui32>& typeByName,
- const THashMap<TString, TVector<ui32>>& procByName, const TProcs& procs,
- const TOpFamilies& opFamilies)
- : AmProcs(amProcs)
- , TypeByName(typeByName)
- , ProcByName(procByName)
- , Procs(procs)
- , OpFamilies(opFamilies)
- {}
- void OnKey(const TString& key, const TString& value) override {
- if (key == "amprocfamily") {
- LastAmProc.Family = value;
- auto opFamilyPtr = OpFamilies.FindPtr(value);
- if (opFamilyPtr) {
- LastAmProc.FamilyId = opFamilyPtr->FamilyId;
- } else {
- IsSupported = false;
- }
- } else if (key == "amproclefttype") {
- auto leftTypePtr = TypeByName.FindPtr(value);
- Y_ENSURE(leftTypePtr);
- LastAmProc.LeftType = *leftTypePtr;
- } else if (key == "amprocrighttype") {
- auto rightTypePtr = TypeByName.FindPtr(value);
- Y_ENSURE(rightTypePtr);
- LastAmProc.RightType = *rightTypePtr;
- } else if (key == "amprocnum") {
- LastAmProc.ProcNum = FromString<ui32>(value);
- } else if (key == "amproc") {
- LastName = value;
- }
- }
- void OnFinish() override {
- if (IsSupported) {
- if (LastName.find('(') == TString::npos) {
- auto procIdPtr = ProcByName.FindPtr(LastName);
- Y_ENSURE(procIdPtr);
- for (const auto& id : *procIdPtr) {
- const auto& d = Procs.FindPtr(id);
- Y_ENSURE(d);
- Y_ENSURE(!LastAmProc.ProcId);
- LastAmProc.ProcId = d->ProcId;
- }
- Y_ENSURE(LastAmProc.ProcId);
- AmProcs[std::make_tuple(LastAmProc.FamilyId, LastAmProc.ProcNum, LastAmProc.LeftType, LastAmProc.RightType)] = LastAmProc;
- }
- }
- LastAmProc = TAmProcDesc();
- LastName = "";
- IsSupported = true;
- }
- private:
- TAmProcs& AmProcs;
- const THashMap<TString, ui32>& TypeByName;
- const THashMap<TString, TVector<ui32>>& ProcByName;
- const TProcs& Procs;
- const TOpFamilies& OpFamilies;
- TAmProcDesc LastAmProc;
- TString LastName;
- bool IsSupported = true;
- };
- class TConversionsParser : public TParser {
- public:
- TConversionsParser(TConversions& conversions, const THashMap<TString, TVector<ui32>>& procByName)
- : Conversions(conversions)
- , ProcByName(procByName)
- {}
- void OnKey(const TString& key, const TString& value) override {
- if (key == "oid") {
- LastConversion.ConversionId = FromString<ui32>(value);
- } else if (key == "conforencoding") {
- Y_ENSURE(value.StartsWith("PG_"));
- LastConversion.From = value.substr(3);
- } else if (key == "descr") {
- LastConversion.Descr = value;
- } else if (key == "contoencoding") {
- Y_ENSURE(value.StartsWith("PG_"));
- LastConversion.To = value.substr(3);
- } else if (key == "conproc") {
- auto found = ProcByName.FindPtr(value);
- if (found && found->size() == 1) {
- LastConversion.ProcId = found->front();
- }
- }
- }
- void OnFinish() override {
- if (LastConversion.ProcId) {
- Conversions[std::make_pair(LastConversion.From, LastConversion.To)] = LastConversion;
- }
- LastConversion = TConversionDesc();
- }
- private:
- TConversions& Conversions;
- const THashMap<TString, TVector<ui32>>& ProcByName;
- TConversionDesc LastConversion;
- };
- class TLanguagesParser : public TParser {
- public:
- TLanguagesParser(TLanguages& languages)
- : Languages(languages)
- {}
- void OnKey(const TString& key, const TString& value) override {
- if (key == "oid") {
- LastLanguage.LangId = FromString<ui32>(value);
- } else if (key == "lanname") {
- LastLanguage.Name = value;
- } else if (key == "descr") {
- LastLanguage.Descr = value;
- }
- }
- void OnFinish() override {
- Languages[LastLanguage.LangId] = LastLanguage;
- LastLanguage = TLanguageDesc();
- }
- private:
- TLanguages& Languages;
- TLanguageDesc LastLanguage;
- };
- TOperators ParseOperators(const TString& dat, const THashMap<TString, ui32>& typeByName,
- const TTypes& types, const THashMap<TString, TVector<ui32>>& procByName, const TProcs& procs, THashMap<ui32, TLazyOperInfo>& lazyInfos) {
- TOperators ret;
- TOperatorsParser parser(ret, typeByName, types, procByName, procs, lazyInfos);
- parser.Do(dat);
- return ret;
- }
- ui32 FindOperator(const THashMap<TString, TVector<ui32>>& operatorsByName, const THashMap<TString, ui32>& typeByName, TOperators& operators, const TString& signature) {
- auto pos1 = signature.find('(');
- auto pos2 = signature.find(')');
- Y_ENSURE(pos1 != TString::npos && pos1 > 0);
- Y_ENSURE(pos2 != TString::npos && pos2 > pos1);
- auto name = signature.substr(0, pos1);
- auto operIdsPtr = operatorsByName.FindPtr(name);
- Y_ENSURE(operIdsPtr);
- TVector<TString> strArgs;
- Split(signature.substr(pos1 + 1, pos2 - pos1 - 1), ",", strArgs);
- Y_ENSURE(strArgs.size() >= 1 && strArgs.size() <= 2);
- TVector<ui32> argTypes;
- for (const auto& str : strArgs) {
- auto typePtr = typeByName.FindPtr(str);
- Y_ENSURE(typePtr);
- argTypes.push_back(*typePtr);
- }
- for (const auto& operId : *operIdsPtr) {
- auto operPtr = operators.FindPtr(operId);
- Y_ENSURE(operPtr);
- if (argTypes.size() == 1) {
- if (operPtr->RightType != argTypes[0]) {
- continue;
- }
- } else {
- if (operPtr->LeftType != argTypes[0]) {
- continue;
- }
- if (operPtr->RightType != argTypes[1]) {
- continue;
- }
- }
- return operId;
- }
- // for example, some operators are based on SQL system_functions.sql
- return 0;
- }
- void ApplyLazyOperInfos(TOperators& operators, const THashMap<TString, TVector<ui32>>& operatorsByName, const THashMap<TString, ui32>& typeByName, const THashMap<ui32, TLazyOperInfo>& lazyInfos) {
- for (const auto& x : lazyInfos) {
- if (!x.second.Com.empty()) {
- operators[x.first].ComId = FindOperator(operatorsByName, typeByName, operators, x.second.Com);
- }
- if (!x.second.Negate.empty()) {
- operators[x.first].NegateId = FindOperator(operatorsByName, typeByName, operators, x.second.Negate);
- }
- }
- }
- TAggregations ParseAggregations(const TString& dat, const THashMap<TString, ui32>& typeByName,
- const TTypes& types, const THashMap<TString, TVector<ui32>>& procByName, const TProcs& procs) {
- TAggregations ret;
- TAggregationsParser parser(ret, typeByName, types, procByName, procs);
- parser.Do(dat);
- return ret;
- }
- TProcs ParseProcs(const TString& dat, const THashMap<TString, ui32>& typeByName) {
- TProcs ret;
- TProcsParser parser(ret, typeByName);
- parser.Do(dat);
- return ret;
- }
- TTypes ParseTypes(const TString& dat, THashMap<ui32, TLazyTypeInfo>& lazyInfos) {
- TTypes ret;
- TTypesParser parser(ret, lazyInfos);
- parser.Do(dat);
- return ret;
- }
- TCasts ParseCasts(const TString& dat, const THashMap<TString, ui32>& typeByName, const TTypes& types,
- const THashMap<TString, TVector<ui32>>& procByName, const TProcs& procs) {
- TCasts ret;
- TCastsParser parser(ret, typeByName, types, procByName, procs);
- parser.Do(dat);
- return ret;
- }
- TOpFamilies ParseOpFamilies(const TString& dat) {
- TOpFamilies ret;
- TOpFamiliesParser parser(ret);
- parser.Do(dat);
- return ret;
- }
- TOpClasses ParseOpClasses(const TString& dat, const THashMap<TString, ui32>& typeByName,
- const TOpFamilies& opFamilies) {
- TOpClasses ret;
- TOpClassesParser parser(ret, typeByName, opFamilies);
- parser.Do(dat);
- return ret;
- }
- TAmOps ParseAmOps(const TString& dat, const THashMap<TString, ui32>& typeByName, const TTypes& types,
- const THashMap<TString, TVector<ui32>>& operatorsByName, const TOperators& operators,
- const TOpFamilies& opFamilies) {
- TAmOps ret;
- TAmOpsParser parser(ret, typeByName, types, operatorsByName, operators, opFamilies);
- parser.Do(dat);
- return ret;
- }
- TAmProcs ParseAmProcs(const TString& dat, const THashMap<TString, ui32>& typeByName,
- const THashMap<TString, TVector<ui32>>& procByName, const TProcs& procs,
- const TOpFamilies& opFamilies) {
- TAmProcs ret;
- TAmProcsParser parser(ret, typeByName, procByName, procs, opFamilies);
- parser.Do(dat);
- return ret;
- }
- TConversions ParseConversions(const TString& dat, const THashMap<TString, TVector<ui32>>& procByName) {
- TConversions ret;
- TConversionsParser parser(ret, procByName);
- parser.Do(dat);
- return ret;
- }
- TAms ParseAms(const TString& dat) {
- TAms ret;
- TAmsParser parser(ret);
- parser.Do(dat);
- return ret;
- }
- TLanguages ParseLanguages(const TString& dat) {
- TLanguages ret;
- TLanguagesParser parser(ret);
- parser.Do(dat);
- return ret;
- }
- TNamespaces FillNamespaces() {
- const ui32 PgInformationSchemaNamepace = 1;
- const ui32 PgCatalogNamepace = 11;
- const ui32 PgPublicNamepace = 2200;
- return TNamespaces{
- {PgInformationSchemaNamepace, TNamespaceDesc{PgInformationSchemaNamepace, "information_schema", "information_schema namespace"}},
- {PgPublicNamepace, TNamespaceDesc{PgPublicNamepace, "public", "public namespace"}},
- {PgCatalogNamepace, TNamespaceDesc{PgCatalogNamepace, "pg_catalog", "pg_catalog namespace"}},
- };
- }
- struct TTableInfoKeyRaw {
- const char* Schema;
- const char* Name;
- };
- struct TTableInfoRaw : public TTableInfoKeyRaw {
- ERelKind Kind;
- ui32 Oid;
- };
- struct TColumnInfoRaw {
- const char* Schema;
- const char* TableName;
- const char* Name;
- const char* UdtType;
- };
- const TTableInfoRaw AllStaticTablesRaw[] = {
- #include "pg_class.generated.h"
- };
- const TColumnInfoRaw AllStaticColumnsRaw[] = {
- #include "columns.generated.h"
- };
- const char* AllowedProcsRaw[] = {
- #include "safe_procs.h"
- #include "used_procs.h"
- #include "postgis_procs.h"
- };
- struct TCatalog : public IExtensionSqlBuilder {
- TCatalog() {
- Init();
- }
- void Clear() {
- State.Clear();
- }
- void Init() {
- Clear();
- State.ConstructInPlace();
- for (size_t i = 0; i < Y_ARRAY_SIZE(AllStaticTablesRaw); ++i) {
- const auto& raw = AllStaticTablesRaw[i];
- State->AllStaticTables.push_back(
- {{TString(raw.Schema), TString(raw.Name)}, raw.Kind, raw.Oid}
- );
- }
- for (size_t i = 0; i < Y_ARRAY_SIZE(AllStaticColumnsRaw); ++i) {
- const auto& raw = AllStaticColumnsRaw[i];
- State->AllStaticColumns.push_back(
- {TString(raw.Schema), TString(raw.TableName), TString(raw.Name), TString(raw.UdtType)}
- );
- }
- if ( GetEnv("YDB_EXPERIMENTAL_PG") == "1"){
- // grafana migration_log
- State->AllStaticTables.push_back(
- {{"public", "migration_log"}, ERelKind::Relation, 100001}
- );
- State->AllStaticColumns.push_back(
- {"public", "migration_log", "id", "int"}
- );
- State->AllStaticColumns.push_back(
- {"public", "migration_log", "migration_id", "character varying(255)"}
- );
- State->AllStaticColumns.push_back(
- {"public", "migration_log", "sql", "text"}
- );
- State->AllStaticColumns.push_back(
- {"public", "migration_log", "success", "boolean"}
- );
- State->AllStaticColumns.push_back(
- {"public", "migration_log", "error", "text"}
- );
- State->AllStaticColumns.push_back(
- {"public", "migration_log", "timestamp", "timestamp without time zone"}
- );
- // zabbix config
- State->AllStaticTables.push_back(
- {{"public", "config"}, ERelKind::Relation, 100001}
- );
- State->AllStaticColumns.push_back(
- {"public", "config", "configid", "bigint"}
- );
- State->AllStaticColumns.push_back(
- {"public", "config", "server_check_interval", "integer"}
- );
- State->AllStaticColumns.push_back(
- {"public", "config", "dbversion_status", "text"}
- );
- // zabbix dbversion
- State->AllStaticTables.push_back(
- {{"public", "dbversion"}, ERelKind::Relation, 100002}
- );
- State->AllStaticColumns.push_back(
- {"public", "dbversion", "dbversionid", "bigint"}
- );
- State->AllStaticColumns.push_back(
- {"public", "dbversion", "mandatory", "integer"}
- );
- State->AllStaticColumns.push_back(
- {"public", "dbversion", "mandatory", "optional"}
- );
- }
- THashSet<ui32> usedTableOids;
- for (const auto& t : State->AllStaticTables) {
- State->StaticColumns.insert(std::make_pair(t, TVector<TColumnInfo>()));
- Y_ENSURE(usedTableOids.insert(t.Oid).first);
- State->StaticTables.insert(std::make_pair(TTableInfoKey(t), t));
- }
- for (const auto& c: State->AllStaticColumns) {
- auto tablePtr = State->StaticColumns.FindPtr(TTableInfoKey{c.Schema, c.TableName});
- Y_ENSURE(tablePtr);
- tablePtr->push_back(c);
- }
- for (const auto& t : State->StaticColumns) {
- Y_ENSURE(!t.second.empty());
- }
- TString typeData;
- Y_ENSURE(NResource::FindExact("pg_type.dat", &typeData));
- TString opData;
- Y_ENSURE(NResource::FindExact("pg_operator.dat", &opData));
- TString procData;
- Y_ENSURE(NResource::FindExact("pg_proc.dat", &procData));
- TString castData;
- Y_ENSURE(NResource::FindExact("pg_cast.dat", &castData));
- TString aggData;
- Y_ENSURE(NResource::FindExact("pg_aggregate.dat", &aggData));
- TString opFamiliesData;
- Y_ENSURE(NResource::FindExact("pg_opfamily.dat", &opFamiliesData));
- TString opClassData;
- Y_ENSURE(NResource::FindExact("pg_opclass.dat", &opClassData));
- TString amProcData;
- Y_ENSURE(NResource::FindExact("pg_amproc.dat", &amProcData));
- TString amOpData;
- Y_ENSURE(NResource::FindExact("pg_amop.dat", &amOpData));
- TString conversionData;
- Y_ENSURE(NResource::FindExact("pg_conversion.dat", &conversionData));
- TString amData;
- Y_ENSURE(NResource::FindExact("pg_am.dat", &amData));
- TString languagesData;
- Y_ENSURE(NResource::FindExact("pg_language.dat", &languagesData));
- THashMap<ui32, TLazyTypeInfo> lazyTypeInfos;
- State->Types = ParseTypes(typeData, lazyTypeInfos);
- for (const auto& [k, v] : State->Types) {
- if (k == v.TypeId) {
- Y_ENSURE(State->TypeByName.insert(std::make_pair(v.Name, k)).second);
- }
- if (k == v.ArrayTypeId) {
- Y_ENSURE(State->TypeByName.insert(std::make_pair("_" + v.Name, k)).second);
- }
- }
- State->Procs = ParseProcs(procData, State->TypeByName);
- for (const auto& [k, v] : State->Procs) {
- State->ProcByName[v.Name].push_back(k);
- }
- const ui32 cstringId = 2275;
- const ui32 byteaId = 17;
- const ui32 internalId = 2281;
- for (const auto& [k, v] : lazyTypeInfos) {
- auto typePtr = State->Types.FindPtr(k);
- Y_ENSURE(typePtr);
- auto inFuncIdPtr = State->ProcByName.FindPtr(v.InFunc);
- Y_ENSURE(inFuncIdPtr);
- Y_ENSURE(inFuncIdPtr->size() == 1);
- auto inFuncPtr = State->Procs.FindPtr(inFuncIdPtr->at(0));
- Y_ENSURE(inFuncPtr);
- Y_ENSURE(inFuncPtr->ArgTypes.size() >= 1); // may have mods
- Y_ENSURE(inFuncPtr->ArgTypes[0] == cstringId);
- typePtr->InFuncId = inFuncIdPtr->at(0);
- auto outFuncIdPtr = State->ProcByName.FindPtr(v.OutFunc);
- Y_ENSURE(outFuncIdPtr);
- Y_ENSURE(outFuncIdPtr->size() == 1);
- auto outFuncPtr = State->Procs.FindPtr(outFuncIdPtr->at(0));
- Y_ENSURE(outFuncPtr);
- Y_ENSURE(outFuncPtr->ArgTypes.size() == 1);
- Y_ENSURE(outFuncPtr->ResultType == cstringId);
- typePtr->OutFuncId = outFuncIdPtr->at(0);
- if (v.ReceiveFunc != "-") {
- auto receiveFuncIdPtr = State->ProcByName.FindPtr(v.ReceiveFunc);
- Y_ENSURE(receiveFuncIdPtr);
- Y_ENSURE(receiveFuncIdPtr->size() == 1);
- auto receiveFuncPtr = State->Procs.FindPtr(receiveFuncIdPtr->at(0));
- Y_ENSURE(receiveFuncPtr);
- Y_ENSURE(receiveFuncPtr->ArgTypes.size() >= 1);
- Y_ENSURE(receiveFuncPtr->ArgTypes[0] == internalId); // mutable StringInfo
- typePtr->ReceiveFuncId = receiveFuncIdPtr->at(0);
- }
- if (v.SendFunc != "-") {
- auto sendFuncIdPtr = State->ProcByName.FindPtr(v.SendFunc);
- Y_ENSURE(sendFuncIdPtr);
- Y_ENSURE(sendFuncIdPtr->size() == 1);
- auto sendFuncPtr = State->Procs.FindPtr(sendFuncIdPtr->at(0));
- Y_ENSURE(sendFuncPtr);
- Y_ENSURE(sendFuncPtr->ArgTypes.size() == 1);
- Y_ENSURE(sendFuncPtr->ResultType == byteaId);
- typePtr->SendFuncId = sendFuncIdPtr->at(0);
- }
- if (v.ModInFunc) {
- auto modInFuncIdPtr = State->ProcByName.FindPtr(v.ModInFunc);
- Y_ENSURE(modInFuncIdPtr);
- Y_ENSURE(modInFuncIdPtr->size() == 1);
- auto modInFuncPtr = State->Procs.FindPtr(modInFuncIdPtr->at(0));
- Y_ENSURE(modInFuncPtr);
- Y_ENSURE(modInFuncPtr->ArgTypes.size() == 1);
- typePtr->TypeModInFuncId = modInFuncIdPtr->at(0);
- }
- if (v.ModOutFunc) {
- auto modOutFuncIdPtr = State->ProcByName.FindPtr(v.ModOutFunc);
- Y_ENSURE(modOutFuncIdPtr);
- Y_ENSURE(modOutFuncIdPtr->size() == 1);
- auto modOutFuncPtr = State->Procs.FindPtr(modOutFuncIdPtr->at(0));
- Y_ENSURE(modOutFuncPtr);
- Y_ENSURE(modOutFuncPtr->ArgTypes.size() == 1);
- typePtr->TypeModOutFuncId = modOutFuncIdPtr->at(0);
- }
- if (v.SubscriptFunc) {
- auto subscriptFuncIdPtr = State->ProcByName.FindPtr(v.SubscriptFunc);
- Y_ENSURE(subscriptFuncIdPtr);
- Y_ENSURE(subscriptFuncIdPtr->size() == 1);
- auto subscriptFuncPtr = State->Procs.FindPtr(subscriptFuncIdPtr->at(0));
- Y_ENSURE(subscriptFuncPtr);
- Y_ENSURE(subscriptFuncPtr->ArgTypes.size() == 1);
- typePtr->TypeSubscriptFuncId = subscriptFuncIdPtr->at(0);
- }
- if (v.ElementType) {
- auto elemTypePtr = State->TypeByName.FindPtr(v.ElementType);
- Y_ENSURE(elemTypePtr);
- typePtr->ElementTypeId = *elemTypePtr;
- }
- }
- State->Casts = ParseCasts(castData, State->TypeByName, State->Types, State->ProcByName, State->Procs);
- for (const auto&[k, v] : State->Casts) {
- Y_ENSURE(State->CastsByDir.insert(std::make_pair(std::make_pair(v.SourceId, v.TargetId), k)).second);
- }
- THashMap<ui32, TLazyOperInfo> lazyOperInfos;
- State->Operators = ParseOperators(opData, State->TypeByName, State->Types, State->ProcByName, State->Procs, lazyOperInfos);
- for (const auto&[k, v] : State->Operators) {
- State->OperatorsByName[v.Name].push_back(k);
- }
- ApplyLazyOperInfos(State->Operators, State->OperatorsByName, State->TypeByName, lazyOperInfos);
- State->Aggregations = ParseAggregations(aggData, State->TypeByName, State->Types, State->ProcByName, State->Procs);
- for (const auto&[k, v] : State->Aggregations) {
- State->AggregationsByName[v.Name].push_back(k);
- }
- State->OpFamilies = ParseOpFamilies(opFamiliesData);
- State->OpClasses = ParseOpClasses(opClassData, State->TypeByName, State->OpFamilies);
- State->AmOps = ParseAmOps(amOpData, State->TypeByName, State->Types, State->OperatorsByName, State->Operators, State->OpFamilies);
- State->AmProcs = ParseAmProcs(amProcData, State->TypeByName, State->ProcByName, State->Procs, State->OpFamilies);
- State->Ams = ParseAms(amData);
- State->Namespaces = FillNamespaces();
- for (auto& [k, v] : State->Types) {
- if (v.TypeId != v.ArrayTypeId) {
- auto lookupId = (v.TypeId == VarcharOid ? TextOid : v.TypeId);
- if (regClasses.contains(lookupId)) {
- lookupId = OidOid;
- }
- CacheAmFuncs(lookupId, v);
- }
- }
- State->Conversions = ParseConversions(conversionData, State->ProcByName);
- State->Languages = ParseLanguages(languagesData);
- if (GetEnv("YQL_ALLOW_ALL_PG_FUNCTIONS")) {
- State->AllowAllFunctions = true;
- } else if (auto exportDir = GetEnv("YQL_EXPORT_PG_FUNCTIONS_DIR")) {
- State->AllowAllFunctions = true;
- ExportFile.ConstructInPlace(MakeTempName(exportDir.c_str(), "procs"), CreateAlways | RdWr);
- for (const auto& a : State->Aggregations) {
- const auto& desc = a.second;
- ExportFunction(desc.TransFuncId);
- ExportFunction(desc.FinalFuncId);
- ExportFunction(desc.CombineFuncId);
- ExportFunction(desc.SerializeFuncId);
- ExportFunction(desc.DeserializeFuncId);
- }
- for (const auto& t : State->Types) {
- const auto& desc = t.second;
- ExportFunction(desc.InFuncId);
- ExportFunction(desc.OutFuncId);
- ExportFunction(desc.SendFuncId);
- ExportFunction(desc.ReceiveFuncId);
- ExportFunction(desc.TypeModInFuncId);
- ExportFunction(desc.TypeModOutFuncId);
- ExportFunction(desc.TypeSubscriptFuncId);
- ExportFunction(desc.LessProcId);
- ExportFunction(desc.EqualProcId);
- ExportFunction(desc.CompareProcId);
- ExportFunction(desc.HashProcId);
- }
- for (const auto& o : State->Operators) {
- const auto& desc = o.second;
- ExportFunction(desc.ProcId);
- }
- for (const auto& c : State->Casts) {
- const auto& desc = c.second;
- ExportFunction(desc.FunctionId);
- }
- } else {
- for (size_t i = 0; i < Y_ARRAY_SIZE(AllowedProcsRaw); ++i) {
- const auto& raw = AllowedProcsRaw[i];
- State->AllowedProcs.insert(raw);
- }
- for (const auto& t : State->Types) {
- State->AllowedProcs.insert(t.second.Name);
- }
- }
- }
- void ExportFunction(ui32 procOid) const {
- if (!procOid || !ExportFile) {
- return;
- }
- auto procPtr = State->Procs.FindPtr(procOid);
- Y_ENSURE(procPtr);
- ExportFunction(procPtr->Name);
- }
- void ExportFunction(const TString& name) const {
- if (!ExportFile) {
- return;
- }
- TString line = TStringBuilder() << "\"" << name << "\",\n";
- with_lock(ExportGuard) {
- ExportFile->Write(line.data(), line.size());
- }
- }
- void CacheAmFuncs(ui32 typeId, TTypeDesc& v) {
- auto btreeOpClassPtr = State->OpClasses.FindPtr(std::make_pair(EOpClassMethod::Btree, typeId));
- if (btreeOpClassPtr) {
- auto lessAmOpPtr = State->AmOps.FindPtr(std::make_tuple(btreeOpClassPtr->FamilyId, ui32(EBtreeAmStrategy::Less), typeId, typeId));
- Y_ENSURE(lessAmOpPtr);
- auto equalAmOpPtr = State->AmOps.FindPtr(std::make_tuple(btreeOpClassPtr->FamilyId, ui32(EBtreeAmStrategy::Equal), typeId, typeId));
- Y_ENSURE(equalAmOpPtr);
- auto lessOperPtr = State->Operators.FindPtr(lessAmOpPtr->OperId);
- Y_ENSURE(lessOperPtr);
- auto equalOperPtr = State->Operators.FindPtr(equalAmOpPtr->OperId);
- Y_ENSURE(equalOperPtr);
- v.LessProcId = lessOperPtr->ProcId;
- v.EqualProcId = equalOperPtr->ProcId;
- auto compareAmProcPtr = State->AmProcs.FindPtr(std::make_tuple(btreeOpClassPtr->FamilyId, ui32(EBtreeAmProcNum::Compare), typeId, typeId));
- Y_ENSURE(compareAmProcPtr);
- v.CompareProcId = compareAmProcPtr->ProcId;
- }
- auto hashOpClassPtr = State->OpClasses.FindPtr(std::make_pair(EOpClassMethod::Hash, typeId));
- if (hashOpClassPtr) {
- auto hashAmProcPtr = State->AmProcs.FindPtr(std::make_tuple(hashOpClassPtr->FamilyId, ui32(EHashAmProcNum::Hash), typeId, typeId));
- Y_ENSURE(hashAmProcPtr);
- v.HashProcId = hashAmProcPtr->ProcId;
- }
- }
- void CreateProc(const TProcDesc& desc) final {
- Y_ENSURE(desc.ExtensionIndex);
- TProcDesc newDesc = desc;
- newDesc.Name = to_lower(newDesc.Name);
- newDesc.ProcId = 16000 + State->Procs.size();
- State->Procs[newDesc.ProcId] = newDesc;
- State->ProcByName[newDesc.Name].push_back(newDesc.ProcId);
- }
- void PrepareType(ui32 extensionIndex, const TString& name) final {
- Y_ENSURE(extensionIndex);
- auto lowerName = to_lower(name);
- if (auto idPtr = State->TypeByName.FindPtr(lowerName)) {
- auto typePtr = State->Types.FindPtr(*idPtr);
- Y_ENSURE(typePtr);
- Y_ENSURE(!typePtr->ExtensionIndex || typePtr->ExtensionIndex == extensionIndex);
- return;
- }
- TTypeDesc newDesc;
- newDesc.Name = lowerName;
- newDesc.TypeId = 16000 + State->Types.size();
- newDesc.ExtensionIndex = extensionIndex;
- newDesc.ArrayTypeId = newDesc.TypeId + 1;
- newDesc.Category = 'U';
- State->Types[newDesc.TypeId] = newDesc;
- State->TypeByName[newDesc.Name] = newDesc.TypeId;
- TTypeDesc newArrayDesc = newDesc;
- newArrayDesc.TypeId += 1;
- newArrayDesc.Name = "_" + newArrayDesc.Name;
- newArrayDesc.ElementTypeId = newDesc.TypeId;
- newArrayDesc.ArrayTypeId = newArrayDesc.TypeId;
- newArrayDesc.PassByValue = false;
- newArrayDesc.TypeLen = -1;
- newArrayDesc.SendFuncId = (*State->ProcByName.FindPtr("array_send"))[0];
- newArrayDesc.ReceiveFuncId = (*State->ProcByName.FindPtr("array_recv"))[0];
- newArrayDesc.InFuncId = (*State->ProcByName.FindPtr("array_in"))[0];
- newArrayDesc.OutFuncId = (*State->ProcByName.FindPtr("array_out"))[0];
- newArrayDesc.Category = 'A';
- State->Types[newArrayDesc.TypeId] = newArrayDesc;
- State->TypeByName[newArrayDesc.Name] = newArrayDesc.TypeId;
- }
- void UpdateType(const TTypeDesc& desc) final {
- Y_ENSURE(desc.ExtensionIndex);
- auto byIdPtr = State->Types.FindPtr(desc.TypeId);
- Y_ENSURE(byIdPtr);
- Y_ENSURE(byIdPtr->Name == desc.Name);
- Y_ENSURE(byIdPtr->ArrayTypeId == desc.ArrayTypeId);
- Y_ENSURE(byIdPtr->TypeId == desc.TypeId);
- Y_ENSURE(byIdPtr->ExtensionIndex == desc.ExtensionIndex);
- if (desc.InFuncId) {
- State->AllowedProcs.insert(State->Procs.FindPtr(desc.InFuncId)->Name);
- }
- if (desc.OutFuncId) {
- State->AllowedProcs.insert(State->Procs.FindPtr(desc.OutFuncId)->Name);
- }
- if (desc.SendFuncId) {
- State->AllowedProcs.insert(State->Procs.FindPtr(desc.SendFuncId)->Name);
- }
- if (desc.ReceiveFuncId) {
- State->AllowedProcs.insert(State->Procs.FindPtr(desc.ReceiveFuncId)->Name);
- }
- if (desc.TypeModInFuncId) {
- State->AllowedProcs.insert(State->Procs.FindPtr(desc.TypeModInFuncId)->Name);
- }
- if (desc.TypeModOutFuncId) {
- State->AllowedProcs.insert(State->Procs.FindPtr(desc.TypeModOutFuncId)->Name);
- }
- *byIdPtr = desc;
- }
- void CreateTable(const TTableInfo& table, const TVector<TColumnInfo>& columns) final {
- Y_ENSURE(table.ExtensionIndex);
- Y_ENSURE(!columns.empty());
- THashSet<TString> usedColumns;
- for (const auto& c : columns) {
- Y_ENSURE(c.Schema == table.Schema);
- Y_ENSURE(c.TableName == table.Name);
- Y_ENSURE(c.ExtensionIndex == table.ExtensionIndex);
- Y_ENSURE(usedColumns.insert(c.Name).second);
- }
- TTableInfoKey key{table};
- TTableInfo value = table;
- value.Oid = 16000 + State->StaticTables.size();
- Y_ENSURE(State->StaticTables.emplace(key, value).second);
- Y_ENSURE(State->StaticColumns.emplace(key, columns).second);
- State->AllStaticTables.push_back(value);
- for (const auto& c : columns) {
- State->AllStaticColumns.push_back(c);
- }
- }
- void InsertValues(const TTableInfoKey& table, const TVector<TString>& columns,
- const TVector<TMaybe<TString>>& data) final {
- Y_ENSURE(State->StaticTables.contains(table));
- const auto& columnDefs = *State->StaticColumns.FindPtr(table);
- Y_ENSURE(columnDefs.size() == columns.size());
- Y_ENSURE(data.size() % columns.size() == 0);
- THashMap<TString, ui32> columnToIndex;
- for (ui32 i = 0; i < columnDefs.size(); ++i) {
- columnToIndex[columnDefs[i].Name] = i;
- }
- THashSet<TString> usedColumns;
- TVector<ui32> dataColumnRemap;
- for (const auto& c : columns) {
- Y_ENSURE(usedColumns.insert(c).second);
- dataColumnRemap.push_back(*columnToIndex.FindPtr(c));
- }
- auto& tableData = State->StaticTablesData[table];
- size_t writePos = tableData.size();
- tableData.resize(tableData.size() + data.size());
- size_t readRowPos = 0;
- while (writePos < tableData.size()) {
- for (size_t colIdx = 0; colIdx < columns.size(); ++colIdx) {
- tableData[writePos++] = data[readRowPos + dataColumnRemap[colIdx]];
- }
- readRowPos += columns.size();
- }
- Y_ENSURE(readRowPos == data.size());
- }
- void CreateCast(const TCastDesc& desc) final {
- Y_ENSURE(desc.ExtensionIndex);
- auto id = 1 + State->Casts.size();
- State->Casts[id] = desc;
- Y_ENSURE(State->CastsByDir.insert(std::make_pair(std::make_pair(desc.SourceId, desc.TargetId), id)).second);
- if (desc.FunctionId) {
- auto funcPtr = State->Procs.FindPtr(desc.FunctionId);
- Y_ENSURE(funcPtr);
- State->AllowedProcs.insert(funcPtr->Name);
- }
- }
- void PrepareOper(ui32 extensionIndex, const TString& name, const TVector<ui32>& args) final {
- Y_ENSURE(args.size() >= 1 && args.size() <= 2);
- Y_ENSURE(extensionIndex);
- auto lowerName = to_lower(name);
- auto operIdPtr = State->OperatorsByName.FindPtr(lowerName);
- if (operIdPtr) {
- for (const auto& id : *operIdPtr) {
- const auto& d = State->Operators.FindPtr(id);
- Y_ENSURE(d);
- if (d->LeftType == args[0] && (args.size() == 1 || d->RightType == args[1])) {
- Y_ENSURE(!d->ExtensionIndex || d->ExtensionIndex == extensionIndex);
- return;
- }
- }
- }
- if (!operIdPtr) {
- operIdPtr = &State->OperatorsByName[lowerName];
- }
- TOperDesc desc;
- desc.Name = name;
- desc.LeftType = args[0];
- if (args.size() == 1) {
- desc.Kind = EOperKind::LeftUnary;
- } else {
- desc.RightType = args[1];
- }
- auto id = 16000 + State->Operators.size();
- desc.OperId = id;
- desc.ExtensionIndex = extensionIndex;
- Y_ENSURE(State->Operators.emplace(id, desc).second);
- operIdPtr->push_back(id);
- }
- void UpdateOper(const TOperDesc& desc) final {
- Y_ENSURE(desc.ExtensionIndex);
- const auto& d = State->Operators.FindPtr(desc.OperId);
- Y_ENSURE(d);
- Y_ENSURE(d->Name == desc.Name);
- Y_ENSURE(d->ExtensionIndex == desc.ExtensionIndex);
- Y_ENSURE(d->LeftType == desc.LeftType);
- Y_ENSURE(d->RightType == desc.RightType);
- Y_ENSURE(d->Kind == desc.Kind);
- d->ProcId = desc.ProcId;
- d->ComId = desc.ComId;
- d->NegateId = desc.NegateId;
- d->ResultType = desc.ResultType;
- auto procPtr = State->Procs.FindPtr(desc.ProcId);
- Y_ENSURE(procPtr);
- State->AllowedProcs.insert(procPtr->Name);
- }
- void CreateAggregate(const TAggregateDesc& desc) final {
- Y_ENSURE(desc.ExtensionIndex);
- auto id = 16000 + State->Aggregations.size();
- auto newDesc = desc;
- newDesc.Name = to_lower(newDesc.Name);
- newDesc.AggId = id;
- Y_ENSURE(State->Aggregations.emplace(id, newDesc).second);
- State->AggregationsByName[newDesc.Name].push_back(id);
- if (desc.CombineFuncId) {
- State->AllowedProcs.insert(State->Procs.FindPtr(desc.CombineFuncId)->Name);
- }
- if (desc.DeserializeFuncId) {
- State->AllowedProcs.insert(State->Procs.FindPtr(desc.DeserializeFuncId)->Name);
- }
- if (desc.SerializeFuncId) {
- State->AllowedProcs.insert(State->Procs.FindPtr(desc.SerializeFuncId)->Name);
- }
- if (desc.FinalFuncId) {
- State->AllowedProcs.insert(State->Procs.FindPtr(desc.FinalFuncId)->Name);
- }
- State->AllowedProcs.insert(State->Procs.FindPtr(desc.TransFuncId)->Name);
- }
- void CreateOpClass(const TOpClassDesc& opclass, const TVector<TAmOpDesc>& ops, const TVector<TAmProcDesc>& procs) final {
- Y_ENSURE(opclass.ExtensionIndex);
- auto newDesc = opclass;
- newDesc.Family = to_lower(newDesc.Family);
- newDesc.Name = to_lower(newDesc.Name);
- auto newFamilyId = 16000 + State->OpFamilies.size();
- TOpFamilyDesc opFamilyDesc;
- opFamilyDesc.FamilyId = newFamilyId;
- opFamilyDesc.Name = newDesc.Family;
- opFamilyDesc.ExtensionIndex = opclass.ExtensionIndex;
- Y_ENSURE(State->OpFamilies.emplace(newDesc.Family, opFamilyDesc).second);
- newDesc.FamilyId = newFamilyId;
- const auto key = std::make_pair(newDesc.Method, newDesc.TypeId);
- Y_ENSURE(State->OpClasses.emplace(key, newDesc).second);
- for (const auto& o : ops) {
- Y_ENSURE(opclass.ExtensionIndex == o.ExtensionIndex);
- Y_ENSURE(opclass.Family == o.Family);
- auto newOpDesc = o;
- newOpDesc.FamilyId = newFamilyId;
- newOpDesc.Family = newDesc.Name;
- Y_ENSURE(State->AmOps.emplace(std::make_tuple(newFamilyId, o.Strategy, o.LeftType, o.RightType), newOpDesc).second);
- auto operPtr = State->Operators.FindPtr(o.OperId);
- Y_ENSURE(operPtr);
- auto procPtr = State->Procs.FindPtr(operPtr->ProcId);
- Y_ENSURE(procPtr);
- State->AllowedProcs.emplace(procPtr->Name);
- }
- for (const auto& p : procs) {
- Y_ENSURE(opclass.ExtensionIndex == p.ExtensionIndex);
- Y_ENSURE(opclass.Family == p.Family);
- auto newProcDesc = p;
- newProcDesc.FamilyId = newFamilyId;
- newProcDesc.Family = newDesc.Name;
- Y_ENSURE(State->AmProcs.emplace(std::make_tuple(newFamilyId, p.ProcNum, p.LeftType, p.RightType), newProcDesc).second);
- auto procPtr = State->Procs.FindPtr(p.ProcId);
- Y_ENSURE(procPtr);
- State->AllowedProcs.emplace(procPtr->Name);
- }
- auto typePtr = State->Types.FindPtr(opclass.TypeId);
- Y_ENSURE(typePtr);
- Y_ENSURE(typePtr->ExtensionIndex == opclass.ExtensionIndex);
- CacheAmFuncs(opclass.TypeId, *typePtr);
- }
- static const TCatalog& Instance() {
- return *Singleton<TCatalog>();
- }
- static TCatalog& MutableInstance() {
- return *Singleton<TCatalog>();
- }
- struct TState {
- TExtensionsByName ExtensionsByName, ExtensionsByInstallName;
- TExtensions Extensions;
- TOperators Operators;
- TProcs Procs;
- TTypes Types;
- TCasts Casts;
- TAggregations Aggregations;
- TAms Ams;
- TNamespaces Namespaces;
- TOpFamilies OpFamilies;
- TOpClasses OpClasses;
- TAmOps AmOps;
- TAmProcs AmProcs;
- TConversions Conversions;
- TLanguages Languages;
- THashMap<TString, TVector<ui32>> ProcByName;
- THashMap<TString, ui32> TypeByName;
- THashMap<std::pair<ui32, ui32>, ui32> CastsByDir;
- THashMap<TString, TVector<ui32>> OperatorsByName;
- THashMap<TString, TVector<ui32>> AggregationsByName;
- TVector<TTableInfo> AllStaticTables;
- TVector<TColumnInfo> AllStaticColumns;
- THashMap<TTableInfoKey, TTableInfo> StaticTables;
- THashMap<TTableInfoKey, TVector<TColumnInfo>> StaticColumns;
- THashMap<TTableInfoKey, TVector<TMaybe<TString>>> StaticTablesData;
- bool AllowAllFunctions = false;
- THashSet<TString> AllowedProcs;
- bool SystemFunctionInit = false;
- };
- mutable TMaybe<TFile> ExportFile;
- TMutex ExportGuard;
- TMaybe<TState> State;
- TMutex ExtensionsGuard;
- bool ExtensionsInit = false;
- };
- bool ValidateProcArgs(const TProcDesc& d, const TVector<ui32>& argTypeIds) {
- const auto& catalog = TCatalog::Instance();
- return ValidateArgs(d.ArgTypes, argTypeIds, catalog.State->Types, d.VariadicType);
- }
- const TProcDesc& LookupProc(ui32 procId, const TVector<ui32>& argTypeIds) {
- const auto& catalog = TCatalog::Instance();
- auto procPtr = catalog.State->Procs.FindPtr(procId);
- if (!procPtr) {
- throw yexception() << "No such proc: " << procId;
- }
- if (!catalog.State->AllowAllFunctions && !catalog.State->AllowedProcs.contains(procPtr->Name)) {
- throw yexception() << "No access to proc: " << procPtr->Name;
- }
- if (!ValidateProcArgs(*procPtr, argTypeIds)) {
- throw yexception() << "Unable to find an overload for proc with oid " << procId << " with given argument types: " <<
- ArgTypesList(argTypeIds);
- }
- catalog.ExportFunction(procId);
- return *procPtr;
- }
- const TProcDesc& LookupProc(const TString& name, const TVector<ui32>& argTypeIds) {
- const auto& catalog = TCatalog::Instance();
- auto lower = to_lower(name);
- auto procIdPtr = catalog.State->ProcByName.FindPtr(lower);
- if (!procIdPtr) {
- throw yexception() << "No such proc: " << name;
- }
- for (const auto& id : *procIdPtr) {
- const auto& d = catalog.State->Procs.FindPtr(id);
- Y_ENSURE(d);
- if (!catalog.State->AllowAllFunctions && !catalog.State->AllowedProcs.contains(d->Name)) {
- throw yexception() << "No access to proc: " << d->Name;
- }
- if (!ValidateProcArgs(*d, argTypeIds)) {
- continue;
- }
- catalog.ExportFunction(d->Name);
- return *d;
- }
- throw yexception() << "Unable to find an overload for proc " << name << " with given argument types: "
- << ArgTypesList(argTypeIds);
- }
- const TProcDesc& LookupProc(ui32 procId) {
- const auto& catalog = TCatalog::Instance();
- auto procPtr = catalog.State->Procs.FindPtr(procId);
- if (!procPtr) {
- throw yexception() << "No such proc: " << procId;
- }
- if (!catalog.State->AllowAllFunctions && !catalog.State->AllowedProcs.contains(procPtr->Name)) {
- throw yexception() << "No access to proc: " << procPtr->Name;
- }
- catalog.ExportFunction(procId);
- return *procPtr;
- }
- void EnumProc(std::function<void(ui32, const TProcDesc&)> f) {
- const auto& catalog = TCatalog::Instance();
- for (const auto& x : catalog.State->Procs) {
- if (catalog.State->AllowAllFunctions || catalog.State->AllowedProcs.contains(x.second.Name)) {
- f(x.first, x.second);
- }
- }
- }
- bool HasProc(const TString& name, EProcKind kind) {
- const auto& catalog = TCatalog::Instance();
- auto procIdPtr = catalog.State->ProcByName.FindPtr(to_lower(name));
- if (!procIdPtr) {
- return false;
- }
- for (const auto& id : *procIdPtr) {
- const auto& d = catalog.State->Procs.FindPtr(id);
- Y_ENSURE(d);
- if (d->Kind == kind) {
- return true;
- }
- }
- return false;
- }
- bool HasReturnSetProc(const TString& name) {
- const auto& catalog = TCatalog::Instance();
- auto procIdPtr = catalog.State->ProcByName.FindPtr(to_lower(name));
- if (!procIdPtr) {
- return false;
- }
- for (const auto& id : *procIdPtr) {
- const auto& d = catalog.State->Procs.FindPtr(id);
- Y_ENSURE(d);
- if (d->ReturnSet) {
- return true;
- }
- }
- return false;
- }
- bool HasType(const TString& name) {
- const auto& catalog = TCatalog::Instance();
- return catalog.State->TypeByName.contains(GetCanonicalTypeName(to_lower(name)));
- }
- const TTypeDesc& LookupType(const TString& name) {
- const auto& catalog = TCatalog::Instance();
- const auto typeIdPtr = catalog.State->TypeByName.FindPtr(GetCanonicalTypeName(to_lower(name)));
- if (!typeIdPtr) {
- throw yexception() << "No such type: " << name;
- }
- const auto typePtr = catalog.State->Types.FindPtr(*typeIdPtr);
- Y_ENSURE(typePtr);
- return *typePtr;
- }
- bool HasType(ui32 typeId) {
- const auto& catalog = TCatalog::Instance();
- return catalog.State->Types.contains(typeId);
- }
- const TTypeDesc& LookupType(ui32 typeId) {
- const auto& catalog = TCatalog::Instance();
- const auto typePtr = catalog.State->Types.FindPtr(typeId);
- if (!typePtr) {
- throw yexception() << "No such type: " << typeId;
- }
- return *typePtr;
- }
- void EnumTypes(std::function<void(ui32, const TTypeDesc&)> f) {
- const auto& catalog = TCatalog::Instance();
- for (const auto& [typeId, desc] : catalog.State->Types) {
- f(typeId, desc);
- }
- }
- const TAmDesc& LookupAm(ui32 oid) {
- const auto& catalog = TCatalog::Instance();
- const auto typePtr = catalog.State->Ams.FindPtr(oid);
- if (!typePtr) {
- throw yexception() << "No such am: " << oid;
- }
- return *typePtr;
- }
- void EnumAm(std::function<void(ui32, const TAmDesc&)> f) {
- const auto& catalog = TCatalog::Instance();
- for (const auto& [oid, desc] : catalog.State->Ams) {
- f(oid, desc);
- }
- }
- void EnumConversions(std::function<void(const TConversionDesc&)> f) {
- const auto& catalog = TCatalog::Instance();
- for (const auto& [_, desc] : catalog.State->Conversions) {
- f(desc);
- }
- }
- const TNamespaceDesc& LookupNamespace(ui32 oid) {
- const auto& catalog = TCatalog::Instance();
- const auto typePtr = catalog.State->Namespaces.FindPtr(oid);
- if (!typePtr) {
- throw yexception() << "No such namespace: " << oid;
- }
- return *typePtr;
- }
- void EnumNamespace(std::function<void(ui32, const TNamespaceDesc&)> f) {
- const auto& catalog = TCatalog::Instance();
- for (const auto& [oid, desc] : catalog.State->Namespaces) {
- f(oid, desc);
- }
- }
- void EnumOperators(std::function<void(const TOperDesc&)> f) {
- const auto& catalog = TCatalog::Instance();
- for (const auto& [_, desc] : catalog.State->Operators) {
- f(desc);
- }
- }
- bool HasCast(ui32 sourceId, ui32 targetId) {
- const auto& catalog = TCatalog::Instance();
- return catalog.State->CastsByDir.contains(std::make_pair(sourceId, targetId));
- }
- const TCastDesc& LookupCast(ui32 sourceId, ui32 targetId) {
- const auto& catalog = TCatalog::Instance();
- auto castByDirPtr = catalog.State->CastsByDir.FindPtr(std::make_pair(sourceId, targetId));
- if (!castByDirPtr) {
- throw yexception() << "No such cast";
- }
- auto castPtr = catalog.State->Casts.FindPtr(*castByDirPtr);
- Y_ENSURE(castPtr);
- return *castPtr;
- }
- namespace NPrivate {
- constexpr ui64 NoFitScore = 0;
- bool CanUseCoercionType(ECoercionCode requiredCoercionLevel, ECoercionCode actualCoercionLevel) {
- switch (requiredCoercionLevel) {
- case NYql::NPg::ECoercionCode::Implicit:
- return actualCoercionLevel == ECoercionCode::Implicit;
- case NYql::NPg::ECoercionCode::Assignment:
- return (actualCoercionLevel == ECoercionCode::Implicit) || (actualCoercionLevel == ECoercionCode::Assignment);
- case NYql::NPg::ECoercionCode::Explicit:
- return (actualCoercionLevel != ECoercionCode::Unknown);
- case NYql::NPg::ECoercionCode::Unknown:
- return false;
- }
- }
- enum class ECoercionSearchResult
- {
- None,
- Func,
- BinaryCompatible,
- ArrayCoerce,
- IOCoerce,
- };
- ECoercionSearchResult FindCoercionPath(ui32 fromTypeId, ui32 toTypeId, ECoercionCode coercionType, const TCatalog& catalog) {
- if (fromTypeId == toTypeId) {
- return ECoercionSearchResult::BinaryCompatible;
- }
- const auto* castId = catalog.State->CastsByDir.FindPtr(std::make_pair(fromTypeId, toTypeId));
- if (castId != nullptr) {
- const auto* castPtr = catalog.State->Casts.FindPtr(*castId);
- Y_ENSURE(castPtr);
- if (!CanUseCoercionType(coercionType, castPtr->CoercionCode)) {
- return ECoercionSearchResult::None;
- }
- switch (castPtr->Method) {
- case ECastMethod::Function:
- return ECoercionSearchResult::Func;
- case ECastMethod::Binary:
- return ECoercionSearchResult::BinaryCompatible;
- case ECastMethod::InOut:
- return ECoercionSearchResult::IOCoerce;
- }
- }
- if (toTypeId != OidVectorOid && toTypeId != Int2VectorOid) {
- const auto* toTypePtr = catalog.State->Types.FindPtr(toTypeId);
- Y_ENSURE(toTypePtr);
- const auto* fromTypePtr = catalog.State->Types.FindPtr(fromTypeId);
- Y_ENSURE(fromTypePtr);
- if (IsArrayType(*toTypePtr) && IsArrayType(*fromTypePtr)) {
- if (FindCoercionPath(fromTypePtr->ElementTypeId, toTypePtr->ElementTypeId, coercionType, catalog) != ECoercionSearchResult::None) {
- return ECoercionSearchResult::ArrayCoerce;
- }
- }
- }
- if (coercionType == ECoercionCode::Assignment || coercionType == ECoercionCode::Explicit) {
- const auto* toTypePtr = catalog.State->Types.FindPtr(toTypeId);
- Y_ENSURE(toTypePtr);
- if (toTypePtr->Category == 'S') {
- return ECoercionSearchResult::IOCoerce;
- }
- if (coercionType == ECoercionCode::Explicit) {
- const auto* fromTypePtr = catalog.State->Types.FindPtr(fromTypeId);
- Y_ENSURE(fromTypePtr);
- if (fromTypePtr->Category == 'S') {
- return ECoercionSearchResult::IOCoerce;
- }
- }
- }
- return ECoercionSearchResult::None;
- }
- bool IsCoercible(ui32 fromTypeId, ui32 toTypeId, ECoercionCode coercionType, const TCatalog& catalog) {
- if (fromTypeId == toTypeId) {
- return true;
- }
- if (toTypeId == AnyOid) {
- return true;
- }
- //TODO: support polymorphic types
- if (fromTypeId == UnknownOid) {
- return true;
- }
- if (FindCoercionPath(fromTypeId, toTypeId, coercionType, catalog) != ECoercionSearchResult::None ) {
- return true;
- }
- // TODO: support record & complex types
- // TODO: support record array
- // TODO: support inheritance
- if (toTypeId == AnyArrayOid) {
- const auto& actualDescPtr = catalog.State->Types.FindPtr(fromTypeId);
- Y_ENSURE(actualDescPtr);
- return actualDescPtr->ArrayTypeId == actualDescPtr->TypeId;
- }
- if (toTypeId == AnyNonArrayOid) {
- const auto& actualDescPtr = catalog.State->Types.FindPtr(fromTypeId);
- Y_ENSURE(actualDescPtr);
- return actualDescPtr->ArrayTypeId != actualDescPtr->TypeId;
- }
- return false;
- }
- bool IsPreferredType(char categoryId, const TTypeDesc& type) {
- Y_ENSURE(type.Category != InvalidCategory);
- return (categoryId == type.Category) ? type.IsPreferred : false;
- }
- constexpr ui32 CoercibleMatchShift = 16;
- constexpr ui64 ArgExactTypeMatch = 1ULL << 2*CoercibleMatchShift;
- constexpr ui64 ArgPreferredTypeMatch = 1ULL << CoercibleMatchShift;
- constexpr ui64 ArgCoercibleTypeMatch = 1ULL;
- constexpr ui64 ArgTypeMismatch = 0;
- ui64 CalcArgumentMatchScore(ui32 operArgTypeId, ui32 argTypeId, const TCatalog& catalog) {
- Y_ENSURE(operArgTypeId != UnknownOid);
- // https://www.postgresql.org/docs/14/typeconv-oper.html, step 2
- if (argTypeId == operArgTypeId) {
- return ArgExactTypeMatch;
- }
- if (argTypeId == UnknownOid) {
- return ArgCoercibleTypeMatch;
- }
- // https://www.postgresql.org/docs/14/typeconv-oper.html, step 3.c
- if (IsCoercible(argTypeId, operArgTypeId, ECoercionCode::Implicit, catalog)) {
- // https://www.postgresql.org/docs/14/typeconv-oper.html, step 3.d
- const auto& argType = catalog.State->Types.FindPtr(argTypeId);
- Y_ENSURE(argType);
- const auto& operArgType = catalog.State->Types.FindPtr(operArgTypeId);
- Y_ENSURE(operArgType);
- return IsPreferredType(argType->Category, *operArgType)
- ? ArgPreferredTypeMatch
- : ArgCoercibleTypeMatch;
- }
- // https://www.postgresql.org/docs/14/typeconv-oper.html, step 3.a
- return ArgTypeMismatch;
- }
- ui64 CalcBinaryOperatorScore(const TOperDesc& oper, ui32 leftArgTypeId, ui32 rightArgTypeId, const TCatalog& catalog) {
- // https://www.postgresql.org/docs/14/typeconv-oper.html, step 2.a
- if (leftArgTypeId == UnknownOid && rightArgTypeId != InvalidOid) {
- if (oper.LeftType == rightArgTypeId && oper.RightType == rightArgTypeId) {
- return ArgExactTypeMatch + ArgExactTypeMatch;
- }
- }
- else if (rightArgTypeId == UnknownOid && leftArgTypeId != InvalidOid) {
- if (oper.LeftType == leftArgTypeId && oper.RightType == leftArgTypeId) {
- return ArgExactTypeMatch + ArgExactTypeMatch;
- }
- }
- // https://www.postgresql.org/docs/14/typeconv-oper.html, steps 3.a, 3.c, 3.d
- auto lscore = CalcArgumentMatchScore(oper.LeftType, leftArgTypeId, catalog);
- auto rscore = CalcArgumentMatchScore(oper.RightType, rightArgTypeId, catalog);
- if (lscore == ArgTypeMismatch || rscore == ArgTypeMismatch) {
- return ArgTypeMismatch;
- }
- return lscore + rscore;
- }
- ui64 CalcUnaryOperatorScore(const TOperDesc& oper, ui32 argTypeId, const TCatalog& catalog) {
- return CalcArgumentMatchScore(oper.RightType, argTypeId, catalog);
- }
- bool IsExactMatch(const TVector<ui32>& procArgTypes, ui32 procVariadicType, const TVector<ui32>& argTypeIds) {
- if (argTypeIds.size() < procArgTypes.size()) {
- return false;
- }
- if (!procVariadicType && argTypeIds.size() > procArgTypes.size()) {
- return false;
- }
- for (ui32 i = 0; i < procArgTypes.size(); ++i) {
- if (procArgTypes[i] != argTypeIds[i]) {
- return false;
- }
- }
- if (procVariadicType) {
- if (argTypeIds.size() == procArgTypes.size()) {
- return false;
- }
- for (ui32 i = procArgTypes.size(); i < argTypeIds.size(); ++i) {
- if (procVariadicType != argTypeIds[i]) {
- return false;
- }
- }
- }
- return true;
- }
- ui64 CalcProcScore(const TVector<ui32>& procArgTypes, ui32 procVariadicType, ui32 procDefArgs, const TVector<ui32>& argTypeIds, const TCatalog& catalog) {
- ui64 result = 0UL;
- if (!procVariadicType) {
- ++result;
- }
- Y_ENSURE(procArgTypes.size() >= procDefArgs);
- if (argTypeIds.size() < procArgTypes.size() - procDefArgs) {
- return ArgTypeMismatch;
- }
- if (!procVariadicType && argTypeIds.size() > procArgTypes.size()) {
- return ArgTypeMismatch;
- }
- if (procVariadicType && argTypeIds.size() == procArgTypes.size()) {
- return ArgTypeMismatch;
- }
- for (size_t i = 0; i < argTypeIds.size(); ++i) {
- auto score = CalcArgumentMatchScore(i >= procArgTypes.size() ? procVariadicType : procArgTypes[i], argTypeIds[i], catalog);
- if (score == ArgTypeMismatch) {
- return ArgTypeMismatch;
- }
- result += score;
- }
- return result;
- }
- [[noreturn]] void ThrowOperatorNotFound(const TString& name, const TVector<ui32>& argTypeIds) {
- throw yexception() << "Unable to find an overload for operator " << name << " with given argument type(s): "
- << ArgTypesList(argTypeIds);
- }
- [[noreturn]] void ThrowOperatorAmbiguity(const TString& name, const TVector<ui32>& argTypeIds) {
- throw yexception() << "Ambiguity for operator " << name << " with given argument type(s): "
- << ArgTypesList(argTypeIds);
- }
- [[noreturn]] void ThrowProcNotFound(const TString& name, const TVector<ui32>& argTypeIds) {
- throw yexception() << "Unable to find an overload for proc " << name << " with given argument types: "
- << ArgTypesList(argTypeIds);
- }
- [[noreturn]] void ThrowProcAmbiguity(const TString& name, const TVector<ui32>& argTypeIds) {
- throw yexception() << "Ambiguity for proc " << name << " with given argument type(s): "
- << ArgTypesList(argTypeIds);
- }
- [[noreturn]] void ThrowAggregateNotFound(const TString& name, const TVector<ui32>& argTypeIds) {
- throw yexception() << "Unable to find an overload for aggregate " << name << " with given argument types: "
- << ArgTypesList(argTypeIds);
- }
- [[noreturn]] void ThrowAggregateAmbiguity(const TString& name, const TVector<ui32>& argTypeIds) {
- throw yexception() << "Ambiguity for aggregate " << name << " with given argument type(s): "
- << ArgTypesList(argTypeIds);
- }
- struct TCommonCategoryDesc {
- size_t Position;
- char Category = InvalidCategory;
- bool IsPreferred = false;
- TCommonCategoryDesc(size_t position, char category, bool isPreferred)
- : Position(position), Category(category), IsPreferred(isPreferred) {}
- };
- template <class C>
- char FindCommonCategory(const TVector<const C*> &candidates, std::function<ui32(const C*)> getTypeId, const TCatalog &catalog, bool &isPreferred) {
- char category = InvalidCategory;
- auto isConflict = false;
- isPreferred = false;
- for (const auto* candidate : candidates) {
- const auto argTypeId = getTypeId(candidate);
- const auto& argTypePtr = catalog.State->Types.FindPtr(argTypeId);
- Y_ENSURE(argTypePtr);
- if (InvalidCategory == category) {
- category = argTypePtr->Category;
- isPreferred = argTypePtr->IsPreferred;
- } else if (category == argTypePtr->Category) {
- isPreferred |= argTypePtr->IsPreferred;
- } else {
- if (argTypePtr->Category == 'S') {
- category = argTypePtr->Category;
- isPreferred = argTypePtr->IsPreferred;
- } else {
- isConflict = true;
- }
- }
- }
- if (isConflict && category != 'S') {
- isPreferred = false;
- return InvalidCategory;
- }
- return category;
- }
- template <class C>
- TVector<const C*> TryResolveUnknownsByCategory(const TVector<const C*>& candidates, const TVector<ui32>& argTypeIds, const TCatalog& catalog) {
- TVector<NPrivate::TCommonCategoryDesc> argCommonCategory;
- size_t unknownsCnt = 0;
- for (size_t i = 0; i < argTypeIds.size(); ++i) {
- if (argTypeIds[i] != UnknownOid) {
- continue;
- }
- ++unknownsCnt;
- char category = InvalidCategory;
- bool isPreferred = false;
- std::function<ui32(const C *)> typeGetter = [i] (const auto* candidate) {
- if constexpr (std::is_same_v<C, TProcDesc>) {
- return i < candidate->ArgTypes.size() ? candidate->ArgTypes[i] : candidate->VariadicType;
- } else {
- return candidate->ArgTypes[i];
- }
- };
- if (InvalidCategory != (category = NPrivate::FindCommonCategory<C>(candidates, typeGetter, catalog, isPreferred))) {
- argCommonCategory.emplace_back(i, category, isPreferred);
- }
- }
- if (argCommonCategory.size() < unknownsCnt) {
- return candidates;
- }
- TVector<const C*> filteredCandidates;
- for (const auto* candidate : candidates) {
- auto keepIt = true;
- for (const auto& category : argCommonCategory) {
- ui32 argTypeId;
- if constexpr (std::is_same_v<C, TProcDesc>) {
- argTypeId = category.Position < candidate->ArgTypes.size() ? candidate->ArgTypes[category.Position] : candidate->VariadicType;
- } else {
- argTypeId = candidate->ArgTypes[category.Position];
- }
- const auto& argTypePtr = catalog.State->Types.FindPtr(argTypeId);
- Y_ENSURE(argTypePtr);
- if (argTypePtr->Category != category.Category) {
- keepIt = false;
- break;
- }
- if (category.IsPreferred && !argTypePtr->IsPreferred) {
- keepIt = false;
- break;
- }
- }
- if (keepIt) {
- filteredCandidates.push_back(candidate);
- }
- }
- return filteredCandidates.empty() ? candidates : filteredCandidates;
- }
- template <>
- TVector<const TOperDesc*> TryResolveUnknownsByCategory<TOperDesc>(const TVector<const TOperDesc*>& candidates, const TVector<ui32>& argTypeIds, const TCatalog& catalog) {
- TVector<NPrivate::TCommonCategoryDesc> argCommonCategory;
- size_t unknownsCnt = 0;
- for (size_t i = 0; i < argTypeIds.size(); ++i) {
- if (argTypeIds[i] != UnknownOid) {
- continue;
- }
- ++unknownsCnt;
- char category = InvalidCategory;
- bool isPreferred = false;
- std::function <ui32(const TOperDesc*)> typeGetter;
- if (i == 1) {
- typeGetter = [] (const auto* candidate) {
- return candidate->RightType;
- };
- } else {
- typeGetter = [] (const auto* candidate) {
- return (candidate->Kind == EOperKind::Binary)
- ? candidate->LeftType
- : candidate->RightType;
- };
- }
- if (InvalidCategory != (category = NPrivate::FindCommonCategory<TOperDesc>(candidates, typeGetter, catalog, isPreferred))) {
- argCommonCategory.emplace_back(i, category, isPreferred);
- }
- }
- if (argCommonCategory.size() < unknownsCnt) {
- return candidates;
- }
- TVector<const TOperDesc*> filteredCandidates;
- for (const auto* candidate : candidates) {
- auto keepIt = true;
- for (const auto& category : argCommonCategory) {
- const auto argTypeId = (category.Position == 1)
- ? candidate->RightType
- : (candidate->Kind == EOperKind::Binary) ? candidate->LeftType : candidate->RightType;
- const auto& argTypePtr = catalog.State->Types.FindPtr(argTypeId);
- Y_ENSURE(argTypePtr);
- if (argTypePtr->Category != category.Category) {
- keepIt = false;
- break;
- }
- if (category.IsPreferred && !argTypePtr->IsPreferred) {
- keepIt = false;
- break;
- }
- }
- if (keepIt) {
- filteredCandidates.push_back(candidate);
- }
- }
- return filteredCandidates.empty() ? candidates : filteredCandidates;
- }
- bool CanCastImplicitly(ui32 fromTypeId, ui32 toTypeId, const TCatalog& catalog) {
- const auto* castId = catalog.State->CastsByDir.FindPtr(std::make_pair(fromTypeId, toTypeId));
- if (!castId) {
- return false;
- }
- const auto* castPtr = catalog.State->Casts.FindPtr(*castId);
- Y_ENSURE(castPtr);
- return (castPtr->CoercionCode == ECoercionCode::Implicit);
- }
- } // NPrivate
- bool IsCoercible(ui32 fromTypeId, ui32 toTypeId, ECoercionCode coercionType) {
- const auto& catalog = TCatalog::Instance();
- return NPrivate::IsCoercible(fromTypeId, toTypeId, coercionType, catalog);
- }
- std::variant<const TProcDesc*, const TTypeDesc*> LookupProcWithCasts(const TString& name, const TVector<ui32>& argTypeIds) {
- const auto& catalog = TCatalog::Instance();
- auto lower = to_lower(name);
- auto procIdPtr = catalog.State->ProcByName.FindPtr(lower);
- if (!procIdPtr) {
- throw yexception() << "No such proc: " << name;
- }
- auto bestScore = NPrivate::NoFitScore;
- TVector<const TProcDesc*> candidates;
- for (const auto& id : *procIdPtr) {
- const auto& d = catalog.State->Procs.FindPtr(id);
- Y_ENSURE(d);
- if (!catalog.State->AllowAllFunctions && !catalog.State->AllowedProcs.contains(d->Name)) {
- throw yexception() << "No access to proc: " << d->Name;
- }
- if (NPrivate::IsExactMatch(d->ArgTypes, d->VariadicType, argTypeIds)) {
- // At most one exact match is possible, so look no further
- // https://www.postgresql.org/docs/14/typeconv-func.html, step 2
- catalog.ExportFunction(d->Name);
- return d;
- }
- // https://www.postgresql.org/docs/14/typeconv-func.html, steps 4.a, 4.c, 4.d
- auto score = NPrivate::CalcProcScore(d->ArgTypes, d->VariadicType, d->DefaultArgs.size(), argTypeIds, catalog);
- if (bestScore < score) {
- bestScore = score;
- candidates.clear();
- candidates.push_back(d);
- } else if (bestScore == score && NPrivate::NoFitScore < score) {
- candidates.push_back(d);
- }
- }
- // check, if it's a form of typecast
- // https://www.postgresql.org/docs/14/typeconv-func.html, step 3
- if (argTypeIds.size() == 1) {
- const auto typeIdPtr = catalog.State->TypeByName.FindPtr(to_lower(name));
- if (typeIdPtr) {
- const auto typePtr = catalog.State->Types.FindPtr(*typeIdPtr);
- Y_ENSURE(typePtr);
- const auto fromTypeId = argTypeIds[0];
- if (fromTypeId == UnknownOid) {
- return typePtr;
- }
- const auto coercionType = NPrivate::FindCoercionPath(fromTypeId, typePtr->TypeId,
- ECoercionCode::Explicit, catalog);
- switch (coercionType) {
- case NPrivate::ECoercionSearchResult::BinaryCompatible:
- return typePtr;
- case NPrivate::ECoercionSearchResult::IOCoerce:
- if (!(fromTypeId == RecordOid /* || TODO: IsComplex */ && typePtr->Category == 'S')) {
- return typePtr;
- }
- default:
- break;
- }
- }
- }
- switch (candidates.size()) {
- case 1:
- // https://www.postgresql.org/docs/14/typeconv-func.html, end of steps 4.a, 4.c or 4.d
- catalog.ExportFunction(candidates[0]->Name);
- return candidates[0];
- case 0:
- NPrivate::ThrowProcNotFound(name, argTypeIds);
- }
- // https://www.postgresql.org/docs/14/typeconv-func.html, step 4.e
- const size_t unknownsCount = std::count(argTypeIds.cbegin(), argTypeIds.cend(), UnknownOid);
- if (0 == unknownsCount) {
- NPrivate::ThrowProcNotFound(name, argTypeIds);
- }
- // https://www.postgresql.org/docs/14/typeconv-funcr.html, step 4.e
- candidates = NPrivate::TryResolveUnknownsByCategory<TProcDesc>(candidates, argTypeIds, catalog);
- if (1 == candidates.size()) {
- // https://www.postgresql.org/docs/14/typeconv-func.html, end of step 4.e
- catalog.ExportFunction(candidates[0]->Name);
- return candidates[0];
- }
- // https://www.postgresql.org/docs/14/typeconv-func.html, step 4.f
- if (unknownsCount < argTypeIds.size()) {
- ui32 commonType = UnknownOid;
- for (const auto argType: argTypeIds) {
- if (argType == UnknownOid) {
- continue;
- }
- if (commonType == UnknownOid) {
- commonType = argType;
- continue;
- }
- if (argType != commonType) {
- commonType = UnknownOid;
- break;
- }
- }
- if (commonType != UnknownOid) {
- const TProcDesc* finalCandidate = nullptr;
- for (const auto* candidate : candidates) {
- for (size_t i = 0; i < argTypeIds.size(); ++i) {
- if (NPrivate::IsCoercible(commonType, i >= candidate->ArgTypes.size() ? candidate->VariadicType : candidate->ArgTypes[i], ECoercionCode::Implicit, catalog)) {
- if (finalCandidate) {
- NPrivate::ThrowProcAmbiguity(name, argTypeIds);
- }
- finalCandidate = candidate;
- }
- }
- }
- if (finalCandidate) {
- catalog.ExportFunction(finalCandidate->Name);
- return finalCandidate;
- }
- }
- }
- NPrivate::ThrowProcNotFound(name, argTypeIds);
- }
- TMaybe<TIssue> LookupCommonType(const TVector<ui32>& typeIds, const std::function<TPosition(size_t i)>& GetPosition, const TTypeDesc*& typeDesc, bool& castsNeeded) {
- Y_ENSURE(0 != typeIds.size());
- const auto& catalog = TCatalog::Instance();
- size_t unknownsCnt = (typeIds[0] == UnknownOid || typeIds[0] == InvalidOid) ? 1 : 0;
- castsNeeded = (unknownsCnt != 0);
- const TTypeDesc* commonType = nullptr;
- char commonCategory = 0;
- if (typeIds[0] != InvalidOid) {
- commonType = &LookupType(typeIds[0]);
- commonCategory = commonType->Category;
- }
- size_t i = 1;
- for (auto typeId = typeIds.cbegin() + 1; typeId != typeIds.cend(); ++typeId, ++i) {
- if (*typeId == UnknownOid || *typeId == InvalidOid) {
- ++unknownsCnt;
- castsNeeded = true;
- continue;
- }
- if (commonType && *typeId == commonType->TypeId) {
- continue;
- }
- const TTypeDesc& otherType = LookupType(*typeId);
- if (!commonType || commonType->TypeId == UnknownOid) {
- commonType = &otherType;
- commonCategory = otherType.Category;
- continue;
- }
- if (otherType.Category != commonCategory) {
- // https://www.postgresql.org/docs/14/typeconv-union-case.html, step 4
- return TIssue(GetPosition(i), TStringBuilder() << "Cannot infer common type for types "
- << commonType->TypeId << " and " << otherType.TypeId);
- }
- castsNeeded = true;
- if (NPrivate::CanCastImplicitly(otherType.TypeId, commonType->TypeId, catalog)) {
- continue;
- }
- if (commonType->IsPreferred || !NPrivate::CanCastImplicitly(commonType->TypeId, otherType.TypeId, catalog)) {
- return TIssue(GetPosition(i), TStringBuilder() << "Cannot infer common type for types "
- << commonType->TypeId << " and " << otherType.TypeId);
- }
- commonType = &otherType;
- }
- // https://www.postgresql.org/docs/14/typeconv-union-case.html, step 3
- if (unknownsCnt == typeIds.size()) {
- castsNeeded = true;
- typeDesc = &LookupType("text");
- } else {
- typeDesc = commonType;
- }
- return {};
- }
- TMaybe<TIssue> LookupCommonType(const TVector<ui32>& typeIds, const std::function<TPosition(size_t i)>&GetPosition, const TTypeDesc*& typeDesc) {
- bool _;
- return LookupCommonType(typeIds, GetPosition, typeDesc, _);
- }
- const TOperDesc& LookupOper(const TString& name, const TVector<ui32>& argTypeIds) {
- const auto& catalog = TCatalog::Instance();
- auto operIdPtr = catalog.State->OperatorsByName.FindPtr(to_lower(name));
- if (!operIdPtr) {
- throw yexception() << "No such operator: " << name;
- }
- EOperKind expectedOpKind;
- std::function<ui64(const TOperDesc*)> calcScore;
- switch (argTypeIds.size()) {
- case 2:
- expectedOpKind = EOperKind::Binary;
- calcScore = [&] (const auto* d) {
- return NPrivate::CalcBinaryOperatorScore(*d, argTypeIds[0], argTypeIds[1], catalog);
- };
- break;
- case 1:
- expectedOpKind = EOperKind::LeftUnary;
- calcScore = [&] (const auto* d) {
- return NPrivate::CalcUnaryOperatorScore(*d, argTypeIds[0], catalog);
- };
- break;
- default:
- throw yexception() << "Operator's number of arguments should be 1 or 2, got: " << argTypeIds.size();
- }
- auto bestScore = NPrivate::NoFitScore;
- TVector<const TOperDesc*> candidates;
- const ui64 maxPossibleScore = NPrivate::ArgExactTypeMatch * argTypeIds.size();
- for (const auto& operId : *operIdPtr) {
- const auto& oper = catalog.State->Operators.FindPtr(operId);
- Y_ENSURE(oper);
- if (expectedOpKind != oper->Kind) {
- continue;
- }
- auto score = calcScore(oper);
- if (maxPossibleScore == score) {
- // The only exact match is possible, so look no further
- // https://www.postgresql.org/docs/14/typeconv-oper.html, step 2
- return *oper;
- }
- // https://www.postgresql.org/docs/14/typeconv-oper.html, steps 3.a, 3.c, 3.d
- if (bestScore < score) {
- bestScore = score;
- candidates.clear();
- candidates.push_back(oper);
- } else if (bestScore == score && NPrivate::NoFitScore < score) {
- candidates.push_back(oper);
- }
- }
- switch (candidates.size()) {
- case 1:
- // https://www.postgresql.org/docs/14/typeconv-oper.html, end of steps 3.a, 3.c or 3.d
- return *candidates[0];
- case 0:
- NPrivate::ThrowOperatorNotFound(name, argTypeIds);
- }
- if (!(argTypeIds[0] == UnknownOid || (2 == argTypeIds.size() && argTypeIds[1] == UnknownOid))) {
- NPrivate::ThrowOperatorNotFound(name, argTypeIds);
- }
- // https://www.postgresql.org/docs/14/typeconv-oper.html, step 3.e
- candidates = NPrivate::TryResolveUnknownsByCategory<TOperDesc>(candidates, argTypeIds, catalog);
- if (1 == candidates.size()) {
- // https://www.postgresql.org/docs/14/typeconv-oper.html, end of step 3.e
- return *candidates[0];
- }
- // https://www.postgresql.org/docs/14/typeconv-oper.html, step 3.f
- if (EOperKind::LeftUnary == expectedOpKind) {
- NPrivate::ThrowOperatorNotFound(name, argTypeIds);
- }
- auto TryResolveUnknownsBySpreadingType = [&] (ui32 argTypeId, std::function<ui32(const TOperDesc*)> getArgType) {
- const TOperDesc* finalCandidate = nullptr;
- for (const auto* candidate : candidates) {
- if (NPrivate::IsCoercible(argTypeId, getArgType(candidate), ECoercionCode::Implicit, catalog)) {
- if (finalCandidate) {
- NPrivate::ThrowOperatorAmbiguity(name, argTypeIds);
- }
- finalCandidate = candidate;
- }
- }
- return finalCandidate;
- };
- const TOperDesc* finalCandidate = nullptr;
- if (argTypeIds[0] == UnknownOid) {
- finalCandidate = TryResolveUnknownsBySpreadingType(argTypeIds[1], [&] (const auto* oper) { return oper->LeftType; });
- } else if (argTypeIds[1] == UnknownOid) {
- finalCandidate = TryResolveUnknownsBySpreadingType(argTypeIds[0], [&] (const auto* oper) { return oper->RightType; });
- }
- if (finalCandidate) {
- return *finalCandidate;
- }
- NPrivate::ThrowOperatorNotFound(name, argTypeIds);
- }
- const TOperDesc& LookupOper(ui32 operId, const TVector<ui32>& argTypeIds) {
- const auto& catalog = TCatalog::Instance();
- auto operPtr = catalog.State->Operators.FindPtr(operId);
- if (!operPtr) {
- throw yexception() << "No such oper: " << operId;
- }
- if (!ValidateOperArgs(*operPtr, argTypeIds, catalog.State->Types)) {
- throw yexception() << "Unable to find an overload for operator with oid " << operId << " with given argument types: "
- << ArgTypesList(argTypeIds);
- }
- return *operPtr;
- }
- const TOperDesc& LookupOper(ui32 operId) {
- const auto& catalog = TCatalog::Instance();
- auto operPtr = catalog.State->Operators.FindPtr(operId);
- if (!operPtr) {
- throw yexception() << "No such oper: " << operId;
- }
- return *operPtr;
- }
- bool HasAggregation(const TString& name, EAggKind kind) {
- const auto& catalog = TCatalog::Instance();
- auto aggIdPtr = catalog.State->AggregationsByName.FindPtr(to_lower(name));
- if (!aggIdPtr) {
- return false;
- }
- for (const auto& id : *aggIdPtr) {
- const auto& d = catalog.State->Aggregations.FindPtr(id);
- Y_ENSURE(d);
- if (d->Kind == kind) {
- return true;
- }
- }
- return false;
- }
- bool ValidateAggregateArgs(const TAggregateDesc& d, const TVector<ui32>& argTypeIds) {
- const auto& catalog = TCatalog::Instance();
- return ValidateArgs(d.ArgTypes, argTypeIds, catalog.State->Types);
- }
- bool ValidateAggregateArgs(const TAggregateDesc& d, ui32 stateType, ui32 resultType) {
- auto expectedStateType = LookupProc(d.SerializeFuncId ? d.SerializeFuncId : d.TransFuncId).ResultType;
- if (stateType != expectedStateType) {
- return false;
- }
- auto expectedResultType = LookupProc(d.FinalFuncId ? d.FinalFuncId : d.TransFuncId).ResultType;
- if (resultType != expectedResultType) {
- return false;
- }
- return true;
- }
- const TAggregateDesc& LookupAggregation(const TString& name, const TVector<ui32>& argTypeIds) {
- const auto& catalog = TCatalog::Instance();
- auto aggIdPtr = catalog.State->AggregationsByName.FindPtr(to_lower(name));
- if (!aggIdPtr) {
- throw yexception() << "No such aggregate: " << name;
- }
- auto bestScore = NPrivate::NoFitScore;
- TVector<const TAggregateDesc*> candidates;
- for (const auto& id : *aggIdPtr) {
- const auto& d = catalog.State->Aggregations.FindPtr(id);
- Y_ENSURE(d);
- if (NPrivate::IsExactMatch(d->ArgTypes, 0, argTypeIds)) {
- // At most one exact match is possible, so look no further
- // https://www.postgresql.org/docs/14/typeconv-func.html, step 2
- return *d;
- }
- // https://www.postgresql.org/docs/14/typeconv-func.html, steps 4.a, 4.c, 4.d
- auto score = NPrivate::CalcProcScore(d->ArgTypes, 0, 0, argTypeIds, catalog);
- if (bestScore < score) {
- bestScore = score;
- candidates.clear();
- candidates.push_back(d);
- } else if (bestScore == score && NPrivate::NoFitScore < score) {
- candidates.push_back(d);
- }
- }
- switch (candidates.size()) {
- case 1:
- // https://www.postgresql.org/docs/14/typeconv-func.html, end of steps 4.a, 4.c or 4.d
- return *candidates[0];
- case 0:
- NPrivate::ThrowAggregateNotFound(name, argTypeIds);
- }
- // https://www.postgresql.org/docs/14/typeconv-func.html, step 4.e
- const size_t unknownsCount = std::count(argTypeIds.cbegin(), argTypeIds.cend(), UnknownOid);
- if (0 == unknownsCount) {
- NPrivate::ThrowAggregateNotFound(name, argTypeIds);
- }
- // https://www.postgresql.org/docs/14/typeconv-funcr.html, step 4.e
- candidates = NPrivate::TryResolveUnknownsByCategory<TAggregateDesc>(candidates, argTypeIds, catalog);
- if (1 == candidates.size()) {
- // https://www.postgresql.org/docs/14/typeconv-func.html, end of step 4.e
- return *candidates[0];
- }
- // https://www.postgresql.org/docs/14/typeconv-func.html, step 4.f
- if (unknownsCount < argTypeIds.size()) {
- ui32 commonType = UnknownOid;
- for (const auto argType: argTypeIds) {
- if (argType == UnknownOid) {
- continue;
- }
- if (commonType == UnknownOid) {
- commonType = argType;
- continue;
- }
- if (argType != commonType) {
- commonType = UnknownOid;
- break;
- }
- }
- if (commonType != UnknownOid) {
- const TAggregateDesc* finalCandidate = nullptr;
- for (const auto* candidate : candidates) {
- for (size_t i = 0; i < argTypeIds.size(); ++i) {
- if (NPrivate::IsCoercible(commonType, candidate->ArgTypes[i], ECoercionCode::Implicit, catalog)) {
- if (finalCandidate) {
- NPrivate::ThrowAggregateAmbiguity(name, argTypeIds);
- }
- finalCandidate = candidate;
- }
- }
- }
- if (finalCandidate) {
- return *finalCandidate;
- }
- }
- }
- NPrivate::ThrowAggregateNotFound(name, argTypeIds);
- }
- const TAggregateDesc& LookupAggregation(const TString& name, ui32 stateType, ui32 resultType) {
- TStringBuf realName = name;
- TMaybe<ui32> aggId;
- TStringBuf left, right;
- if (realName.TrySplit('#', left, right)) {
- aggId = FromString<ui32>(right);
- realName = left;
- }
- const auto& catalog = TCatalog::Instance();
- auto aggIdPtr = catalog.State->AggregationsByName.FindPtr(to_lower(TString(realName)));
- if (!aggIdPtr) {
- throw yexception() << "No such aggregate: " << name;
- }
- for (const auto& id : *aggIdPtr) {
- const auto& d = catalog.State->Aggregations.FindPtr(id);
- Y_ENSURE(d);
- if (aggId && d->AggId != *aggId) {
- continue;
- }
- if (!ValidateAggregateArgs(*d, stateType, resultType)) {
- continue;
- }
- return *d;
- }
- throw yexception() << "Unable to find an overload for aggregate " << name << " with given state type: " <<
- NPg::LookupType(stateType).Name << " and result type: " <<
- NPg::LookupType(resultType).Name;
- }
- void EnumAggregation(std::function<void(ui32, const TAggregateDesc&)> f) {
- const auto& catalog = TCatalog::Instance();
- for (const auto& x : catalog.State->Aggregations) {
- f(x.first, x.second);
- }
- }
- bool HasOpClass(EOpClassMethod method, ui32 typeId) {
- const auto& catalog = TCatalog::Instance();
- return catalog.State->OpClasses.contains(std::make_pair(method, typeId));
- }
- const TOpClassDesc* LookupDefaultOpClass(EOpClassMethod method, ui32 typeId) {
- const auto& catalog = TCatalog::Instance();
- auto lookupId = (typeId == VarcharOid ? TextOid : typeId);
- const auto opClassPtr = catalog.State->OpClasses.FindPtr(std::make_pair(method, lookupId));
- if (opClassPtr)
- return opClassPtr;
- throw yexception() << "No such opclass";
- // TODO: support binary coercible and preferred types as define in PG's GetDefaultOpClass()
- }
- bool HasAmOp(ui32 familyId, ui32 strategy, ui32 leftType, ui32 rightType) {
- const auto &catalog = TCatalog::Instance();
- return catalog.State->AmOps.contains(std::make_tuple(familyId, strategy, leftType, rightType));
- }
- const TAmOpDesc& LookupAmOp(ui32 familyId, ui32 strategy, ui32 leftType, ui32 rightType) {
- const auto& catalog = TCatalog::Instance();
- const auto amOpPtr = catalog.State->AmOps.FindPtr(std::make_tuple(familyId, strategy, leftType, rightType));
- if (!amOpPtr) {
- throw yexception() << "No such amop";
- }
- return *amOpPtr;
- }
- bool HasAmProc(ui32 familyId, ui32 num, ui32 leftType, ui32 rightType) {
- const auto &catalog = TCatalog::Instance();
- return catalog.State->AmProcs.contains(std::make_tuple(familyId, num, leftType, rightType));
- }
- const TAmProcDesc& LookupAmProc(ui32 familyId, ui32 num, ui32 leftType, ui32 rightType) {
- const auto& catalog = TCatalog::Instance();
- auto amProcPtr = catalog.State->AmProcs.FindPtr(std::make_tuple(familyId, num, leftType, rightType));
- if (!amProcPtr) {
- throw yexception() << "No such amproc";
- }
- return *amProcPtr;
- }
- bool HasConversion(const TString& from, const TString& to) {
- const auto &catalog = TCatalog::Instance();
- return catalog.State->Conversions.contains(std::make_pair(from, to));
- }
- const TConversionDesc& LookupConversion(const TString& from, const TString& to) {
- const auto& catalog = TCatalog::Instance();
- auto convPtr = catalog.State->Conversions.FindPtr(std::make_pair(from, to));
- if (!convPtr) {
- throw yexception() << "No such conversion from " << from << " to " << to;
- }
- return *convPtr;
- }
- bool IsCompatibleTo(ui32 actualType, ui32 expectedType) {
- const auto& catalog = TCatalog::Instance();
- return IsCompatibleTo(actualType, expectedType, catalog.State->Types);
- }
- const TLanguageDesc& LookupLanguage(ui32 langId) {
- const auto& catalog = TCatalog::Instance();
- auto langPtr = catalog.State->Languages.FindPtr(langId);
- if (!langPtr) {
- throw yexception() << "No such lang: " << langId;
- }
- return *langPtr;
- }
- void EnumLanguages(std::function<void(ui32, const TLanguageDesc&)> f) {
- const auto& catalog = TCatalog::Instance();
- for (const auto& x : catalog.State->Languages) {
- f(x.first, x.second);
- }
- }
- const TVector<TTableInfo>& GetStaticTables() {
- const auto& catalog = TCatalog::Instance();
- return catalog.State->AllStaticTables;
- }
- const THashMap<TTableInfoKey, TVector<TColumnInfo>>& GetStaticColumns() {
- const auto& catalog = TCatalog::Instance();
- return catalog.State->StaticColumns;
- }
- const TTableInfo& LookupStaticTable(const TTableInfoKey& tableKey) {
- const auto& catalog = TCatalog::Instance();
- auto tablePtr = catalog.State->StaticTables.FindPtr(tableKey);
- if (!tablePtr) {
- throw yexception() << "No such table: " << tableKey.Schema << "." << tableKey.Name;
- }
- return *tablePtr;
- }
- const TVector<TMaybe<TString>>* ReadTable(
- const TTableInfoKey& tableKey,
- const TVector<TString>& columnNames,
- size_t* columnsRemap, // should have the same length as columnNames
- size_t& rowStep) {
- const auto& catalog = TCatalog::Instance();
- auto dataPtr = catalog.State->StaticTablesData.FindPtr(tableKey);
- if (!dataPtr) {
- throw yexception() << "Missing data for table "
- << tableKey.Schema << "." << tableKey.Name;
- }
- const auto& allColumns = *catalog.State->StaticColumns.FindPtr(tableKey);
- THashMap<TString, size_t> columnsToIndex;
- for (size_t i = 0; i < allColumns.size(); ++i) {
- Y_ENSURE(columnsToIndex.emplace(allColumns[i].Name,i).second);
- }
- rowStep = allColumns.size();
- for (size_t i = 0; i < columnNames.size(); ++i) {
- auto indexPtr = columnsToIndex.FindPtr(columnNames[i]);
- if (!indexPtr) {
- throw yexception() << "Missing column " << columnNames[i] << " in table "
- << tableKey.Schema << "." << tableKey.Name;
- }
- columnsRemap[i] = *indexPtr;
- }
- return dataPtr;
- }
- bool AreAllFunctionsAllowed() {
- const auto& catalog = TCatalog::Instance();
- return catalog.State->AllowAllFunctions;
- }
- void AllowFunction(const TString& name) {
- auto& catalog = TCatalog::MutableInstance();
- if (!catalog.State->AllowAllFunctions) {
- catalog.State->AllowedProcs.insert(name);
- }
- }
- struct TSqlLanguageParserHolder {
- std::unique_ptr<ISqlLanguageParser> Parser;
- };
- void SetSqlLanguageParser(std::unique_ptr<ISqlLanguageParser> parser) {
- Singleton<TSqlLanguageParserHolder>()->Parser = std::move(parser);
- }
- ISqlLanguageParser* GetSqlLanguageParser() {
- return Singleton<TSqlLanguageParserHolder>()->Parser.get();
- }
- void LoadSystemFunctions(ISystemFunctionsParser& parser) {
- YQL_PROFILE_FUNC(DEBUG);
- auto& catalog = TCatalog::MutableInstance();
- with_lock (catalog.ExtensionsGuard) {
- if (catalog.State->SystemFunctionInit) {
- return;
- }
- TString data;
- Y_ENSURE(NResource::FindExact("system_functions.sql", &data));
- TVector<TProcDesc> procs;
- parser.Parse(data, procs);
- for (const auto& p : procs) {
- auto procIdPtr = catalog.State->ProcByName.FindPtr(p.Name);
- Y_ENSURE(procIdPtr);
- TProcDesc* foundProc = nullptr;
- for (auto procId : *procIdPtr) {
- auto procPtr = catalog.State->Procs.FindPtr(procId);
- Y_ENSURE(procPtr);
- if (procPtr->ArgTypes == p.ArgTypes && procPtr->VariadicType == p.VariadicType) {
- foundProc = procPtr;
- break;
- }
- }
- Y_ENSURE(foundProc);
- foundProc->DefaultArgs = p.DefaultArgs;
- foundProc->Src = p.Src;
- foundProc->ExprNode = p.ExprNode;
- }
- catalog.State->SystemFunctionInit = true;
- }
- }
- void RegisterExtensions(const TVector<TExtensionDesc>& extensions, bool typesOnly,
- IExtensionSqlParser& parser, IExtensionLoader* loader) {
- YQL_PROFILE_FUNC(DEBUG);
- if (extensions.size() > MaximumExtensionsCount) {
- throw yexception() << "Too many extensions: " << extensions.size();
- }
- auto& catalog = TCatalog::MutableInstance();
- with_lock (catalog.ExtensionsGuard) {
- Y_ENSURE(!catalog.ExtensionsInit);
- auto savedAllowAllFunctions = catalog.State->AllowAllFunctions;
- catalog.State->AllowAllFunctions = true;
- for (ui32 i = 0; i < extensions.size(); ++i) {
- auto e = extensions[i];
- e.TypesOnly = e.TypesOnly || typesOnly;
- if (e.Name.empty()) {
- throw yexception() << "Empty extension name";
- }
- if (!catalog.State->ExtensionsByName.insert(std::make_pair(e.Name, i + 1)).second) {
- throw yexception() << "Duplicated extension name: " << e.Name;
- }
- if (!catalog.State->ExtensionsByInstallName.insert(std::make_pair(e.InstallName, i + 1)).second) {
- throw yexception() << "Duplicated extension install name: " << e.InstallName;
- }
- if (e.LibraryMD5.empty() && !e.LibraryPath.empty()) {
- e.LibraryMD5 = MD5::File(e.LibraryPath);
- }
- catalog.State->Extensions.push_back(e);
- TVector<TString> sqls;
- for (const auto& p : e.SqlPaths) {
- TString sql = TFileInput(p).ReadAll();
- sqls.push_back(sql);
- }
- parser.Parse(i + 1, sqls, catalog);
- if (loader && !e.TypesOnly && !e.LibraryPath.empty()) {
- loader->Load(i + 1, e.Name, e.LibraryPath);
- }
- }
- catalog.State->AllowAllFunctions = savedAllowAllFunctions;
- catalog.ExtensionsInit = true;
- }
- }
- TString ExportExtensions(const TMaybe<TSet<ui32>>& filter) {
- auto& catalog = TCatalog::Instance();
- if (catalog.State->Extensions.empty()) {
- return TString();
- }
- NProto::TPgCatalog proto;
- for (ui32 i = 0; i < catalog.State->Extensions.size(); ++i) {
- const auto& ext = catalog.State->Extensions[i];
- const bool skip = filter && !filter->contains(i + 1);
- auto protoExt = proto.AddExtension();
- protoExt->SetName(ext.Name);
- protoExt->SetInstallName(ext.InstallName);
- protoExt->SetTypesOnly(skip);
- if (!skip && !ext.LibraryPath.empty()) {
- protoExt->SetLibraryPath(TFsPath(".") / TFsPath(ext.LibraryPath).GetName());
- protoExt->SetLibraryMD5(ext.LibraryMD5);
- }
- }
- TVector<ui32> extTypes;
- for (const auto& t : catalog.State->Types) {
- const auto& desc = t.second;
- if (!desc.ExtensionIndex) {
- continue;
- }
- extTypes.push_back(t.first);
- }
- Sort(extTypes);
- for (const auto t : extTypes) {
- const auto& desc = *catalog.State->Types.FindPtr(t);
- auto protoType = proto.AddType();
- protoType->SetTypeId(desc.TypeId);
- protoType->SetName(desc.Name);
- protoType->SetExtensionIndex(desc.ExtensionIndex);
- protoType->SetCategory(desc.Category);
- protoType->SetTypeLen(desc.TypeLen);
- protoType->SetPassByValue(desc.PassByValue);
- protoType->SetTypeAlign(desc.TypeAlign);
- protoType->SetElementTypeId(desc.ElementTypeId);
- protoType->SetArrayTypeId(desc.ArrayTypeId);
- if (desc.InFuncId) {
- protoType->SetInFuncId(desc.InFuncId);
- }
- if (desc.OutFuncId) {
- protoType->SetOutFuncId(desc.OutFuncId);
- }
- if (desc.SendFuncId) {
- protoType->SetSendFuncId(desc.SendFuncId);
- }
- if (desc.ReceiveFuncId) {
- protoType->SetReceiveFuncId(desc.ReceiveFuncId);
- }
- if (desc.TypeModInFuncId) {
- protoType->SetTypeModInFuncId(desc.TypeModInFuncId);
- }
- if (desc.TypeModOutFuncId) {
- protoType->SetTypeModOutFuncId(desc.TypeModOutFuncId);
- }
- if (desc.TypeSubscriptFuncId) {
- protoType->SetTypeSubscriptFuncId(desc.TypeSubscriptFuncId);
- }
- if (desc.LessProcId) {
- protoType->SetLessProcId(desc.LessProcId);
- }
- if (desc.EqualProcId) {
- protoType->SetEqualProcId(desc.EqualProcId);
- }
- if (desc.CompareProcId) {
- protoType->SetCompareProcId(desc.CompareProcId);
- }
- if (desc.HashProcId) {
- protoType->SetHashProcId(desc.HashProcId);
- }
- }
- TVector<ui32> extProcs;
- for (const auto& p : catalog.State->Procs) {
- const auto& desc = p.second;
- if (!desc.ExtensionIndex) {
- continue;
- }
- extProcs.push_back(p.first);
- }
- Sort(extProcs);
- for (const auto p : extProcs) {
- const auto& desc = *catalog.State->Procs.FindPtr(p);
- auto protoProc = proto.AddProc();
- protoProc->SetProcId(desc.ProcId);
- protoProc->SetName(desc.Name);
- protoProc->SetExtensionIndex(desc.ExtensionIndex);
- protoProc->SetSrc(desc.Src);
- for (const auto t : desc.ArgTypes) {
- protoProc->AddArgType(t);
- }
- for (const auto t : desc.OutputArgTypes) {
- protoProc->AddOutputArgType(t);
- }
- protoProc->SetVariadicType(desc.VariadicType);
- protoProc->SetVariadicArgType(desc.VariadicArgType);
- for (const auto& name : desc.InputArgNames) {
- protoProc->AddInputArgName(name);
- }
- for (const auto& name : desc.OutputArgNames) {
- protoProc->AddOutputArgName(name);
- }
- protoProc->SetVariadicArgName(desc.VariadicArgName);
- for (const auto& d : desc.DefaultArgs) {
- protoProc->AddDefaultArgNull(!d.Defined());
- protoProc->AddDefaultArgValue(d ? *d : "");
- }
- protoProc->SetIsStrict(desc.IsStrict);
- protoProc->SetLang(desc.Lang);
- protoProc->SetResultType(desc.ResultType);
- protoProc->SetReturnSet(desc.ReturnSet);
- protoProc->SetKind((ui32)desc.Kind);
- }
- TVector<TTableInfoKey> extTables;
- for (const auto& t : catalog.State->StaticTables) {
- if (!t.second.ExtensionIndex) {
- continue;
- }
- extTables.push_back(t.first);
- }
- Sort(extTables);
- for (const auto& key : extTables) {
- const auto& table = *catalog.State->StaticTables.FindPtr(key);
- auto protoTable = proto.AddTable();
- protoTable->SetOid(table.Oid);
- protoTable->SetSchema(table.Schema);
- protoTable->SetName(table.Name);
- protoTable->SetExtensionIndex(table.ExtensionIndex);
- const auto columnsPtr = catalog.State->StaticColumns.FindPtr(key);
- Y_ENSURE(columnsPtr);
- for (const auto& c : *columnsPtr) {
- protoTable->AddColumn(c.Name);
- protoTable->AddUdtType(c.UdtType);
- }
- const auto dataPtr = catalog.State->StaticTablesData.FindPtr(key);
- if (dataPtr) {
- for (const auto& v : *dataPtr) {
- if (v.Defined()) {
- protoTable->AddDataNull(false);
- protoTable->AddDataValue(*v);
- } else {
- protoTable->AddDataNull(true);
- protoTable->AddDataValue("");
- }
- }
- }
- }
- TVector<ui32> extCasts;
- for (const auto& c : catalog.State->Casts) {
- const auto& desc = c.second;
- if (!desc.ExtensionIndex) {
- continue;
- }
- extCasts.push_back(c.first);
- }
- Sort(extCasts);
- for (const auto p : extCasts) {
- const auto& desc = *catalog.State->Casts.FindPtr(p);
- auto protoCast = proto.AddCast();
- protoCast->SetId(p);
- protoCast->SetSourceId(desc.SourceId);
- protoCast->SetTargetId(desc.TargetId);
- protoCast->SetExtensionIndex(desc.ExtensionIndex);
- protoCast->SetMethod((ui32)desc.Method);
- protoCast->SetFunctionId(desc.FunctionId);
- protoCast->SetCoercionCode((ui32)desc.CoercionCode);
- }
- TVector<ui32> extOpers;
- for (const auto& o : catalog.State->Operators) {
- const auto& desc = o.second;
- if (!desc.ExtensionIndex) {
- continue;
- }
- extOpers.push_back(o.first);
- }
- Sort(extOpers);
- for (const auto o : extOpers) {
- const auto& desc = *catalog.State->Operators.FindPtr(o);
- auto protoOper = proto.AddOper();
- protoOper->SetOperId(o);
- protoOper->SetName(desc.Name);
- protoOper->SetExtensionIndex(desc.ExtensionIndex);
- protoOper->SetLeftType(desc.LeftType);
- protoOper->SetRightType(desc.RightType);
- protoOper->SetKind((ui32)desc.Kind);
- protoOper->SetProcId(desc.ProcId);
- protoOper->SetResultType(desc.ResultType);
- protoOper->SetComId(desc.ComId);
- protoOper->SetNegateId(desc.NegateId);
- }
- TVector<ui32> extAggs;
- for (const auto& a : catalog.State->Aggregations) {
- const auto& desc = a.second;
- if (!desc.ExtensionIndex) {
- continue;
- }
- extAggs.push_back(a.first);
- }
- Sort(extAggs);
- for (const auto a : extAggs) {
- const auto& desc = *catalog.State->Aggregations.FindPtr(a);
- auto protoAggregation = proto.AddAggregation();
- protoAggregation->SetAggId(a);
- protoAggregation->SetName(desc.Name);
- protoAggregation->SetExtensionIndex(desc.ExtensionIndex);
- for (const auto argType : desc.ArgTypes) {
- protoAggregation->AddArgType(argType);
- }
- protoAggregation->SetKind((ui32)desc.Kind);
- protoAggregation->SetTransTypeId(desc.TransTypeId);
- protoAggregation->SetTransFuncId(desc.TransFuncId);
- protoAggregation->SetFinalFuncId(desc.FinalFuncId);
- protoAggregation->SetCombineFuncId(desc.CombineFuncId);
- protoAggregation->SetSerializeFuncId(desc.SerializeFuncId);
- protoAggregation->SetDeserializeFuncId(desc.DeserializeFuncId);
- protoAggregation->SetInitValue(desc.InitValue);
- protoAggregation->SetFinalExtra(desc.FinalExtra);
- protoAggregation->SetNumDirectArgs(desc.NumDirectArgs);
- }
- TVector<TString> extOpFamilies;
- for (const auto& f : catalog.State->OpFamilies) {
- const auto& desc = f.second;
- if (!desc.ExtensionIndex) {
- continue;
- }
- extOpFamilies.push_back(f.first);
- }
- Sort(extOpFamilies);
- for (const auto& f : extOpFamilies) {
- const auto& desc = *catalog.State->OpFamilies.FindPtr(f);
- auto protoOpClassFamily = proto.AddOpClassFamily();
- protoOpClassFamily->SetFamilyId(desc.FamilyId);
- protoOpClassFamily->SetName(desc.Name);
- protoOpClassFamily->SetExtensionIndex(desc.ExtensionIndex);
- }
- TVector<std::pair<NPg::EOpClassMethod, ui32>> extOpClasses;
- for (const auto& c : catalog.State->OpClasses) {
- const auto& desc = c.second;
- if (!desc.ExtensionIndex) {
- continue;
- }
- extOpClasses.push_back(c.first);
- }
- for (const auto& c : extOpClasses) {
- const auto& desc = *catalog.State->OpClasses.FindPtr(c);
- auto protoOpClass = proto.AddOpClass();
- protoOpClass->SetMethod((ui32)desc.Method);
- protoOpClass->SetTypeId(desc.TypeId);
- protoOpClass->SetExtensionIndex(desc.ExtensionIndex);
- protoOpClass->SetName(desc.Name);
- protoOpClass->SetFamilyId(desc.FamilyId);
- }
- TVector<std::tuple<ui32, ui32, ui32, ui32>> extAmOps;
- for (const auto& o : catalog.State->AmOps) {
- const auto& desc = o.second;
- if (!desc.ExtensionIndex) {
- continue;
- }
- extAmOps.push_back(o.first);
- }
- for (const auto& o : extAmOps) {
- const auto& desc = *catalog.State->AmOps.FindPtr(o);
- auto protoAmOp = proto.AddAmOp();
- protoAmOp->SetFamilyId(desc.FamilyId);
- protoAmOp->SetStrategy(desc.Strategy);
- protoAmOp->SetLeftType(desc.LeftType);
- protoAmOp->SetRightType(desc.RightType);
- protoAmOp->SetOperId(desc.OperId);
- protoAmOp->SetExtensionIndex(desc.ExtensionIndex);
- }
- TVector<std::tuple<ui32, ui32, ui32, ui32>> extAmProcs;
- for (const auto& p : catalog.State->AmProcs) {
- const auto& desc = p.second;
- if (!desc.ExtensionIndex) {
- continue;
- }
- extAmProcs.push_back(p.first);
- }
- for (const auto& p : extAmProcs) {
- const auto& desc = *catalog.State->AmProcs.FindPtr(p);
- auto protoAmProc = proto.AddAmProc();
- protoAmProc->SetFamilyId(desc.FamilyId);
- protoAmProc->SetProcNum(desc.ProcNum);
- protoAmProc->SetLeftType(desc.LeftType);
- protoAmProc->SetRightType(desc.RightType);
- protoAmProc->SetProcId(desc.ProcId);
- protoAmProc->SetExtensionIndex(desc.ExtensionIndex);
- }
- return proto.SerializeAsString();
- }
- void ImportExtensions(const TString& exported, bool typesOnly, IExtensionLoader* loader) {
- auto& catalog = TCatalog::MutableInstance();
- with_lock (catalog.ExtensionsGuard) {
- Y_ENSURE(!catalog.ExtensionsInit);
- if (exported.empty()) {
- catalog.ExtensionsInit = true;
- return;
- }
- NProto::TPgCatalog proto;
- Y_ENSURE(proto.ParseFromString(exported));
- for (ui32 i = 0; i < proto.ExtensionSize(); ++i) {
- const auto& protoExt = proto.GetExtension(i);
- TExtensionDesc e;
- e.Name = protoExt.GetName();
- e.InstallName = protoExt.GetInstallName();
- e.TypesOnly = protoExt.GetTypesOnly();
- e.LibraryMD5 = protoExt.GetLibraryMD5();
- e.LibraryPath = protoExt.GetLibraryPath();
- catalog.State->Extensions.push_back(e);
- if (!catalog.State->ExtensionsByName.insert(std::make_pair(e.Name, i + 1)).second) {
- throw yexception() << "Duplicated extension name: " << e.Name;
- }
- if (!catalog.State->ExtensionsByInstallName.insert(std::make_pair(e.InstallName, i + 1)).second) {
- throw yexception() << "Duplicated extension install name: " << e.InstallName;
- }
- }
- for (const auto& protoType : proto.GetType()) {
- TTypeDesc desc;
- desc.TypeId = protoType.GetTypeId();
- desc.Name = protoType.GetName();
- desc.ExtensionIndex = protoType.GetExtensionIndex();
- desc.Category = protoType.GetCategory();
- desc.TypeLen = protoType.GetTypeLen();
- desc.PassByValue = protoType.GetPassByValue();
- desc.TypeAlign = protoType.GetTypeAlign();
- desc.ElementTypeId = protoType.GetElementTypeId();
- desc.ArrayTypeId = protoType.GetArrayTypeId();
- desc.InFuncId = protoType.GetInFuncId();
- desc.OutFuncId = protoType.GetOutFuncId();
- desc.SendFuncId = protoType.GetSendFuncId();
- desc.ReceiveFuncId = protoType.GetReceiveFuncId();
- desc.TypeModInFuncId = protoType.GetTypeModInFuncId();
- desc.TypeModOutFuncId = protoType.GetTypeModOutFuncId();
- desc.TypeSubscriptFuncId = protoType.GetTypeSubscriptFuncId();
- desc.LessProcId = protoType.GetLessProcId();
- desc.EqualProcId = protoType.GetEqualProcId();
- desc.CompareProcId = protoType.GetCompareProcId();
- desc.HashProcId = protoType.GetHashProcId();
- Y_ENSURE(catalog.State->Types.emplace(desc.TypeId, desc).second);
- Y_ENSURE(catalog.State->TypeByName.emplace(desc.Name, desc.TypeId).second);
- }
- for (const auto& protoProc : proto.GetProc()) {
- TProcDesc desc;
- desc.ProcId = protoProc.GetProcId();
- desc.Name = protoProc.GetName();
- desc.ExtensionIndex = protoProc.GetExtensionIndex();
- desc.Src = protoProc.GetSrc();
- desc.IsStrict = protoProc.GetIsStrict();
- desc.Lang = protoProc.GetLang();
- desc.ResultType = protoProc.GetResultType();
- desc.ReturnSet = protoProc.GetReturnSet();
- desc.Kind = (EProcKind)protoProc.GetKind();
- for (const auto t : protoProc.GetArgType()) {
- desc.ArgTypes.push_back(t);
- }
- for (const auto t : protoProc.GetOutputArgType()) {
- desc.OutputArgTypes.push_back(t);
- }
- desc.VariadicType = protoProc.GetVariadicType();
- desc.VariadicArgType = protoProc.GetVariadicArgType();
- for (const auto& name : protoProc.GetInputArgName()) {
- desc.InputArgNames.push_back(name);
- }
- for (const auto& name : protoProc.GetOutputArgName()) {
- desc.OutputArgNames.push_back(name);
- }
- desc.VariadicArgName = protoProc.GetVariadicArgName();
- Y_ENSURE(protoProc.DefaultArgNullSize() == protoProc.DefaultArgValueSize());
- for (ui32 i = 0; i < protoProc.DefaultArgNullSize(); ++i) {
- if (protoProc.GetDefaultArgNull(i)) {
- desc.DefaultArgs.push_back(Nothing());
- } else {
- desc.DefaultArgs.push_back(protoProc.GetDefaultArgValue(i));
- }
- }
- Y_ENSURE(catalog.State->Procs.emplace(desc.ProcId, desc).second);
- catalog.State->ProcByName[desc.Name].push_back(desc.ProcId);
- }
- for (const auto& protoTable : proto.GetTable()) {
- TTableInfo table;
- table.Oid = protoTable.GetOid();
- table.Schema = protoTable.GetSchema();
- table.Name = protoTable.GetName();
- table.Kind = ERelKind::Relation;
- table.ExtensionIndex = protoTable.GetExtensionIndex();
- catalog.State->AllStaticTables.push_back(table);
- TTableInfoKey key = table;
- Y_ENSURE(catalog.State->StaticTables.emplace(key, table).second);
- Y_ENSURE(protoTable.ColumnSize() > 0);
- Y_ENSURE(protoTable.ColumnSize() == protoTable.UdtTypeSize());
- for (ui32 i = 0; i < protoTable.ColumnSize(); ++i) {
- TColumnInfo columnInfo;
- columnInfo.Schema = table.Schema;
- columnInfo.TableName = table.Name;
- columnInfo.ExtensionIndex = table.ExtensionIndex;
- columnInfo.Name = protoTable.GetColumn(i);
- columnInfo.UdtType = protoTable.GetUdtType(i);
- catalog.State->AllStaticColumns.push_back(columnInfo);
- catalog.State->StaticColumns[key].push_back(columnInfo);
- }
- if (protoTable.DataValueSize() > 0) {
- Y_ENSURE(protoTable.DataValueSize() == protoTable.DataNullSize());
- auto& data = catalog.State->StaticTablesData[key];
- data.reserve(protoTable.DataValueSize());
- for (ui64 i = 0; i < protoTable.DataValueSize(); ++i) {
- if (protoTable.GetDataNull(i)) {
- data.push_back(Nothing());
- } else {
- data.push_back(protoTable.GetDataValue(i));
- }
- }
- }
- }
- for (const auto& protoCast : proto.GetCast()) {
- auto id = protoCast.GetId();
- TCastDesc desc;
- desc.SourceId = protoCast.GetSourceId();
- desc.TargetId = protoCast.GetTargetId();
- desc.ExtensionIndex = protoCast.GetExtensionIndex();
- desc.Method = (ECastMethod)protoCast.GetMethod();
- desc.FunctionId = protoCast.GetFunctionId();
- desc.CoercionCode = (ECoercionCode)protoCast.GetCoercionCode();
- Y_ENSURE(catalog.State->Casts.emplace(id, desc).second);
- Y_ENSURE(catalog.State->CastsByDir.insert(std::make_pair(std::make_pair(desc.SourceId, desc.TargetId), id)).second);
- }
- for (const auto& protoOper : proto.GetOper()) {
- TOperDesc desc;
- desc.OperId = protoOper.GetOperId();
- desc.Name = protoOper.GetName();
- desc.ExtensionIndex = protoOper.GetExtensionIndex();
- desc.LeftType = protoOper.GetLeftType();
- desc.RightType = protoOper.GetRightType();
- desc.Kind = (EOperKind)protoOper.GetKind();
- desc.ProcId = protoOper.GetProcId();
- desc.ResultType = protoOper.GetResultType();
- desc.ComId = protoOper.GetComId();
- desc.NegateId = protoOper.GetNegateId();
- Y_ENSURE(catalog.State->Operators.emplace(desc.OperId, desc).second);
- catalog.State->OperatorsByName[desc.Name].push_back(desc.OperId);
- }
- for (const auto& protoAggregation : proto.GetAggregation()) {
- TAggregateDesc desc;
- desc.AggId = protoAggregation.GetAggId();
- desc.Name = protoAggregation.GetName();
- desc.ExtensionIndex = protoAggregation.GetExtensionIndex();
- for (const auto argType : protoAggregation.GetArgType()) {
- desc.ArgTypes.push_back(argType);
- }
- desc.Kind = (NPg::EAggKind)protoAggregation.GetKind();
- desc.TransTypeId = protoAggregation.GetTransTypeId();
- desc.TransFuncId = protoAggregation.GetTransFuncId();
- desc.FinalFuncId = protoAggregation.GetFinalFuncId();
- desc.CombineFuncId = protoAggregation.GetCombineFuncId();
- desc.SerializeFuncId = protoAggregation.GetSerializeFuncId();
- desc.DeserializeFuncId = protoAggregation.GetDeserializeFuncId();
- desc.InitValue = protoAggregation.GetInitValue();
- desc.FinalExtra = protoAggregation.GetFinalExtra();
- desc.NumDirectArgs = protoAggregation.GetNumDirectArgs();
- Y_ENSURE(catalog.State->Aggregations.emplace(desc.AggId, desc).second);
- catalog.State->AggregationsByName[desc.Name].push_back(desc.AggId);
- }
- THashMap<ui32, TString> opFamiliesByOid;
- for (const auto& protoOpClassFamily : proto.GetOpClassFamily()) {
- TOpFamilyDesc desc;
- desc.FamilyId = protoOpClassFamily.GetFamilyId();
- desc.Name = protoOpClassFamily.GetName();
- desc.ExtensionIndex = protoOpClassFamily.GetExtensionIndex();
- Y_ENSURE(catalog.State->OpFamilies.emplace(desc.Name, desc).second);
- Y_ENSURE(opFamiliesByOid.emplace(desc.FamilyId, desc.Name).second);
- }
- for (const auto& protoOpClass : proto.GetOpClass()) {
- TOpClassDesc desc;
- desc.Method = (EOpClassMethod)protoOpClass.GetMethod();
- desc.TypeId = protoOpClass.GetTypeId();
- desc.ExtensionIndex = protoOpClass.GetExtensionIndex();
- desc.FamilyId = protoOpClass.GetFamilyId();
- desc.Name = protoOpClass.GetName();
- desc.Family = *opFamiliesByOid.FindPtr(desc.FamilyId);
- Y_ENSURE(catalog.State->OpClasses.emplace(std::make_pair(desc.Method, desc.TypeId), desc).second);
- }
- for (const auto& protoAmOp : proto.GetAmOp()) {
- TAmOpDesc desc;
- desc.FamilyId = protoAmOp.GetFamilyId();
- desc.Strategy = protoAmOp.GetStrategy();
- desc.LeftType = protoAmOp.GetLeftType();
- desc.RightType = protoAmOp.GetRightType();
- desc.OperId = protoAmOp.GetOperId();
- desc.ExtensionIndex = protoAmOp.GetExtensionIndex();
- desc.Family = *opFamiliesByOid.FindPtr(desc.FamilyId);
- Y_ENSURE(catalog.State->AmOps.emplace(std::make_tuple(desc.FamilyId, desc.Strategy, desc.LeftType, desc.RightType), desc).second);
- }
- for (const auto& protoAmProc : proto.GetAmProc()) {
- TAmProcDesc desc;
- desc.FamilyId = protoAmProc.GetFamilyId();
- desc.ProcNum = protoAmProc.GetProcNum();
- desc.LeftType = protoAmProc.GetLeftType();
- desc.RightType = protoAmProc.GetRightType();
- desc.ProcId = protoAmProc.GetProcId();
- desc.ExtensionIndex = protoAmProc.GetExtensionIndex();
- desc.Family = *opFamiliesByOid.FindPtr(desc.FamilyId);
- Y_ENSURE(catalog.State->AmProcs.emplace(std::make_tuple(desc.FamilyId, desc.ProcNum, desc.LeftType, desc.RightType), desc).second);
- }
- if (!typesOnly && loader) {
- for (ui32 extensionIndex = 1; extensionIndex <= catalog.State->Extensions.size(); ++extensionIndex) {
- const auto& e = catalog.State->Extensions[extensionIndex - 1];
- if (!e.TypesOnly) {
- loader->Load(extensionIndex, e.Name, e.LibraryPath);
- }
- }
- }
- catalog.State->AllowAllFunctions = true;
- catalog.State->AllowedProcs.clear();
- catalog.ExtensionsInit = true;
- }
- }
- void ClearExtensions() {
- auto& catalog = TCatalog::MutableInstance();
- with_lock (catalog.ExtensionsGuard) {
- if (!catalog.ExtensionsInit) {
- return;
- }
- catalog.Init();
- catalog.ExtensionsInit = false;
- }
- }
- void EnumExtensions(std::function<void(ui32, const TExtensionDesc&)> f) {
- const auto& catalog = TCatalog::Instance();
- for (ui32 i = 0; i < catalog.State->Extensions.size(); ++i) {
- f(i + 1, catalog.State->Extensions[i]);
- }
- }
- const TExtensionDesc& LookupExtension(ui32 extIndex) {
- const auto& catalog = TCatalog::Instance();
- Y_ENSURE(extIndex > 0 && extIndex <= catalog.State->Extensions.size());
- return catalog.State->Extensions[extIndex - 1];
- }
- ui32 LookupExtensionByName(const TString& name) {
- const auto& catalog = TCatalog::Instance();
- auto indexPtr = catalog.State->ExtensionsByName.FindPtr(name);
- if (!indexPtr) {
- throw yexception() << "Unknown extension name: " << name;
- }
- return *indexPtr;
- }
- ui32 LookupExtensionByInstallName(const TString& installName) {
- const auto& catalog = TCatalog::Instance();
- auto indexPtr = catalog.State->ExtensionsByInstallName.FindPtr(installName);
- if (!indexPtr) {
- throw yexception() << "Unknown extension install name: " << installName;
- }
- return *indexPtr;
- }
- }
|