You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

postgres_fdw.c 173KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833
  1. /*-------------------------------------------------------------------------
  2. *
  3. * postgres_fdw.c
  4. * Foreign-data wrapper for remote PostgreSQL servers
  5. *
  6. * Portions Copyright (c) 2012-2019, PostgreSQL Global Development Group
  7. *
  8. * IDENTIFICATION
  9. * contrib/postgres_fdw/postgres_fdw.c
  10. *
  11. *-------------------------------------------------------------------------
  12. */
  13. #include "postgres.h"
  14. #include "postgres_fdw.h"
  15. #include "access/htup_details.h"
  16. #include "access/sysattr.h"
  17. #include "catalog/pg_class.h"
  18. #include "commands/defrem.h"
  19. #include "commands/explain.h"
  20. #include "commands/vacuum.h"
  21. #include "foreign/fdwapi.h"
  22. #include "funcapi.h"
  23. #include "miscadmin.h"
  24. #include "nodes/makefuncs.h"
  25. #include "nodes/nodeFuncs.h"
  26. #include "optimizer/cost.h"
  27. #include "optimizer/clauses.h"
  28. #include "optimizer/pathnode.h"
  29. #include "optimizer/paths.h"
  30. #include "optimizer/planmain.h"
  31. #include "optimizer/restrictinfo.h"
  32. #include "optimizer/var.h"
  33. #include "optimizer/tlist.h"
  34. #include "parser/parsetree.h"
  35. #include "utils/builtins.h"
  36. #include "utils/float.h"
  37. #include "utils/guc.h"
  38. #include "utils/lsyscache.h"
  39. #include "utils/memutils.h"
  40. #include "utils/rel.h"
  41. #include "utils/sampling.h"
  42. #include "utils/selfuncs.h"
  43. PG_MODULE_MAGIC;
  44. /* Default CPU cost to start up a foreign query. */
  45. #define DEFAULT_FDW_STARTUP_COST 100.0
  46. /* Default CPU cost to process 1 row (above and beyond cpu_tuple_cost). */
  47. #define DEFAULT_FDW_TUPLE_COST 0.01
  48. /* If no remote estimates, assume a sort costs 20% extra */
  49. #define DEFAULT_FDW_SORT_MULTIPLIER 1.2
  50. /*
  51. * Indexes of FDW-private information stored in fdw_private lists.
  52. *
  53. * These items are indexed with the enum FdwScanPrivateIndex, so an item
  54. * can be fetched with list_nth(). For example, to get the SELECT statement:
  55. * sql = strVal(list_nth(fdw_private, FdwScanPrivateSelectSql));
  56. */
  57. enum FdwScanPrivateIndex
  58. {
  59. /* SQL statement to execute remotely (as a String node) */
  60. FdwScanPrivateSelectSql,
  61. /* Integer list of attribute numbers retrieved by the SELECT */
  62. FdwScanPrivateRetrievedAttrs,
  63. /* Integer representing the desired fetch_size */
  64. FdwScanPrivateFetchSize,
  65. /*
  66. * String describing join i.e. names of relations being joined and types
  67. * of join, added when the scan is join
  68. */
  69. FdwScanPrivateRelations
  70. };
  71. /*
  72. * Similarly, this enum describes what's kept in the fdw_private list for
  73. * a ModifyTable node referencing a postgres_fdw foreign table. We store:
  74. *
  75. * 1) INSERT/UPDATE/DELETE statement text to be sent to the remote server
  76. * 2) Integer list of target attribute numbers for INSERT/UPDATE
  77. * (NIL for a DELETE)
  78. * 3) Boolean flag showing if the remote query has a RETURNING clause
  79. * 4) Integer list of attribute numbers retrieved by RETURNING, if any
  80. */
  81. enum FdwModifyPrivateIndex
  82. {
  83. /* SQL statement to execute remotely (as a String node) */
  84. FdwModifyPrivateUpdateSql,
  85. /* Integer list of target attribute numbers for INSERT/UPDATE */
  86. FdwModifyPrivateTargetAttnums,
  87. /* has-returning flag (as an integer Value node) */
  88. FdwModifyPrivateHasReturning,
  89. /* Integer list of attribute numbers retrieved by RETURNING */
  90. FdwModifyPrivateRetrievedAttrs
  91. };
  92. /*
  93. * Similarly, this enum describes what's kept in the fdw_private list for
  94. * a ForeignScan node that modifies a foreign table directly. We store:
  95. *
  96. * 1) UPDATE/DELETE statement text to be sent to the remote server
  97. * 2) Boolean flag showing if the remote query has a RETURNING clause
  98. * 3) Integer list of attribute numbers retrieved by RETURNING, if any
  99. * 4) Boolean flag showing if we set the command es_processed
  100. */
  101. enum FdwDirectModifyPrivateIndex
  102. {
  103. /* SQL statement to execute remotely (as a String node) */
  104. FdwDirectModifyPrivateUpdateSql,
  105. /* has-returning flag (as an integer Value node) */
  106. FdwDirectModifyPrivateHasReturning,
  107. /* Integer list of attribute numbers retrieved by RETURNING */
  108. FdwDirectModifyPrivateRetrievedAttrs,
  109. /* set-processed flag (as an integer Value node) */
  110. FdwDirectModifyPrivateSetProcessed
  111. };
  112. /*
  113. * Execution state of a foreign scan using postgres_fdw.
  114. */
  115. typedef struct PgFdwScanState
  116. {
  117. Relation rel; /* relcache entry for the foreign table. NULL
  118. * for a foreign join scan. */
  119. TupleDesc tupdesc; /* tuple descriptor of scan */
  120. AttInMetadata *attinmeta; /* attribute datatype conversion metadata */
  121. /* extracted fdw_private data */
  122. char *query; /* text of SELECT command */
  123. List *retrieved_attrs; /* list of retrieved attribute numbers */
  124. /* for remote query execution */
  125. PGconn *conn; /* connection for the scan */
  126. unsigned int cursor_number; /* quasi-unique ID for my cursor */
  127. bool cursor_exists; /* have we created the cursor? */
  128. int numParams; /* number of parameters passed to query */
  129. FmgrInfo *param_flinfo; /* output conversion functions for them */
  130. List *param_exprs; /* executable expressions for param values */
  131. const char **param_values; /* textual values of query parameters */
  132. /* for storing result tuples */
  133. HeapTuple *tuples; /* array of currently-retrieved tuples */
  134. int num_tuples; /* # of tuples in array */
  135. int next_tuple; /* index of next one to return */
  136. /* batch-level state, for optimizing rewinds and avoiding useless fetch */
  137. int fetch_ct_2; /* Min(# of fetches done, 2) */
  138. bool eof_reached; /* true if last fetch reached EOF */
  139. /* working memory contexts */
  140. MemoryContext batch_cxt; /* context holding current batch of tuples */
  141. MemoryContext temp_cxt; /* context for per-tuple temporary data */
  142. int fetch_size; /* number of tuples per fetch */
  143. } PgFdwScanState;
  144. /*
  145. * Execution state of a foreign insert/update/delete operation.
  146. */
  147. typedef struct PgFdwModifyState
  148. {
  149. Relation rel; /* relcache entry for the foreign table */
  150. AttInMetadata *attinmeta; /* attribute datatype conversion metadata */
  151. /* for remote query execution */
  152. PGconn *conn; /* connection for the scan */
  153. char *p_name; /* name of prepared statement, if created */
  154. /* extracted fdw_private data */
  155. char *query; /* text of INSERT/UPDATE/DELETE command */
  156. List *target_attrs; /* list of target attribute numbers */
  157. bool has_returning; /* is there a RETURNING clause? */
  158. List *retrieved_attrs; /* attr numbers retrieved by RETURNING */
  159. /* info about parameters for prepared statement */
  160. AttrNumber ctidAttno; /* attnum of input resjunk ctid column */
  161. int p_nums; /* number of parameters to transmit */
  162. FmgrInfo *p_flinfo; /* output conversion functions for them */
  163. /* working memory context */
  164. MemoryContext temp_cxt; /* context for per-tuple temporary data */
  165. } PgFdwModifyState;
  166. /*
  167. * Execution state of a foreign scan that modifies a foreign table directly.
  168. */
  169. typedef struct PgFdwDirectModifyState
  170. {
  171. Relation rel; /* relcache entry for the foreign table */
  172. AttInMetadata *attinmeta; /* attribute datatype conversion metadata */
  173. /* extracted fdw_private data */
  174. char *query; /* text of UPDATE/DELETE command */
  175. bool has_returning; /* is there a RETURNING clause? */
  176. List *retrieved_attrs; /* attr numbers retrieved by RETURNING */
  177. bool set_processed; /* do we set the command es_processed? */
  178. /* for remote query execution */
  179. PGconn *conn; /* connection for the update */
  180. int numParams; /* number of parameters passed to query */
  181. FmgrInfo *param_flinfo; /* output conversion functions for them */
  182. List *param_exprs; /* executable expressions for param values */
  183. const char **param_values; /* textual values of query parameters */
  184. /* for storing result tuples */
  185. PGresult *result; /* result for query */
  186. int num_tuples; /* # of result tuples */
  187. int next_tuple; /* index of next one to return */
  188. Relation resultRel; /* relcache entry for the target relation */
  189. AttrNumber *attnoMap; /* array of attnums of input user columns */
  190. AttrNumber ctidAttno; /* attnum of input ctid column */
  191. AttrNumber oidAttno; /* attnum of input oid column */
  192. bool hasSystemCols; /* are there system columns of resultRel? */
  193. /* working memory context */
  194. MemoryContext temp_cxt; /* context for per-tuple temporary data */
  195. } PgFdwDirectModifyState;
  196. /*
  197. * Workspace for analyzing a foreign table.
  198. */
  199. typedef struct PgFdwAnalyzeState
  200. {
  201. Relation rel; /* relcache entry for the foreign table */
  202. AttInMetadata *attinmeta; /* attribute datatype conversion metadata */
  203. List *retrieved_attrs; /* attr numbers retrieved by query */
  204. /* collected sample rows */
  205. HeapTuple *rows; /* array of size targrows */
  206. int targrows; /* target # of sample rows */
  207. int numrows; /* # of sample rows collected */
  208. /* for random sampling */
  209. double samplerows; /* # of rows fetched */
  210. double rowstoskip; /* # of rows to skip before next sample */
  211. ReservoirStateData rstate; /* state for reservoir sampling */
  212. /* working memory contexts */
  213. MemoryContext anl_cxt; /* context for per-analyze lifespan data */
  214. MemoryContext temp_cxt; /* context for per-tuple temporary data */
  215. } PgFdwAnalyzeState;
  216. /*
  217. * Identify the attribute where data conversion fails.
  218. */
  219. typedef struct ConversionLocation
  220. {
  221. Relation rel; /* foreign table's relcache entry. */
  222. AttrNumber cur_attno; /* attribute number being processed, or 0 */
  223. /*
  224. * In case of foreign join push down, fdw_scan_tlist is used to identify
  225. * the Var node corresponding to the error location and
  226. * fsstate->ss.ps.state gives access to the RTEs of corresponding relation
  227. * to get the relation name and attribute name.
  228. */
  229. ForeignScanState *fsstate;
  230. } ConversionLocation;
  231. /* Callback argument for ec_member_matches_foreign */
  232. typedef struct
  233. {
  234. Expr *current; /* current expr, or NULL if not yet found */
  235. List *already_used; /* expressions already dealt with */
  236. } ec_member_foreign_arg;
  237. /*
  238. * SQL functions
  239. */
  240. PG_FUNCTION_INFO_V1(postgres_fdw_handler);
  241. /*
  242. * FDW callback routines
  243. */
  244. static void postgresGetForeignRelSize(PlannerInfo *root,
  245. RelOptInfo *baserel,
  246. Oid foreigntableid);
  247. static void postgresGetForeignPaths(PlannerInfo *root,
  248. RelOptInfo *baserel,
  249. Oid foreigntableid);
  250. static ForeignScan *postgresGetForeignPlan(PlannerInfo *root,
  251. RelOptInfo *foreignrel,
  252. Oid foreigntableid,
  253. ForeignPath *best_path,
  254. List *tlist,
  255. List *scan_clauses,
  256. Plan *outer_plan);
  257. static void postgresBeginForeignScan(ForeignScanState *node, int eflags);
  258. static TupleTableSlot *postgresIterateForeignScan(ForeignScanState *node);
  259. static void postgresReScanForeignScan(ForeignScanState *node);
  260. static void postgresEndForeignScan(ForeignScanState *node);
  261. static void postgresAddForeignUpdateTargets(Query *parsetree,
  262. RangeTblEntry *target_rte,
  263. Relation target_relation);
  264. static List *postgresPlanForeignModify(PlannerInfo *root,
  265. ModifyTable *plan,
  266. Index resultRelation,
  267. int subplan_index);
  268. static void postgresBeginForeignModify(ModifyTableState *mtstate,
  269. ResultRelInfo *resultRelInfo,
  270. List *fdw_private,
  271. int subplan_index,
  272. int eflags);
  273. static TupleTableSlot *postgresExecForeignInsert(EState *estate,
  274. ResultRelInfo *resultRelInfo,
  275. TupleTableSlot *slot,
  276. TupleTableSlot *planSlot);
  277. static TupleTableSlot *postgresExecForeignUpdate(EState *estate,
  278. ResultRelInfo *resultRelInfo,
  279. TupleTableSlot *slot,
  280. TupleTableSlot *planSlot);
  281. static TupleTableSlot *postgresExecForeignDelete(EState *estate,
  282. ResultRelInfo *resultRelInfo,
  283. TupleTableSlot *slot,
  284. TupleTableSlot *planSlot);
  285. static void postgresEndForeignModify(EState *estate,
  286. ResultRelInfo *resultRelInfo);
  287. static void postgresBeginForeignInsert(ModifyTableState *mtstate,
  288. ResultRelInfo *resultRelInfo);
  289. static void postgresEndForeignInsert(EState *estate,
  290. ResultRelInfo *resultRelInfo);
  291. static int postgresIsForeignRelUpdatable(Relation rel);
  292. static bool postgresPlanDirectModify(PlannerInfo *root,
  293. ModifyTable *plan,
  294. Index resultRelation,
  295. int subplan_index);
  296. static void postgresBeginDirectModify(ForeignScanState *node, int eflags);
  297. static TupleTableSlot *postgresIterateDirectModify(ForeignScanState *node);
  298. static void postgresEndDirectModify(ForeignScanState *node);
  299. static void postgresExplainForeignScan(ForeignScanState *node,
  300. ExplainState *es);
  301. static void postgresExplainForeignModify(ModifyTableState *mtstate,
  302. ResultRelInfo *rinfo,
  303. List *fdw_private,
  304. int subplan_index,
  305. ExplainState *es);
  306. static void postgresExplainDirectModify(ForeignScanState *node,
  307. ExplainState *es);
  308. static bool postgresAnalyzeForeignTable(Relation relation,
  309. AcquireSampleRowsFunc *func,
  310. BlockNumber *totalpages);
  311. static List *postgresImportForeignSchema(ImportForeignSchemaStmt *stmt,
  312. Oid serverOid);
  313. static void postgresGetForeignJoinPaths(PlannerInfo *root,
  314. RelOptInfo *joinrel,
  315. RelOptInfo *outerrel,
  316. RelOptInfo *innerrel,
  317. JoinType jointype,
  318. JoinPathExtraData *extra);
  319. static bool postgresRecheckForeignScan(ForeignScanState *node,
  320. TupleTableSlot *slot);
  321. static void postgresGetForeignUpperPaths(PlannerInfo *root,
  322. UpperRelationKind stage,
  323. RelOptInfo *input_rel,
  324. RelOptInfo *output_rel,
  325. void *extra);
  326. /*
  327. * Helper functions
  328. */
  329. static void estimate_path_cost_size(PlannerInfo *root,
  330. RelOptInfo *foreignrel,
  331. List *param_join_conds,
  332. List *pathkeys,
  333. double *p_rows, int *p_width,
  334. Cost *p_startup_cost, Cost *p_total_cost);
  335. static void get_remote_estimate(const char *sql,
  336. PGconn *conn,
  337. double *rows,
  338. int *width,
  339. Cost *startup_cost,
  340. Cost *total_cost);
  341. static bool ec_member_matches_foreign(PlannerInfo *root, RelOptInfo *rel,
  342. EquivalenceClass *ec, EquivalenceMember *em,
  343. void *arg);
  344. static void create_cursor(ForeignScanState *node);
  345. static void fetch_more_data(ForeignScanState *node);
  346. static void close_cursor(PGconn *conn, unsigned int cursor_number);
  347. static PgFdwModifyState *create_foreign_modify(EState *estate,
  348. RangeTblEntry *rte,
  349. ResultRelInfo *resultRelInfo,
  350. CmdType operation,
  351. Plan *subplan,
  352. char *query,
  353. List *target_attrs,
  354. bool has_returning,
  355. List *retrieved_attrs);
  356. static void prepare_foreign_modify(PgFdwModifyState *fmstate);
  357. static const char **convert_prep_stmt_params(PgFdwModifyState *fmstate,
  358. ItemPointer tupleid,
  359. TupleTableSlot *slot);
  360. static void store_returning_result(PgFdwModifyState *fmstate,
  361. TupleTableSlot *slot, PGresult *res);
  362. static void finish_foreign_modify(PgFdwModifyState *fmstate);
  363. static List *build_remote_returning(Index rtindex, Relation rel,
  364. List *returningList);
  365. static void rebuild_fdw_scan_tlist(ForeignScan *fscan, List *tlist);
  366. static void execute_dml_stmt(ForeignScanState *node);
  367. static TupleTableSlot *get_returning_data(ForeignScanState *node);
  368. static void init_returning_filter(PgFdwDirectModifyState *dmstate,
  369. List *fdw_scan_tlist,
  370. Index rtindex);
  371. static TupleTableSlot *apply_returning_filter(PgFdwDirectModifyState *dmstate,
  372. TupleTableSlot *slot,
  373. EState *estate);
  374. static void prepare_query_params(PlanState *node,
  375. List *fdw_exprs,
  376. int numParams,
  377. FmgrInfo **param_flinfo,
  378. List **param_exprs,
  379. const char ***param_values);
  380. static void process_query_params(ExprContext *econtext,
  381. FmgrInfo *param_flinfo,
  382. List *param_exprs,
  383. const char **param_values);
  384. static int postgresAcquireSampleRowsFunc(Relation relation, int elevel,
  385. HeapTuple *rows, int targrows,
  386. double *totalrows,
  387. double *totaldeadrows);
  388. static void analyze_row_processor(PGresult *res, int row,
  389. PgFdwAnalyzeState *astate);
  390. static HeapTuple make_tuple_from_result_row(PGresult *res,
  391. int row,
  392. Relation rel,
  393. AttInMetadata *attinmeta,
  394. List *retrieved_attrs,
  395. ForeignScanState *fsstate,
  396. MemoryContext temp_context);
  397. static void conversion_error_callback(void *arg);
  398. static bool foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel,
  399. JoinType jointype, RelOptInfo *outerrel, RelOptInfo *innerrel,
  400. JoinPathExtraData *extra);
  401. static bool foreign_grouping_ok(PlannerInfo *root, RelOptInfo *grouped_rel,
  402. Node *havingQual);
  403. static List *get_useful_pathkeys_for_relation(PlannerInfo *root,
  404. RelOptInfo *rel);
  405. static List *get_useful_ecs_for_relation(PlannerInfo *root, RelOptInfo *rel);
  406. static void add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel,
  407. Path *epq_path);
  408. static void add_foreign_grouping_paths(PlannerInfo *root,
  409. RelOptInfo *input_rel,
  410. RelOptInfo *grouped_rel,
  411. GroupPathExtraData *extra);
  412. static void apply_server_options(PgFdwRelationInfo *fpinfo);
  413. static void apply_table_options(PgFdwRelationInfo *fpinfo);
  414. static void merge_fdw_options(PgFdwRelationInfo *fpinfo,
  415. const PgFdwRelationInfo *fpinfo_o,
  416. const PgFdwRelationInfo *fpinfo_i);
  417. /*
  418. * Foreign-data wrapper handler function: return a struct with pointers
  419. * to my callback routines.
  420. */
  421. Datum
  422. postgres_fdw_handler(PG_FUNCTION_ARGS)
  423. {
  424. FdwRoutine *routine = makeNode(FdwRoutine);
  425. /* Functions for scanning foreign tables */
  426. routine->GetForeignRelSize = postgresGetForeignRelSize;
  427. routine->GetForeignPaths = postgresGetForeignPaths;
  428. routine->GetForeignPlan = postgresGetForeignPlan;
  429. routine->BeginForeignScan = postgresBeginForeignScan;
  430. routine->IterateForeignScan = postgresIterateForeignScan;
  431. routine->ReScanForeignScan = postgresReScanForeignScan;
  432. routine->EndForeignScan = postgresEndForeignScan;
  433. /* Functions for updating foreign tables */
  434. routine->AddForeignUpdateTargets = postgresAddForeignUpdateTargets;
  435. routine->PlanForeignModify = postgresPlanForeignModify;
  436. routine->BeginForeignModify = postgresBeginForeignModify;
  437. routine->ExecForeignInsert = postgresExecForeignInsert;
  438. routine->ExecForeignUpdate = postgresExecForeignUpdate;
  439. routine->ExecForeignDelete = postgresExecForeignDelete;
  440. routine->EndForeignModify = postgresEndForeignModify;
  441. routine->BeginForeignInsert = postgresBeginForeignInsert;
  442. routine->EndForeignInsert = postgresEndForeignInsert;
  443. routine->IsForeignRelUpdatable = postgresIsForeignRelUpdatable;
  444. routine->PlanDirectModify = postgresPlanDirectModify;
  445. routine->BeginDirectModify = postgresBeginDirectModify;
  446. routine->IterateDirectModify = postgresIterateDirectModify;
  447. routine->EndDirectModify = postgresEndDirectModify;
  448. /* Function for EvalPlanQual rechecks */
  449. routine->RecheckForeignScan = postgresRecheckForeignScan;
  450. /* Support functions for EXPLAIN */
  451. routine->ExplainForeignScan = postgresExplainForeignScan;
  452. routine->ExplainForeignModify = postgresExplainForeignModify;
  453. routine->ExplainDirectModify = postgresExplainDirectModify;
  454. /* Support functions for ANALYZE */
  455. routine->AnalyzeForeignTable = postgresAnalyzeForeignTable;
  456. /* Support functions for IMPORT FOREIGN SCHEMA */
  457. routine->ImportForeignSchema = postgresImportForeignSchema;
  458. /* Support functions for join push-down */
  459. routine->GetForeignJoinPaths = postgresGetForeignJoinPaths;
  460. /* Support functions for upper relation push-down */
  461. routine->GetForeignUpperPaths = postgresGetForeignUpperPaths;
  462. PG_RETURN_POINTER(routine);
  463. }
  464. /*
  465. * postgresGetForeignRelSize
  466. * Estimate # of rows and width of the result of the scan
  467. *
  468. * We should consider the effect of all baserestrictinfo clauses here, but
  469. * not any join clauses.
  470. */
  471. static void
  472. postgresGetForeignRelSize(PlannerInfo *root,
  473. RelOptInfo *baserel,
  474. Oid foreigntableid)
  475. {
  476. PgFdwRelationInfo *fpinfo;
  477. ListCell *lc;
  478. RangeTblEntry *rte = planner_rt_fetch(baserel->relid, root);
  479. const char *namespace;
  480. const char *relname;
  481. const char *refname;
  482. /*
  483. * We use PgFdwRelationInfo to pass various information to subsequent
  484. * functions.
  485. */
  486. fpinfo = (PgFdwRelationInfo *) palloc0(sizeof(PgFdwRelationInfo));
  487. baserel->fdw_private = (void *) fpinfo;
  488. /* Base foreign tables need to be pushed down always. */
  489. fpinfo->pushdown_safe = true;
  490. /* Look up foreign-table catalog info. */
  491. fpinfo->table = GetForeignTable(foreigntableid);
  492. fpinfo->server = GetForeignServer(fpinfo->table->serverid);
  493. /*
  494. * Extract user-settable option values. Note that per-table setting of
  495. * use_remote_estimate overrides per-server setting.
  496. */
  497. fpinfo->use_remote_estimate = false;
  498. fpinfo->fdw_startup_cost = DEFAULT_FDW_STARTUP_COST;
  499. fpinfo->fdw_tuple_cost = DEFAULT_FDW_TUPLE_COST;
  500. fpinfo->shippable_extensions = NIL;
  501. fpinfo->fetch_size = 100;
  502. apply_server_options(fpinfo);
  503. apply_table_options(fpinfo);
  504. /*
  505. * If the table or the server is configured to use remote estimates,
  506. * identify which user to do remote access as during planning. This
  507. * should match what ExecCheckRTEPerms() does. If we fail due to lack of
  508. * permissions, the query would have failed at runtime anyway.
  509. */
  510. if (fpinfo->use_remote_estimate)
  511. {
  512. Oid userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
  513. fpinfo->user = GetUserMapping(userid, fpinfo->server->serverid);
  514. }
  515. else
  516. fpinfo->user = NULL;
  517. /*
  518. * Identify which baserestrictinfo clauses can be sent to the remote
  519. * server and which can't.
  520. */
  521. classifyConditions(root, baserel, baserel->baserestrictinfo,
  522. &fpinfo->remote_conds, &fpinfo->local_conds);
  523. /*
  524. * Identify which attributes will need to be retrieved from the remote
  525. * server. These include all attrs needed for joins or final output, plus
  526. * all attrs used in the local_conds. (Note: if we end up using a
  527. * parameterized scan, it's possible that some of the join clauses will be
  528. * sent to the remote and thus we wouldn't really need to retrieve the
  529. * columns used in them. Doesn't seem worth detecting that case though.)
  530. */
  531. fpinfo->attrs_used = NULL;
  532. pull_varattnos((Node *) baserel->reltarget->exprs, baserel->relid,
  533. &fpinfo->attrs_used);
  534. foreach(lc, fpinfo->local_conds)
  535. {
  536. RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
  537. pull_varattnos((Node *) rinfo->clause, baserel->relid,
  538. &fpinfo->attrs_used);
  539. }
  540. /*
  541. * Compute the selectivity and cost of the local_conds, so we don't have
  542. * to do it over again for each path. The best we can do for these
  543. * conditions is to estimate selectivity on the basis of local statistics.
  544. */
  545. fpinfo->local_conds_sel = clauselist_selectivity(root,
  546. fpinfo->local_conds,
  547. baserel->relid,
  548. JOIN_INNER,
  549. NULL);
  550. cost_qual_eval(&fpinfo->local_conds_cost, fpinfo->local_conds, root);
  551. /*
  552. * Set cached relation costs to some negative value, so that we can detect
  553. * when they are set to some sensible costs during one (usually the first)
  554. * of the calls to estimate_path_cost_size().
  555. */
  556. fpinfo->rel_startup_cost = -1;
  557. fpinfo->rel_total_cost = -1;
  558. /*
  559. * If the table or the server is configured to use remote estimates,
  560. * connect to the foreign server and execute EXPLAIN to estimate the
  561. * number of rows selected by the restriction clauses, as well as the
  562. * average row width. Otherwise, estimate using whatever statistics we
  563. * have locally, in a way similar to ordinary tables.
  564. */
  565. if (fpinfo->use_remote_estimate)
  566. {
  567. /*
  568. * Get cost/size estimates with help of remote server. Save the
  569. * values in fpinfo so we don't need to do it again to generate the
  570. * basic foreign path.
  571. */
  572. estimate_path_cost_size(root, baserel, NIL, NIL,
  573. &fpinfo->rows, &fpinfo->width,
  574. &fpinfo->startup_cost, &fpinfo->total_cost);
  575. /* Report estimated baserel size to planner. */
  576. baserel->rows = fpinfo->rows;
  577. baserel->reltarget->width = fpinfo->width;
  578. }
  579. else
  580. {
  581. /*
  582. * If the foreign table has never been ANALYZEd, it will have relpages
  583. * and reltuples equal to zero, which most likely has nothing to do
  584. * with reality. We can't do a whole lot about that if we're not
  585. * allowed to consult the remote server, but we can use a hack similar
  586. * to plancat.c's treatment of empty relations: use a minimum size
  587. * estimate of 10 pages, and divide by the column-datatype-based width
  588. * estimate to get the corresponding number of tuples.
  589. */
  590. if (baserel->pages == 0 && baserel->tuples == 0)
  591. {
  592. baserel->pages = 10;
  593. baserel->tuples =
  594. (10 * BLCKSZ) / (baserel->reltarget->width +
  595. MAXALIGN(SizeofHeapTupleHeader));
  596. }
  597. /* Estimate baserel size as best we can with local statistics. */
  598. set_baserel_size_estimates(root, baserel);
  599. /* Fill in basically-bogus cost estimates for use later. */
  600. estimate_path_cost_size(root, baserel, NIL, NIL,
  601. &fpinfo->rows, &fpinfo->width,
  602. &fpinfo->startup_cost, &fpinfo->total_cost);
  603. }
  604. /*
  605. * Set the name of relation in fpinfo, while we are constructing it here.
  606. * It will be used to build the string describing the join relation in
  607. * EXPLAIN output. We can't know whether VERBOSE option is specified or
  608. * not, so always schema-qualify the foreign table name.
  609. */
  610. fpinfo->relation_name = makeStringInfo();
  611. namespace = get_namespace_name(get_rel_namespace(foreigntableid));
  612. relname = get_rel_name(foreigntableid);
  613. refname = rte->eref->aliasname;
  614. appendStringInfo(fpinfo->relation_name, "%s.%s",
  615. quote_identifier(namespace),
  616. quote_identifier(relname));
  617. if (*refname && strcmp(refname, relname) != 0)
  618. appendStringInfo(fpinfo->relation_name, " %s",
  619. quote_identifier(rte->eref->aliasname));
  620. /* No outer and inner relations. */
  621. fpinfo->make_outerrel_subquery = false;
  622. fpinfo->make_innerrel_subquery = false;
  623. fpinfo->lower_subquery_rels = NULL;
  624. /* Set the relation index. */
  625. fpinfo->relation_index = baserel->relid;
  626. }
  627. /*
  628. * get_useful_ecs_for_relation
  629. * Determine which EquivalenceClasses might be involved in useful
  630. * orderings of this relation.
  631. *
  632. * This function is in some respects a mirror image of the core function
  633. * pathkeys_useful_for_merging: for a regular table, we know what indexes
  634. * we have and want to test whether any of them are useful. For a foreign
  635. * table, we don't know what indexes are present on the remote side but
  636. * want to speculate about which ones we'd like to use if they existed.
  637. *
  638. * This function returns a list of potentially-useful equivalence classes,
  639. * but it does not guarantee that an EquivalenceMember exists which contains
  640. * Vars only from the given relation. For example, given ft1 JOIN t1 ON
  641. * ft1.x + t1.x = 0, this function will say that the equivalence class
  642. * containing ft1.x + t1.x is potentially useful. Supposing ft1 is remote and
  643. * t1 is local (or on a different server), it will turn out that no useful
  644. * ORDER BY clause can be generated. It's not our job to figure that out
  645. * here; we're only interested in identifying relevant ECs.
  646. */
  647. static List *
  648. get_useful_ecs_for_relation(PlannerInfo *root, RelOptInfo *rel)
  649. {
  650. List *useful_eclass_list = NIL;
  651. ListCell *lc;
  652. Relids relids;
  653. /*
  654. * First, consider whether any active EC is potentially useful for a merge
  655. * join against this relation.
  656. */
  657. if (rel->has_eclass_joins)
  658. {
  659. foreach(lc, root->eq_classes)
  660. {
  661. EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc);
  662. if (eclass_useful_for_merging(root, cur_ec, rel))
  663. useful_eclass_list = lappend(useful_eclass_list, cur_ec);
  664. }
  665. }
  666. /*
  667. * Next, consider whether there are any non-EC derivable join clauses that
  668. * are merge-joinable. If the joininfo list is empty, we can exit
  669. * quickly.
  670. */
  671. if (rel->joininfo == NIL)
  672. return useful_eclass_list;
  673. /* If this is a child rel, we must use the topmost parent rel to search. */
  674. if (IS_OTHER_REL(rel))
  675. {
  676. Assert(!bms_is_empty(rel->top_parent_relids));
  677. relids = rel->top_parent_relids;
  678. }
  679. else
  680. relids = rel->relids;
  681. /* Check each join clause in turn. */
  682. foreach(lc, rel->joininfo)
  683. {
  684. RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(lc);
  685. /* Consider only mergejoinable clauses */
  686. if (restrictinfo->mergeopfamilies == NIL)
  687. continue;
  688. /* Make sure we've got canonical ECs. */
  689. update_mergeclause_eclasses(root, restrictinfo);
  690. /*
  691. * restrictinfo->mergeopfamilies != NIL is sufficient to guarantee
  692. * that left_ec and right_ec will be initialized, per comments in
  693. * distribute_qual_to_rels.
  694. *
  695. * We want to identify which side of this merge-joinable clause
  696. * contains columns from the relation produced by this RelOptInfo. We
  697. * test for overlap, not containment, because there could be extra
  698. * relations on either side. For example, suppose we've got something
  699. * like ((A JOIN B ON A.x = B.x) JOIN C ON A.y = C.y) LEFT JOIN D ON
  700. * A.y = D.y. The input rel might be the joinrel between A and B, and
  701. * we'll consider the join clause A.y = D.y. relids contains a
  702. * relation not involved in the join class (B) and the equivalence
  703. * class for the left-hand side of the clause contains a relation not
  704. * involved in the input rel (C). Despite the fact that we have only
  705. * overlap and not containment in either direction, A.y is potentially
  706. * useful as a sort column.
  707. *
  708. * Note that it's even possible that relids overlaps neither side of
  709. * the join clause. For example, consider A LEFT JOIN B ON A.x = B.x
  710. * AND A.x = 1. The clause A.x = 1 will appear in B's joininfo list,
  711. * but overlaps neither side of B. In that case, we just skip this
  712. * join clause, since it doesn't suggest a useful sort order for this
  713. * relation.
  714. */
  715. if (bms_overlap(relids, restrictinfo->right_ec->ec_relids))
  716. useful_eclass_list = list_append_unique_ptr(useful_eclass_list,
  717. restrictinfo->right_ec);
  718. else if (bms_overlap(relids, restrictinfo->left_ec->ec_relids))
  719. useful_eclass_list = list_append_unique_ptr(useful_eclass_list,
  720. restrictinfo->left_ec);
  721. }
  722. return useful_eclass_list;
  723. }
  724. /*
  725. * get_useful_pathkeys_for_relation
  726. * Determine which orderings of a relation might be useful.
  727. *
  728. * Getting data in sorted order can be useful either because the requested
  729. * order matches the final output ordering for the overall query we're
  730. * planning, or because it enables an efficient merge join. Here, we try
  731. * to figure out which pathkeys to consider.
  732. */
  733. static List *
  734. get_useful_pathkeys_for_relation(PlannerInfo *root, RelOptInfo *rel)
  735. {
  736. List *useful_pathkeys_list = NIL;
  737. List *useful_eclass_list;
  738. PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) rel->fdw_private;
  739. EquivalenceClass *query_ec = NULL;
  740. ListCell *lc;
  741. /*
  742. * Pushing the query_pathkeys to the remote server is always worth
  743. * considering, because it might let us avoid a local sort.
  744. */
  745. if (root->query_pathkeys)
  746. {
  747. bool query_pathkeys_ok = true;
  748. foreach(lc, root->query_pathkeys)
  749. {
  750. PathKey *pathkey = (PathKey *) lfirst(lc);
  751. EquivalenceClass *pathkey_ec = pathkey->pk_eclass;
  752. Expr *em_expr;
  753. /*
  754. * The planner and executor don't have any clever strategy for
  755. * taking data sorted by a prefix of the query's pathkeys and
  756. * getting it to be sorted by all of those pathkeys. We'll just
  757. * end up resorting the entire data set. So, unless we can push
  758. * down all of the query pathkeys, forget it.
  759. *
  760. * is_foreign_expr would detect volatile expressions as well, but
  761. * checking ec_has_volatile here saves some cycles.
  762. */
  763. if (pathkey_ec->ec_has_volatile ||
  764. !(em_expr = find_em_expr_for_rel(pathkey_ec, rel)) ||
  765. !is_foreign_expr(root, rel, em_expr))
  766. {
  767. query_pathkeys_ok = false;
  768. break;
  769. }
  770. }
  771. if (query_pathkeys_ok)
  772. useful_pathkeys_list = list_make1(list_copy(root->query_pathkeys));
  773. }
  774. /*
  775. * Even if we're not using remote estimates, having the remote side do the
  776. * sort generally won't be any worse than doing it locally, and it might
  777. * be much better if the remote side can generate data in the right order
  778. * without needing a sort at all. However, what we're going to do next is
  779. * try to generate pathkeys that seem promising for possible merge joins,
  780. * and that's more speculative. A wrong choice might hurt quite a bit, so
  781. * bail out if we can't use remote estimates.
  782. */
  783. if (!fpinfo->use_remote_estimate)
  784. return useful_pathkeys_list;
  785. /* Get the list of interesting EquivalenceClasses. */
  786. useful_eclass_list = get_useful_ecs_for_relation(root, rel);
  787. /* Extract unique EC for query, if any, so we don't consider it again. */
  788. if (list_length(root->query_pathkeys) == 1)
  789. {
  790. PathKey *query_pathkey = linitial(root->query_pathkeys);
  791. query_ec = query_pathkey->pk_eclass;
  792. }
  793. /*
  794. * As a heuristic, the only pathkeys we consider here are those of length
  795. * one. It's surely possible to consider more, but since each one we
  796. * choose to consider will generate a round-trip to the remote side, we
  797. * need to be a bit cautious here. It would sure be nice to have a local
  798. * cache of information about remote index definitions...
  799. */
  800. foreach(lc, useful_eclass_list)
  801. {
  802. EquivalenceClass *cur_ec = lfirst(lc);
  803. Expr *em_expr;
  804. PathKey *pathkey;
  805. /* If redundant with what we did above, skip it. */
  806. if (cur_ec == query_ec)
  807. continue;
  808. /* If no pushable expression for this rel, skip it. */
  809. em_expr = find_em_expr_for_rel(cur_ec, rel);
  810. if (em_expr == NULL || !is_foreign_expr(root, rel, em_expr))
  811. continue;
  812. /* Looks like we can generate a pathkey, so let's do it. */
  813. pathkey = make_canonical_pathkey(root, cur_ec,
  814. linitial_oid(cur_ec->ec_opfamilies),
  815. BTLessStrategyNumber,
  816. false);
  817. useful_pathkeys_list = lappend(useful_pathkeys_list,
  818. list_make1(pathkey));
  819. }
  820. return useful_pathkeys_list;
  821. }
  822. /*
  823. * postgresGetForeignPaths
  824. * Create possible scan paths for a scan on the foreign table
  825. */
  826. static void
  827. postgresGetForeignPaths(PlannerInfo *root,
  828. RelOptInfo *baserel,
  829. Oid foreigntableid)
  830. {
  831. PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) baserel->fdw_private;
  832. ForeignPath *path;
  833. List *ppi_list;
  834. ListCell *lc;
  835. /*
  836. * Create simplest ForeignScan path node and add it to baserel. This path
  837. * corresponds to SeqScan path of regular tables (though depending on what
  838. * baserestrict conditions we were able to send to remote, there might
  839. * actually be an indexscan happening there). We already did all the work
  840. * to estimate cost and size of this path.
  841. */
  842. path = create_foreignscan_path(root, baserel,
  843. NULL, /* default pathtarget */
  844. fpinfo->rows,
  845. fpinfo->startup_cost,
  846. fpinfo->total_cost,
  847. NIL, /* no pathkeys */
  848. NULL, /* no outer rel either */
  849. NULL, /* no extra plan */
  850. NIL); /* no fdw_private list */
  851. add_path(baserel, (Path *) path);
  852. /* Add paths with pathkeys */
  853. add_paths_with_pathkeys_for_rel(root, baserel, NULL);
  854. /*
  855. * If we're not using remote estimates, stop here. We have no way to
  856. * estimate whether any join clauses would be worth sending across, so
  857. * don't bother building parameterized paths.
  858. */
  859. if (!fpinfo->use_remote_estimate)
  860. return;
  861. /*
  862. * Thumb through all join clauses for the rel to identify which outer
  863. * relations could supply one or more safe-to-send-to-remote join clauses.
  864. * We'll build a parameterized path for each such outer relation.
  865. *
  866. * It's convenient to manage this by representing each candidate outer
  867. * relation by the ParamPathInfo node for it. We can then use the
  868. * ppi_clauses list in the ParamPathInfo node directly as a list of the
  869. * interesting join clauses for that rel. This takes care of the
  870. * possibility that there are multiple safe join clauses for such a rel,
  871. * and also ensures that we account for unsafe join clauses that we'll
  872. * still have to enforce locally (since the parameterized-path machinery
  873. * insists that we handle all movable clauses).
  874. */
  875. ppi_list = NIL;
  876. foreach(lc, baserel->joininfo)
  877. {
  878. RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
  879. Relids required_outer;
  880. ParamPathInfo *param_info;
  881. /* Check if clause can be moved to this rel */
  882. if (!join_clause_is_movable_to(rinfo, baserel))
  883. continue;
  884. /* See if it is safe to send to remote */
  885. if (!is_foreign_expr(root, baserel, rinfo->clause))
  886. continue;
  887. /* Calculate required outer rels for the resulting path */
  888. required_outer = bms_union(rinfo->clause_relids,
  889. baserel->lateral_relids);
  890. /* We do not want the foreign rel itself listed in required_outer */
  891. required_outer = bms_del_member(required_outer, baserel->relid);
  892. /*
  893. * required_outer probably can't be empty here, but if it were, we
  894. * couldn't make a parameterized path.
  895. */
  896. if (bms_is_empty(required_outer))
  897. continue;
  898. /* Get the ParamPathInfo */
  899. param_info = get_baserel_parampathinfo(root, baserel,
  900. required_outer);
  901. Assert(param_info != NULL);
  902. /*
  903. * Add it to list unless we already have it. Testing pointer equality
  904. * is OK since get_baserel_parampathinfo won't make duplicates.
  905. */
  906. ppi_list = list_append_unique_ptr(ppi_list, param_info);
  907. }
  908. /*
  909. * The above scan examined only "generic" join clauses, not those that
  910. * were absorbed into EquivalenceClauses. See if we can make anything out
  911. * of EquivalenceClauses.
  912. */
  913. if (baserel->has_eclass_joins)
  914. {
  915. /*
  916. * We repeatedly scan the eclass list looking for column references
  917. * (or expressions) belonging to the foreign rel. Each time we find
  918. * one, we generate a list of equivalence joinclauses for it, and then
  919. * see if any are safe to send to the remote. Repeat till there are
  920. * no more candidate EC members.
  921. */
  922. ec_member_foreign_arg arg;
  923. arg.already_used = NIL;
  924. for (;;)
  925. {
  926. List *clauses;
  927. /* Make clauses, skipping any that join to lateral_referencers */
  928. arg.current = NULL;
  929. clauses = generate_implied_equalities_for_column(root,
  930. baserel,
  931. ec_member_matches_foreign,
  932. (void *) &arg,
  933. baserel->lateral_referencers);
  934. /* Done if there are no more expressions in the foreign rel */
  935. if (arg.current == NULL)
  936. {
  937. Assert(clauses == NIL);
  938. break;
  939. }
  940. /* Scan the extracted join clauses */
  941. foreach(lc, clauses)
  942. {
  943. RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
  944. Relids required_outer;
  945. ParamPathInfo *param_info;
  946. /* Check if clause can be moved to this rel */
  947. if (!join_clause_is_movable_to(rinfo, baserel))
  948. continue;
  949. /* See if it is safe to send to remote */
  950. if (!is_foreign_expr(root, baserel, rinfo->clause))
  951. continue;
  952. /* Calculate required outer rels for the resulting path */
  953. required_outer = bms_union(rinfo->clause_relids,
  954. baserel->lateral_relids);
  955. required_outer = bms_del_member(required_outer, baserel->relid);
  956. if (bms_is_empty(required_outer))
  957. continue;
  958. /* Get the ParamPathInfo */
  959. param_info = get_baserel_parampathinfo(root, baserel,
  960. required_outer);
  961. Assert(param_info != NULL);
  962. /* Add it to list unless we already have it */
  963. ppi_list = list_append_unique_ptr(ppi_list, param_info);
  964. }
  965. /* Try again, now ignoring the expression we found this time */
  966. arg.already_used = lappend(arg.already_used, arg.current);
  967. }
  968. }
  969. /*
  970. * Now build a path for each useful outer relation.
  971. */
  972. foreach(lc, ppi_list)
  973. {
  974. ParamPathInfo *param_info = (ParamPathInfo *) lfirst(lc);
  975. double rows;
  976. int width;
  977. Cost startup_cost;
  978. Cost total_cost;
  979. /* Get a cost estimate from the remote */
  980. estimate_path_cost_size(root, baserel,
  981. param_info->ppi_clauses, NIL,
  982. &rows, &width,
  983. &startup_cost, &total_cost);
  984. /*
  985. * ppi_rows currently won't get looked at by anything, but still we
  986. * may as well ensure that it matches our idea of the rowcount.
  987. */
  988. param_info->ppi_rows = rows;
  989. /* Make the path */
  990. path = create_foreignscan_path(root, baserel,
  991. NULL, /* default pathtarget */
  992. rows,
  993. startup_cost,
  994. total_cost,
  995. NIL, /* no pathkeys */
  996. param_info->ppi_req_outer,
  997. NULL,
  998. NIL); /* no fdw_private list */
  999. add_path(baserel, (Path *) path);
  1000. }
  1001. }
  1002. /*
  1003. * postgresGetForeignPlan
  1004. * Create ForeignScan plan node which implements selected best path
  1005. */
  1006. static ForeignScan *
  1007. postgresGetForeignPlan(PlannerInfo *root,
  1008. RelOptInfo *foreignrel,
  1009. Oid foreigntableid,
  1010. ForeignPath *best_path,
  1011. List *tlist,
  1012. List *scan_clauses,
  1013. Plan *outer_plan)
  1014. {
  1015. PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
  1016. Index scan_relid;
  1017. List *fdw_private;
  1018. List *remote_exprs = NIL;
  1019. List *local_exprs = NIL;
  1020. List *params_list = NIL;
  1021. List *fdw_scan_tlist = NIL;
  1022. List *fdw_recheck_quals = NIL;
  1023. List *retrieved_attrs;
  1024. StringInfoData sql;
  1025. ListCell *lc;
  1026. if (IS_SIMPLE_REL(foreignrel))
  1027. {
  1028. /*
  1029. * For base relations, set scan_relid as the relid of the relation.
  1030. */
  1031. scan_relid = foreignrel->relid;
  1032. /*
  1033. * In a base-relation scan, we must apply the given scan_clauses.
  1034. *
  1035. * Separate the scan_clauses into those that can be executed remotely
  1036. * and those that can't. baserestrictinfo clauses that were
  1037. * previously determined to be safe or unsafe by classifyConditions
  1038. * are found in fpinfo->remote_conds and fpinfo->local_conds. Anything
  1039. * else in the scan_clauses list will be a join clause, which we have
  1040. * to check for remote-safety.
  1041. *
  1042. * Note: the join clauses we see here should be the exact same ones
  1043. * previously examined by postgresGetForeignPaths. Possibly it'd be
  1044. * worth passing forward the classification work done then, rather
  1045. * than repeating it here.
  1046. *
  1047. * This code must match "extract_actual_clauses(scan_clauses, false)"
  1048. * except for the additional decision about remote versus local
  1049. * execution.
  1050. */
  1051. foreach(lc, scan_clauses)
  1052. {
  1053. RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
  1054. /* Ignore any pseudoconstants, they're dealt with elsewhere */
  1055. if (rinfo->pseudoconstant)
  1056. continue;
  1057. if (list_member_ptr(fpinfo->remote_conds, rinfo))
  1058. remote_exprs = lappend(remote_exprs, rinfo->clause);
  1059. else if (list_member_ptr(fpinfo->local_conds, rinfo))
  1060. local_exprs = lappend(local_exprs, rinfo->clause);
  1061. else if (is_foreign_expr(root, foreignrel, rinfo->clause))
  1062. remote_exprs = lappend(remote_exprs, rinfo->clause);
  1063. else
  1064. local_exprs = lappend(local_exprs, rinfo->clause);
  1065. }
  1066. /*
  1067. * For a base-relation scan, we have to support EPQ recheck, which
  1068. * should recheck all the remote quals.
  1069. */
  1070. fdw_recheck_quals = remote_exprs;
  1071. }
  1072. else
  1073. {
  1074. /*
  1075. * Join relation or upper relation - set scan_relid to 0.
  1076. */
  1077. scan_relid = 0;
  1078. /*
  1079. * For a join rel, baserestrictinfo is NIL and we are not considering
  1080. * parameterization right now, so there should be no scan_clauses for
  1081. * a joinrel or an upper rel either.
  1082. */
  1083. Assert(!scan_clauses);
  1084. /*
  1085. * Instead we get the conditions to apply from the fdw_private
  1086. * structure.
  1087. */
  1088. remote_exprs = extract_actual_clauses(fpinfo->remote_conds, false);
  1089. local_exprs = extract_actual_clauses(fpinfo->local_conds, false);
  1090. /*
  1091. * We leave fdw_recheck_quals empty in this case, since we never need
  1092. * to apply EPQ recheck clauses. In the case of a joinrel, EPQ
  1093. * recheck is handled elsewhere --- see postgresGetForeignJoinPaths().
  1094. * If we're planning an upperrel (ie, remote grouping or aggregation)
  1095. * then there's no EPQ to do because SELECT FOR UPDATE wouldn't be
  1096. * allowed, and indeed we *can't* put the remote clauses into
  1097. * fdw_recheck_quals because the unaggregated Vars won't be available
  1098. * locally.
  1099. */
  1100. /* Build the list of columns to be fetched from the foreign server. */
  1101. fdw_scan_tlist = build_tlist_to_deparse(foreignrel);
  1102. /*
  1103. * Ensure that the outer plan produces a tuple whose descriptor
  1104. * matches our scan tuple slot. Also, remove the local conditions
  1105. * from outer plan's quals, lest they be evaluated twice, once by the
  1106. * local plan and once by the scan.
  1107. */
  1108. if (outer_plan)
  1109. {
  1110. ListCell *lc;
  1111. /*
  1112. * Right now, we only consider grouping and aggregation beyond
  1113. * joins. Queries involving aggregates or grouping do not require
  1114. * EPQ mechanism, hence should not have an outer plan here.
  1115. */
  1116. Assert(!IS_UPPER_REL(foreignrel));
  1117. /*
  1118. * First, update the plan's qual list if possible. In some cases
  1119. * the quals might be enforced below the topmost plan level, in
  1120. * which case we'll fail to remove them; it's not worth working
  1121. * harder than this.
  1122. */
  1123. foreach(lc, local_exprs)
  1124. {
  1125. Node *qual = lfirst(lc);
  1126. outer_plan->qual = list_delete(outer_plan->qual, qual);
  1127. /*
  1128. * For an inner join the local conditions of foreign scan plan
  1129. * can be part of the joinquals as well. (They might also be
  1130. * in the mergequals or hashquals, but we can't touch those
  1131. * without breaking the plan.)
  1132. */
  1133. if (IsA(outer_plan, NestLoop) ||
  1134. IsA(outer_plan, MergeJoin) ||
  1135. IsA(outer_plan, HashJoin))
  1136. {
  1137. Join *join_plan = (Join *) outer_plan;
  1138. if (join_plan->jointype == JOIN_INNER)
  1139. join_plan->joinqual = list_delete(join_plan->joinqual,
  1140. qual);
  1141. }
  1142. }
  1143. /*
  1144. * Now fix the subplan's tlist --- this might result in inserting
  1145. * a Result node atop the plan tree.
  1146. */
  1147. outer_plan = change_plan_targetlist(outer_plan, fdw_scan_tlist,
  1148. best_path->path.parallel_safe);
  1149. }
  1150. }
  1151. /*
  1152. * Build the query string to be sent for execution, and identify
  1153. * expressions to be sent as parameters.
  1154. */
  1155. initStringInfo(&sql);
  1156. deparseSelectStmtForRel(&sql, root, foreignrel, fdw_scan_tlist,
  1157. remote_exprs, best_path->path.pathkeys,
  1158. false, &retrieved_attrs, &params_list);
  1159. /* Remember remote_exprs for possible use by postgresPlanDirectModify */
  1160. fpinfo->final_remote_exprs = remote_exprs;
  1161. /*
  1162. * Build the fdw_private list that will be available to the executor.
  1163. * Items in the list must match order in enum FdwScanPrivateIndex.
  1164. */
  1165. fdw_private = list_make3(makeString(sql.data),
  1166. retrieved_attrs,
  1167. makeInteger(fpinfo->fetch_size));
  1168. if (IS_JOIN_REL(foreignrel) || IS_UPPER_REL(foreignrel))
  1169. fdw_private = lappend(fdw_private,
  1170. makeString(fpinfo->relation_name->data));
  1171. /*
  1172. * Create the ForeignScan node for the given relation.
  1173. *
  1174. * Note that the remote parameter expressions are stored in the fdw_exprs
  1175. * field of the finished plan node; we can't keep them in private state
  1176. * because then they wouldn't be subject to later planner processing.
  1177. */
  1178. return make_foreignscan(tlist,
  1179. local_exprs,
  1180. scan_relid,
  1181. params_list,
  1182. fdw_private,
  1183. fdw_scan_tlist,
  1184. fdw_recheck_quals,
  1185. outer_plan);
  1186. }
  1187. /*
  1188. * postgresBeginForeignScan
  1189. * Initiate an executor scan of a foreign PostgreSQL table.
  1190. */
  1191. static void
  1192. postgresBeginForeignScan(ForeignScanState *node, int eflags)
  1193. {
  1194. ForeignScan *fsplan = (ForeignScan *) node->ss.ps.plan;
  1195. EState *estate = node->ss.ps.state;
  1196. PgFdwScanState *fsstate;
  1197. RangeTblEntry *rte;
  1198. Oid userid;
  1199. ForeignTable *table;
  1200. UserMapping *user;
  1201. int rtindex;
  1202. int numParams;
  1203. /*
  1204. * Do nothing in EXPLAIN (no ANALYZE) case. node->fdw_state stays NULL.
  1205. */
  1206. if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
  1207. return;
  1208. /*
  1209. * We'll save private state in node->fdw_state.
  1210. */
  1211. fsstate = (PgFdwScanState *) palloc0(sizeof(PgFdwScanState));
  1212. node->fdw_state = (void *) fsstate;
  1213. /*
  1214. * Identify which user to do the remote access as. This should match what
  1215. * ExecCheckRTEPerms() does. In case of a join or aggregate, use the
  1216. * lowest-numbered member RTE as a representative; we would get the same
  1217. * result from any.
  1218. */
  1219. if (fsplan->scan.scanrelid > 0)
  1220. rtindex = fsplan->scan.scanrelid;
  1221. else
  1222. rtindex = bms_next_member(fsplan->fs_relids, -1);
  1223. rte = exec_rt_fetch(rtindex, estate);
  1224. userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
  1225. /* Get info about foreign table. */
  1226. table = GetForeignTable(rte->relid);
  1227. user = GetUserMapping(userid, table->serverid);
  1228. /*
  1229. * Get connection to the foreign server. Connection manager will
  1230. * establish new connection if necessary.
  1231. */
  1232. fsstate->conn = GetConnection(user, false);
  1233. /* Assign a unique ID for my cursor */
  1234. fsstate->cursor_number = GetCursorNumber(fsstate->conn);
  1235. fsstate->cursor_exists = false;
  1236. /* Get private info created by planner functions. */
  1237. fsstate->query = strVal(list_nth(fsplan->fdw_private,
  1238. FdwScanPrivateSelectSql));
  1239. fsstate->retrieved_attrs = (List *) list_nth(fsplan->fdw_private,
  1240. FdwScanPrivateRetrievedAttrs);
  1241. fsstate->fetch_size = intVal(list_nth(fsplan->fdw_private,
  1242. FdwScanPrivateFetchSize));
  1243. /* Create contexts for batches of tuples and per-tuple temp workspace. */
  1244. fsstate->batch_cxt = AllocSetContextCreate(estate->es_query_cxt,
  1245. "postgres_fdw tuple data",
  1246. ALLOCSET_DEFAULT_SIZES);
  1247. fsstate->temp_cxt = AllocSetContextCreate(estate->es_query_cxt,
  1248. "postgres_fdw temporary data",
  1249. ALLOCSET_SMALL_SIZES);
  1250. /*
  1251. * Get info we'll need for converting data fetched from the foreign server
  1252. * into local representation and error reporting during that process.
  1253. */
  1254. if (fsplan->scan.scanrelid > 0)
  1255. {
  1256. fsstate->rel = node->ss.ss_currentRelation;
  1257. fsstate->tupdesc = RelationGetDescr(fsstate->rel);
  1258. }
  1259. else
  1260. {
  1261. fsstate->rel = NULL;
  1262. fsstate->tupdesc = node->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
  1263. }
  1264. fsstate->attinmeta = TupleDescGetAttInMetadata(fsstate->tupdesc);
  1265. /*
  1266. * Prepare for processing of parameters used in remote query, if any.
  1267. */
  1268. numParams = list_length(fsplan->fdw_exprs);
  1269. fsstate->numParams = numParams;
  1270. if (numParams > 0)
  1271. prepare_query_params((PlanState *) node,
  1272. fsplan->fdw_exprs,
  1273. numParams,
  1274. &fsstate->param_flinfo,
  1275. &fsstate->param_exprs,
  1276. &fsstate->param_values);
  1277. }
  1278. /*
  1279. * postgresIterateForeignScan
  1280. * Retrieve next row from the result set, or clear tuple slot to indicate
  1281. * EOF.
  1282. */
  1283. static TupleTableSlot *
  1284. postgresIterateForeignScan(ForeignScanState *node)
  1285. {
  1286. PgFdwScanState *fsstate = (PgFdwScanState *) node->fdw_state;
  1287. TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
  1288. /*
  1289. * If this is the first call after Begin or ReScan, we need to create the
  1290. * cursor on the remote side.
  1291. */
  1292. if (!fsstate->cursor_exists)
  1293. create_cursor(node);
  1294. /*
  1295. * Get some more tuples, if we've run out.
  1296. */
  1297. if (fsstate->next_tuple >= fsstate->num_tuples)
  1298. {
  1299. /* No point in another fetch if we already detected EOF, though. */
  1300. if (!fsstate->eof_reached)
  1301. fetch_more_data(node);
  1302. /* If we didn't get any tuples, must be end of data. */
  1303. if (fsstate->next_tuple >= fsstate->num_tuples)
  1304. return ExecClearTuple(slot);
  1305. }
  1306. /*
  1307. * Return the next tuple.
  1308. */
  1309. ExecStoreHeapTuple(fsstate->tuples[fsstate->next_tuple++],
  1310. slot,
  1311. false);
  1312. return slot;
  1313. }
  1314. /*
  1315. * postgresReScanForeignScan
  1316. * Restart the scan.
  1317. */
  1318. static void
  1319. postgresReScanForeignScan(ForeignScanState *node)
  1320. {
  1321. PgFdwScanState *fsstate = (PgFdwScanState *) node->fdw_state;
  1322. char sql[64];
  1323. PGresult *res;
  1324. /* If we haven't created the cursor yet, nothing to do. */
  1325. if (!fsstate->cursor_exists)
  1326. return;
  1327. /*
  1328. * If any internal parameters affecting this node have changed, we'd
  1329. * better destroy and recreate the cursor. Otherwise, rewinding it should
  1330. * be good enough. If we've only fetched zero or one batch, we needn't
  1331. * even rewind the cursor, just rescan what we have.
  1332. */
  1333. if (node->ss.ps.chgParam != NULL)
  1334. {
  1335. fsstate->cursor_exists = false;
  1336. snprintf(sql, sizeof(sql), "CLOSE c%u",
  1337. fsstate->cursor_number);
  1338. }
  1339. else if (fsstate->fetch_ct_2 > 1)
  1340. {
  1341. snprintf(sql, sizeof(sql), "MOVE BACKWARD ALL IN c%u",
  1342. fsstate->cursor_number);
  1343. }
  1344. else
  1345. {
  1346. /* Easy: just rescan what we already have in memory, if anything */
  1347. fsstate->next_tuple = 0;
  1348. return;
  1349. }
  1350. /*
  1351. * We don't use a PG_TRY block here, so be careful not to throw error
  1352. * without releasing the PGresult.
  1353. */
  1354. res = pgfdw_exec_query(fsstate->conn, sql);
  1355. if (PQresultStatus(res) != PGRES_COMMAND_OK)
  1356. pgfdw_report_error(ERROR, res, fsstate->conn, true, sql);
  1357. PQclear(res);
  1358. /* Now force a fresh FETCH. */
  1359. fsstate->tuples = NULL;
  1360. fsstate->num_tuples = 0;
  1361. fsstate->next_tuple = 0;
  1362. fsstate->fetch_ct_2 = 0;
  1363. fsstate->eof_reached = false;
  1364. }
  1365. /*
  1366. * postgresEndForeignScan
  1367. * Finish scanning foreign table and dispose objects used for this scan
  1368. */
  1369. static void
  1370. postgresEndForeignScan(ForeignScanState *node)
  1371. {
  1372. PgFdwScanState *fsstate = (PgFdwScanState *) node->fdw_state;
  1373. /* if fsstate is NULL, we are in EXPLAIN; nothing to do */
  1374. if (fsstate == NULL)
  1375. return;
  1376. /* Close the cursor if open, to prevent accumulation of cursors */
  1377. if (fsstate->cursor_exists)
  1378. close_cursor(fsstate->conn, fsstate->cursor_number);
  1379. /* Release remote connection */
  1380. ReleaseConnection(fsstate->conn);
  1381. fsstate->conn = NULL;
  1382. /* MemoryContexts will be deleted automatically. */
  1383. }
  1384. /*
  1385. * postgresAddForeignUpdateTargets
  1386. * Add resjunk column(s) needed for update/delete on a foreign table
  1387. */
  1388. static void
  1389. postgresAddForeignUpdateTargets(Query *parsetree,
  1390. RangeTblEntry *target_rte,
  1391. Relation target_relation)
  1392. {
  1393. Var *var;
  1394. const char *attrname;
  1395. TargetEntry *tle;
  1396. /*
  1397. * In postgres_fdw, what we need is the ctid, same as for a regular table.
  1398. */
  1399. /* Make a Var representing the desired value */
  1400. var = makeVar(parsetree->resultRelation,
  1401. SelfItemPointerAttributeNumber,
  1402. TIDOID,
  1403. -1,
  1404. InvalidOid,
  1405. 0);
  1406. /* Wrap it in a resjunk TLE with the right name ... */
  1407. attrname = "ctid";
  1408. tle = makeTargetEntry((Expr *) var,
  1409. list_length(parsetree->targetList) + 1,
  1410. pstrdup(attrname),
  1411. true);
  1412. /* ... and add it to the query's targetlist */
  1413. parsetree->targetList = lappend(parsetree->targetList, tle);
  1414. }
  1415. /*
  1416. * postgresPlanForeignModify
  1417. * Plan an insert/update/delete operation on a foreign table
  1418. */
  1419. static List *
  1420. postgresPlanForeignModify(PlannerInfo *root,
  1421. ModifyTable *plan,
  1422. Index resultRelation,
  1423. int subplan_index)
  1424. {
  1425. CmdType operation = plan->operation;
  1426. RangeTblEntry *rte = planner_rt_fetch(resultRelation, root);
  1427. Relation rel;
  1428. StringInfoData sql;
  1429. List *targetAttrs = NIL;
  1430. List *withCheckOptionList = NIL;
  1431. List *returningList = NIL;
  1432. List *retrieved_attrs = NIL;
  1433. bool doNothing = false;
  1434. initStringInfo(&sql);
  1435. /*
  1436. * Core code already has some lock on each rel being planned, so we can
  1437. * use NoLock here.
  1438. */
  1439. rel = heap_open(rte->relid, NoLock);
  1440. /*
  1441. * In an INSERT, we transmit all columns that are defined in the foreign
  1442. * table. In an UPDATE, we transmit only columns that were explicitly
  1443. * targets of the UPDATE, so as to avoid unnecessary data transmission.
  1444. * (We can't do that for INSERT since we would miss sending default values
  1445. * for columns not listed in the source statement.)
  1446. */
  1447. if (operation == CMD_INSERT)
  1448. {
  1449. TupleDesc tupdesc = RelationGetDescr(rel);
  1450. int attnum;
  1451. for (attnum = 1; attnum <= tupdesc->natts; attnum++)
  1452. {
  1453. Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1);
  1454. if (!attr->attisdropped)
  1455. targetAttrs = lappend_int(targetAttrs, attnum);
  1456. }
  1457. }
  1458. else if (operation == CMD_UPDATE)
  1459. {
  1460. int col;
  1461. col = -1;
  1462. while ((col = bms_next_member(rte->updatedCols, col)) >= 0)
  1463. {
  1464. /* bit numbers are offset by FirstLowInvalidHeapAttributeNumber */
  1465. AttrNumber attno = col + FirstLowInvalidHeapAttributeNumber;
  1466. if (attno <= InvalidAttrNumber) /* shouldn't happen */
  1467. elog(ERROR, "system-column update is not supported");
  1468. targetAttrs = lappend_int(targetAttrs, attno);
  1469. }
  1470. }
  1471. /*
  1472. * Extract the relevant WITH CHECK OPTION list if any.
  1473. */
  1474. if (plan->withCheckOptionLists)
  1475. withCheckOptionList = (List *) list_nth(plan->withCheckOptionLists,
  1476. subplan_index);
  1477. /*
  1478. * Extract the relevant RETURNING list if any.
  1479. */
  1480. if (plan->returningLists)
  1481. returningList = (List *) list_nth(plan->returningLists, subplan_index);
  1482. /*
  1483. * ON CONFLICT DO UPDATE and DO NOTHING case with inference specification
  1484. * should have already been rejected in the optimizer, as presently there
  1485. * is no way to recognize an arbiter index on a foreign table. Only DO
  1486. * NOTHING is supported without an inference specification.
  1487. */
  1488. if (plan->onConflictAction == ONCONFLICT_NOTHING)
  1489. doNothing = true;
  1490. else if (plan->onConflictAction != ONCONFLICT_NONE)
  1491. elog(ERROR, "unexpected ON CONFLICT specification: %d",
  1492. (int) plan->onConflictAction);
  1493. /*
  1494. * Construct the SQL command string.
  1495. */
  1496. switch (operation)
  1497. {
  1498. case CMD_INSERT:
  1499. deparseInsertSql(&sql, rte, resultRelation, rel,
  1500. targetAttrs, doNothing,
  1501. withCheckOptionList, returningList,
  1502. &retrieved_attrs);
  1503. break;
  1504. case CMD_UPDATE:
  1505. deparseUpdateSql(&sql, rte, resultRelation, rel,
  1506. targetAttrs,
  1507. withCheckOptionList, returningList,
  1508. &retrieved_attrs);
  1509. break;
  1510. case CMD_DELETE:
  1511. deparseDeleteSql(&sql, rte, resultRelation, rel,
  1512. returningList,
  1513. &retrieved_attrs);
  1514. break;
  1515. default:
  1516. elog(ERROR, "unexpected operation: %d", (int) operation);
  1517. break;
  1518. }
  1519. heap_close(rel, NoLock);
  1520. /*
  1521. * Build the fdw_private list that will be available to the executor.
  1522. * Items in the list must match enum FdwModifyPrivateIndex, above.
  1523. */
  1524. return list_make4(makeString(sql.data),
  1525. targetAttrs,
  1526. makeInteger((retrieved_attrs != NIL)),
  1527. retrieved_attrs);
  1528. }
  1529. /*
  1530. * postgresBeginForeignModify
  1531. * Begin an insert/update/delete operation on a foreign table
  1532. */
  1533. static void
  1534. postgresBeginForeignModify(ModifyTableState *mtstate,
  1535. ResultRelInfo *resultRelInfo,
  1536. List *fdw_private,
  1537. int subplan_index,
  1538. int eflags)
  1539. {
  1540. PgFdwModifyState *fmstate;
  1541. char *query;
  1542. List *target_attrs;
  1543. bool has_returning;
  1544. List *retrieved_attrs;
  1545. RangeTblEntry *rte;
  1546. /*
  1547. * Do nothing in EXPLAIN (no ANALYZE) case. resultRelInfo->ri_FdwState
  1548. * stays NULL.
  1549. */
  1550. if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
  1551. return;
  1552. /* Deconstruct fdw_private data. */
  1553. query = strVal(list_nth(fdw_private,
  1554. FdwModifyPrivateUpdateSql));
  1555. target_attrs = (List *) list_nth(fdw_private,
  1556. FdwModifyPrivateTargetAttnums);
  1557. has_returning = intVal(list_nth(fdw_private,
  1558. FdwModifyPrivateHasReturning));
  1559. retrieved_attrs = (List *) list_nth(fdw_private,
  1560. FdwModifyPrivateRetrievedAttrs);
  1561. /* Find RTE. */
  1562. rte = exec_rt_fetch(resultRelInfo->ri_RangeTableIndex,
  1563. mtstate->ps.state);
  1564. /* Construct an execution state. */
  1565. fmstate = create_foreign_modify(mtstate->ps.state,
  1566. rte,
  1567. resultRelInfo,
  1568. mtstate->operation,
  1569. mtstate->mt_plans[subplan_index]->plan,
  1570. query,
  1571. target_attrs,
  1572. has_returning,
  1573. retrieved_attrs);
  1574. resultRelInfo->ri_FdwState = fmstate;
  1575. }
  1576. /*
  1577. * postgresExecForeignInsert
  1578. * Insert one row into a foreign table
  1579. */
  1580. static TupleTableSlot *
  1581. postgresExecForeignInsert(EState *estate,
  1582. ResultRelInfo *resultRelInfo,
  1583. TupleTableSlot *slot,
  1584. TupleTableSlot *planSlot)
  1585. {
  1586. PgFdwModifyState *fmstate = (PgFdwModifyState *) resultRelInfo->ri_FdwState;
  1587. const char **p_values;
  1588. PGresult *res;
  1589. int n_rows;
  1590. /* Set up the prepared statement on the remote server, if we didn't yet */
  1591. if (!fmstate->p_name)
  1592. prepare_foreign_modify(fmstate);
  1593. /* Convert parameters needed by prepared statement to text form */
  1594. p_values = convert_prep_stmt_params(fmstate, NULL, slot);
  1595. /*
  1596. * Execute the prepared statement.
  1597. */
  1598. if (!PQsendQueryPrepared(fmstate->conn,
  1599. fmstate->p_name,
  1600. fmstate->p_nums,
  1601. p_values,
  1602. NULL,
  1603. NULL,
  1604. 0))
  1605. pgfdw_report_error(ERROR, NULL, fmstate->conn, false, fmstate->query);
  1606. /*
  1607. * Get the result, and check for success.
  1608. *
  1609. * We don't use a PG_TRY block here, so be careful not to throw error
  1610. * without releasing the PGresult.
  1611. */
  1612. res = pgfdw_get_result(fmstate->conn, fmstate->query);
  1613. if (PQresultStatus(res) !=
  1614. (fmstate->has_returning ? PGRES_TUPLES_OK : PGRES_COMMAND_OK))
  1615. pgfdw_report_error(ERROR, res, fmstate->conn, true, fmstate->query);
  1616. /* Check number of rows affected, and fetch RETURNING tuple if any */
  1617. if (fmstate->has_returning)
  1618. {
  1619. n_rows = PQntuples(res);
  1620. if (n_rows > 0)
  1621. store_returning_result(fmstate, slot, res);
  1622. }
  1623. else
  1624. n_rows = atoi(PQcmdTuples(res));
  1625. /* And clean up */
  1626. PQclear(res);
  1627. MemoryContextReset(fmstate->temp_cxt);
  1628. /* Return NULL if nothing was inserted on the remote end */
  1629. return (n_rows > 0) ? slot : NULL;
  1630. }
  1631. /*
  1632. * postgresExecForeignUpdate
  1633. * Update one row in a foreign table
  1634. */
  1635. static TupleTableSlot *
  1636. postgresExecForeignUpdate(EState *estate,
  1637. ResultRelInfo *resultRelInfo,
  1638. TupleTableSlot *slot,
  1639. TupleTableSlot *planSlot)
  1640. {
  1641. PgFdwModifyState *fmstate = (PgFdwModifyState *) resultRelInfo->ri_FdwState;
  1642. Datum datum;
  1643. bool isNull;
  1644. const char **p_values;
  1645. PGresult *res;
  1646. int n_rows;
  1647. /* Set up the prepared statement on the remote server, if we didn't yet */
  1648. if (!fmstate->p_name)
  1649. prepare_foreign_modify(fmstate);
  1650. /* Get the ctid that was passed up as a resjunk column */
  1651. datum = ExecGetJunkAttribute(planSlot,
  1652. fmstate->ctidAttno,
  1653. &isNull);
  1654. /* shouldn't ever get a null result... */
  1655. if (isNull)
  1656. elog(ERROR, "ctid is NULL");
  1657. /* Convert parameters needed by prepared statement to text form */
  1658. p_values = convert_prep_stmt_params(fmstate,
  1659. (ItemPointer) DatumGetPointer(datum),
  1660. slot);
  1661. /*
  1662. * Execute the prepared statement.
  1663. */
  1664. if (!PQsendQueryPrepared(fmstate->conn,
  1665. fmstate->p_name,
  1666. fmstate->p_nums,
  1667. p_values,
  1668. NULL,
  1669. NULL,
  1670. 0))
  1671. pgfdw_report_error(ERROR, NULL, fmstate->conn, false, fmstate->query);
  1672. /*
  1673. * Get the result, and check for success.
  1674. *
  1675. * We don't use a PG_TRY block here, so be careful not to throw error
  1676. * without releasing the PGresult.
  1677. */
  1678. res = pgfdw_get_result(fmstate->conn, fmstate->query);
  1679. if (PQresultStatus(res) !=
  1680. (fmstate->has_returning ? PGRES_TUPLES_OK : PGRES_COMMAND_OK))
  1681. pgfdw_report_error(ERROR, res, fmstate->conn, true, fmstate->query);
  1682. /* Check number of rows affected, and fetch RETURNING tuple if any */
  1683. if (fmstate->has_returning)
  1684. {
  1685. n_rows = PQntuples(res);
  1686. if (n_rows > 0)
  1687. store_returning_result(fmstate, slot, res);
  1688. }
  1689. else
  1690. n_rows = atoi(PQcmdTuples(res));
  1691. /* And clean up */
  1692. PQclear(res);
  1693. MemoryContextReset(fmstate->temp_cxt);
  1694. /* Return NULL if nothing was updated on the remote end */
  1695. return (n_rows > 0) ? slot : NULL;
  1696. }
  1697. /*
  1698. * postgresExecForeignDelete
  1699. * Delete one row from a foreign table
  1700. */
  1701. static TupleTableSlot *
  1702. postgresExecForeignDelete(EState *estate,
  1703. ResultRelInfo *resultRelInfo,
  1704. TupleTableSlot *slot,
  1705. TupleTableSlot *planSlot)
  1706. {
  1707. PgFdwModifyState *fmstate = (PgFdwModifyState *) resultRelInfo->ri_FdwState;
  1708. Datum datum;
  1709. bool isNull;
  1710. const char **p_values;
  1711. PGresult *res;
  1712. int n_rows;
  1713. /* Set up the prepared statement on the remote server, if we didn't yet */
  1714. if (!fmstate->p_name)
  1715. prepare_foreign_modify(fmstate);
  1716. /* Get the ctid that was passed up as a resjunk column */
  1717. datum = ExecGetJunkAttribute(planSlot,
  1718. fmstate->ctidAttno,
  1719. &isNull);
  1720. /* shouldn't ever get a null result... */
  1721. if (isNull)
  1722. elog(ERROR, "ctid is NULL");
  1723. /* Convert parameters needed by prepared statement to text form */
  1724. p_values = convert_prep_stmt_params(fmstate,
  1725. (ItemPointer) DatumGetPointer(datum),
  1726. NULL);
  1727. /*
  1728. * Execute the prepared statement.
  1729. */
  1730. if (!PQsendQueryPrepared(fmstate->conn,
  1731. fmstate->p_name,
  1732. fmstate->p_nums,
  1733. p_values,
  1734. NULL,
  1735. NULL,
  1736. 0))
  1737. pgfdw_report_error(ERROR, NULL, fmstate->conn, false, fmstate->query);
  1738. /*
  1739. * Get the result, and check for success.
  1740. *
  1741. * We don't use a PG_TRY block here, so be careful not to throw error
  1742. * without releasing the PGresult.
  1743. */
  1744. res = pgfdw_get_result(fmstate->conn, fmstate->query);
  1745. if (PQresultStatus(res) !=
  1746. (fmstate->has_returning ? PGRES_TUPLES_OK : PGRES_COMMAND_OK))
  1747. pgfdw_report_error(ERROR, res, fmstate->conn, true, fmstate->query);
  1748. /* Check number of rows affected, and fetch RETURNING tuple if any */
  1749. if (fmstate->has_returning)
  1750. {
  1751. n_rows = PQntuples(res);
  1752. if (n_rows > 0)
  1753. store_returning_result(fmstate, slot, res);
  1754. }
  1755. else
  1756. n_rows = atoi(PQcmdTuples(res));
  1757. /* And clean up */
  1758. PQclear(res);
  1759. MemoryContextReset(fmstate->temp_cxt);
  1760. /* Return NULL if nothing was deleted on the remote end */
  1761. return (n_rows > 0) ? slot : NULL;
  1762. }
  1763. /*
  1764. * postgresEndForeignModify
  1765. * Finish an insert/update/delete operation on a foreign table
  1766. */
  1767. static void
  1768. postgresEndForeignModify(EState *estate,
  1769. ResultRelInfo *resultRelInfo)
  1770. {
  1771. PgFdwModifyState *fmstate = (PgFdwModifyState *) resultRelInfo->ri_FdwState;
  1772. /* If fmstate is NULL, we are in EXPLAIN; nothing to do */
  1773. if (fmstate == NULL)
  1774. return;
  1775. /* Destroy the execution state */
  1776. finish_foreign_modify(fmstate);
  1777. }
  1778. /*
  1779. * postgresBeginForeignInsert
  1780. * Begin an insert operation on a foreign table
  1781. */
  1782. static void
  1783. postgresBeginForeignInsert(ModifyTableState *mtstate,
  1784. ResultRelInfo *resultRelInfo)
  1785. {
  1786. PgFdwModifyState *fmstate;
  1787. ModifyTable *plan = castNode(ModifyTable, mtstate->ps.plan);
  1788. EState *estate = mtstate->ps.state;
  1789. Index resultRelation = resultRelInfo->ri_RangeTableIndex;
  1790. Relation rel = resultRelInfo->ri_RelationDesc;
  1791. RangeTblEntry *rte;
  1792. TupleDesc tupdesc = RelationGetDescr(rel);
  1793. int attnum;
  1794. StringInfoData sql;
  1795. List *targetAttrs = NIL;
  1796. List *retrieved_attrs = NIL;
  1797. bool doNothing = false;
  1798. initStringInfo(&sql);
  1799. /* We transmit all columns that are defined in the foreign table. */
  1800. for (attnum = 1; attnum <= tupdesc->natts; attnum++)
  1801. {
  1802. Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1);
  1803. if (!attr->attisdropped)
  1804. targetAttrs = lappend_int(targetAttrs, attnum);
  1805. }
  1806. /* Check if we add the ON CONFLICT clause to the remote query. */
  1807. if (plan)
  1808. {
  1809. OnConflictAction onConflictAction = plan->onConflictAction;
  1810. /* We only support DO NOTHING without an inference specification. */
  1811. if (onConflictAction == ONCONFLICT_NOTHING)
  1812. doNothing = true;
  1813. else if (onConflictAction != ONCONFLICT_NONE)
  1814. elog(ERROR, "unexpected ON CONFLICT specification: %d",
  1815. (int) onConflictAction);
  1816. }
  1817. /*
  1818. * If the foreign table is a partition, we need to create a new RTE
  1819. * describing the foreign table for use by deparseInsertSql and
  1820. * create_foreign_modify() below, after first copying the parent's RTE and
  1821. * modifying some fields to describe the foreign partition to work on.
  1822. * However, if this is invoked by UPDATE, the existing RTE may already
  1823. * correspond to this partition if it is one of the UPDATE subplan target
  1824. * rels; in that case, we can just use the existing RTE as-is.
  1825. */
  1826. rte = exec_rt_fetch(resultRelation, estate);
  1827. if (rte->relid != RelationGetRelid(rel))
  1828. {
  1829. rte = copyObject(rte);
  1830. rte->relid = RelationGetRelid(rel);
  1831. rte->relkind = RELKIND_FOREIGN_TABLE;
  1832. /*
  1833. * For UPDATE, we must use the RT index of the first subplan target
  1834. * rel's RTE, because the core code would have built expressions for
  1835. * the partition, such as RETURNING, using that RT index as varno of
  1836. * Vars contained in those expressions.
  1837. */
  1838. if (plan && plan->operation == CMD_UPDATE &&
  1839. resultRelation == plan->rootRelation)
  1840. resultRelation = mtstate->resultRelInfo[0].ri_RangeTableIndex;
  1841. }
  1842. /* Construct the SQL command string. */
  1843. deparseInsertSql(&sql, rte, resultRelation, rel, targetAttrs, doNothing,
  1844. resultRelInfo->ri_WithCheckOptions,
  1845. resultRelInfo->ri_returningList,
  1846. &retrieved_attrs);
  1847. /* Construct an execution state. */
  1848. fmstate = create_foreign_modify(mtstate->ps.state,
  1849. rte,
  1850. resultRelInfo,
  1851. CMD_INSERT,
  1852. NULL,
  1853. sql.data,
  1854. targetAttrs,
  1855. retrieved_attrs != NIL,
  1856. retrieved_attrs);
  1857. resultRelInfo->ri_FdwState = fmstate;
  1858. }
  1859. /*
  1860. * postgresEndForeignInsert
  1861. * Finish an insert operation on a foreign table
  1862. */
  1863. static void
  1864. postgresEndForeignInsert(EState *estate,
  1865. ResultRelInfo *resultRelInfo)
  1866. {
  1867. PgFdwModifyState *fmstate = (PgFdwModifyState *) resultRelInfo->ri_FdwState;
  1868. Assert(fmstate != NULL);
  1869. /* Destroy the execution state */
  1870. finish_foreign_modify(fmstate);
  1871. }
  1872. /*
  1873. * postgresIsForeignRelUpdatable
  1874. * Determine whether a foreign table supports INSERT, UPDATE and/or
  1875. * DELETE.
  1876. */
  1877. static int
  1878. postgresIsForeignRelUpdatable(Relation rel)
  1879. {
  1880. bool updatable;
  1881. ForeignTable *table;
  1882. ForeignServer *server;
  1883. ListCell *lc;
  1884. /*
  1885. * By default, all postgres_fdw foreign tables are assumed updatable. This
  1886. * can be overridden by a per-server setting, which in turn can be
  1887. * overridden by a per-table setting.
  1888. */
  1889. updatable = true;
  1890. table = GetForeignTable(RelationGetRelid(rel));
  1891. server = GetForeignServer(table->serverid);
  1892. foreach(lc, server->options)
  1893. {
  1894. DefElem *def = (DefElem *) lfirst(lc);
  1895. if (strcmp(def->defname, "updatable") == 0)
  1896. updatable = defGetBoolean(def);
  1897. }
  1898. foreach(lc, table->options)
  1899. {
  1900. DefElem *def = (DefElem *) lfirst(lc);
  1901. if (strcmp(def->defname, "updatable") == 0)
  1902. updatable = defGetBoolean(def);
  1903. }
  1904. /*
  1905. * Currently "updatable" means support for INSERT, UPDATE and DELETE.
  1906. */
  1907. return updatable ?
  1908. (1 << CMD_INSERT) | (1 << CMD_UPDATE) | (1 << CMD_DELETE) : 0;
  1909. }
  1910. /*
  1911. * postgresRecheckForeignScan
  1912. * Execute a local join execution plan for a foreign join
  1913. */
  1914. static bool
  1915. postgresRecheckForeignScan(ForeignScanState *node, TupleTableSlot *slot)
  1916. {
  1917. Index scanrelid = ((Scan *) node->ss.ps.plan)->scanrelid;
  1918. PlanState *outerPlan = outerPlanState(node);
  1919. TupleTableSlot *result;
  1920. /* For base foreign relations, it suffices to set fdw_recheck_quals */
  1921. if (scanrelid > 0)
  1922. return true;
  1923. Assert(outerPlan != NULL);
  1924. /* Execute a local join execution plan */
  1925. result = ExecProcNode(outerPlan);
  1926. if (TupIsNull(result))
  1927. return false;
  1928. /* Store result in the given slot */
  1929. ExecCopySlot(slot, result);
  1930. return true;
  1931. }
  1932. /*
  1933. * postgresPlanDirectModify
  1934. * Consider a direct foreign table modification
  1935. *
  1936. * Decide whether it is safe to modify a foreign table directly, and if so,
  1937. * rewrite subplan accordingly.
  1938. */
  1939. static bool
  1940. postgresPlanDirectModify(PlannerInfo *root,
  1941. ModifyTable *plan,
  1942. Index resultRelation,
  1943. int subplan_index)
  1944. {
  1945. CmdType operation = plan->operation;
  1946. Plan *subplan;
  1947. RelOptInfo *foreignrel;
  1948. RangeTblEntry *rte;
  1949. PgFdwRelationInfo *fpinfo;
  1950. Relation rel;
  1951. StringInfoData sql;
  1952. ForeignScan *fscan;
  1953. List *targetAttrs = NIL;
  1954. List *remote_exprs;
  1955. List *params_list = NIL;
  1956. List *returningList = NIL;
  1957. List *retrieved_attrs = NIL;
  1958. /*
  1959. * Decide whether it is safe to modify a foreign table directly.
  1960. */
  1961. /*
  1962. * The table modification must be an UPDATE or DELETE.
  1963. */
  1964. if (operation != CMD_UPDATE && operation != CMD_DELETE)
  1965. return false;
  1966. /*
  1967. * It's unsafe to modify a foreign table directly if there are any local
  1968. * joins needed.
  1969. */
  1970. subplan = (Plan *) list_nth(plan->plans, subplan_index);
  1971. if (!IsA(subplan, ForeignScan))
  1972. return false;
  1973. fscan = (ForeignScan *) subplan;
  1974. /*
  1975. * It's unsafe to modify a foreign table directly if there are any quals
  1976. * that should be evaluated locally.
  1977. */
  1978. if (subplan->qual != NIL)
  1979. return false;
  1980. /* Safe to fetch data about the target foreign rel */
  1981. if (fscan->scan.scanrelid == 0)
  1982. {
  1983. foreignrel = find_join_rel(root, fscan->fs_relids);
  1984. /* We should have a rel for this foreign join. */
  1985. Assert(foreignrel);
  1986. }
  1987. else
  1988. foreignrel = root->simple_rel_array[resultRelation];
  1989. rte = root->simple_rte_array[resultRelation];
  1990. fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
  1991. /*
  1992. * It's unsafe to update a foreign table directly, if any expressions to
  1993. * assign to the target columns are unsafe to evaluate remotely.
  1994. */
  1995. if (operation == CMD_UPDATE)
  1996. {
  1997. int col;
  1998. /*
  1999. * We transmit only columns that were explicitly targets of the
  2000. * UPDATE, so as to avoid unnecessary data transmission.
  2001. */
  2002. col = -1;
  2003. while ((col = bms_next_member(rte->updatedCols, col)) >= 0)
  2004. {
  2005. /* bit numbers are offset by FirstLowInvalidHeapAttributeNumber */
  2006. AttrNumber attno = col + FirstLowInvalidHeapAttributeNumber;
  2007. TargetEntry *tle;
  2008. if (attno <= InvalidAttrNumber) /* shouldn't happen */
  2009. elog(ERROR, "system-column update is not supported");
  2010. tle = get_tle_by_resno(subplan->targetlist, attno);
  2011. if (!tle)
  2012. elog(ERROR, "attribute number %d not found in subplan targetlist",
  2013. attno);
  2014. if (!is_foreign_expr(root, foreignrel, (Expr *) tle->expr))
  2015. return false;
  2016. targetAttrs = lappend_int(targetAttrs, attno);
  2017. }
  2018. }
  2019. /*
  2020. * Ok, rewrite subplan so as to modify the foreign table directly.
  2021. */
  2022. initStringInfo(&sql);
  2023. /*
  2024. * Core code already has some lock on each rel being planned, so we can
  2025. * use NoLock here.
  2026. */
  2027. rel = heap_open(rte->relid, NoLock);
  2028. /*
  2029. * Recall the qual clauses that must be evaluated remotely. (These are
  2030. * bare clauses not RestrictInfos, but deparse.c's appendConditions()
  2031. * doesn't care.)
  2032. */
  2033. remote_exprs = fpinfo->final_remote_exprs;
  2034. /*
  2035. * Extract the relevant RETURNING list if any.
  2036. */
  2037. if (plan->returningLists)
  2038. {
  2039. returningList = (List *) list_nth(plan->returningLists, subplan_index);
  2040. /*
  2041. * When performing an UPDATE/DELETE .. RETURNING on a join directly,
  2042. * we fetch from the foreign server any Vars specified in RETURNING
  2043. * that refer not only to the target relation but to non-target
  2044. * relations. So we'll deparse them into the RETURNING clause of the
  2045. * remote query; use a targetlist consisting of them instead, which
  2046. * will be adjusted to be new fdw_scan_tlist of the foreign-scan plan
  2047. * node below.
  2048. */
  2049. if (fscan->scan.scanrelid == 0)
  2050. returningList = build_remote_returning(resultRelation, rel,
  2051. returningList);
  2052. }
  2053. /*
  2054. * Construct the SQL command string.
  2055. */
  2056. switch (operation)
  2057. {
  2058. case CMD_UPDATE:
  2059. deparseDirectUpdateSql(&sql, root, resultRelation, rel,
  2060. foreignrel,
  2061. ((Plan *) fscan)->targetlist,
  2062. targetAttrs,
  2063. remote_exprs, &params_list,
  2064. returningList, &retrieved_attrs);
  2065. break;
  2066. case CMD_DELETE:
  2067. deparseDirectDeleteSql(&sql, root, resultRelation, rel,
  2068. foreignrel,
  2069. remote_exprs, &params_list,
  2070. returningList, &retrieved_attrs);
  2071. break;
  2072. default:
  2073. elog(ERROR, "unexpected operation: %d", (int) operation);
  2074. break;
  2075. }
  2076. /*
  2077. * Update the operation info.
  2078. */
  2079. fscan->operation = operation;
  2080. /*
  2081. * Update the fdw_exprs list that will be available to the executor.
  2082. */
  2083. fscan->fdw_exprs = params_list;
  2084. /*
  2085. * Update the fdw_private list that will be available to the executor.
  2086. * Items in the list must match enum FdwDirectModifyPrivateIndex, above.
  2087. */
  2088. fscan->fdw_private = list_make4(makeString(sql.data),
  2089. makeInteger((retrieved_attrs != NIL)),
  2090. retrieved_attrs,
  2091. makeInteger(plan->canSetTag));
  2092. /*
  2093. * Update the foreign-join-related fields.
  2094. */
  2095. if (fscan->scan.scanrelid == 0)
  2096. {
  2097. /* No need for the outer subplan. */
  2098. fscan->scan.plan.lefttree = NULL;
  2099. /* Build new fdw_scan_tlist if UPDATE/DELETE .. RETURNING. */
  2100. if (returningList)
  2101. rebuild_fdw_scan_tlist(fscan, returningList);
  2102. }
  2103. heap_close(rel, NoLock);
  2104. return true;
  2105. }
  2106. /*
  2107. * postgresBeginDirectModify
  2108. * Prepare a direct foreign table modification
  2109. */
  2110. static void
  2111. postgresBeginDirectModify(ForeignScanState *node, int eflags)
  2112. {
  2113. ForeignScan *fsplan = (ForeignScan *) node->ss.ps.plan;
  2114. EState *estate = node->ss.ps.state;
  2115. PgFdwDirectModifyState *dmstate;
  2116. Index rtindex;
  2117. RangeTblEntry *rte;
  2118. Oid userid;
  2119. ForeignTable *table;
  2120. UserMapping *user;
  2121. int numParams;
  2122. /*
  2123. * Do nothing in EXPLAIN (no ANALYZE) case. node->fdw_state stays NULL.
  2124. */
  2125. if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
  2126. return;
  2127. /*
  2128. * We'll save private state in node->fdw_state.
  2129. */
  2130. dmstate = (PgFdwDirectModifyState *) palloc0(sizeof(PgFdwDirectModifyState));
  2131. node->fdw_state = (void *) dmstate;
  2132. /*
  2133. * Identify which user to do the remote access as. This should match what
  2134. * ExecCheckRTEPerms() does.
  2135. */
  2136. rtindex = estate->es_result_relation_info->ri_RangeTableIndex;
  2137. rte = exec_rt_fetch(rtindex, estate);
  2138. userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
  2139. /* Get info about foreign table. */
  2140. if (fsplan->scan.scanrelid == 0)
  2141. dmstate->rel = ExecOpenScanRelation(estate, rtindex, eflags);
  2142. else
  2143. dmstate->rel = node->ss.ss_currentRelation;
  2144. table = GetForeignTable(RelationGetRelid(dmstate->rel));
  2145. user = GetUserMapping(userid, table->serverid);
  2146. /*
  2147. * Get connection to the foreign server. Connection manager will
  2148. * establish new connection if necessary.
  2149. */
  2150. dmstate->conn = GetConnection(user, false);
  2151. /* Update the foreign-join-related fields. */
  2152. if (fsplan->scan.scanrelid == 0)
  2153. {
  2154. /* Save info about foreign table. */
  2155. dmstate->resultRel = dmstate->rel;
  2156. /*
  2157. * Set dmstate->rel to NULL to teach get_returning_data() and
  2158. * make_tuple_from_result_row() that columns fetched from the remote
  2159. * server are described by fdw_scan_tlist of the foreign-scan plan
  2160. * node, not the tuple descriptor for the target relation.
  2161. */
  2162. dmstate->rel = NULL;
  2163. }
  2164. /* Initialize state variable */
  2165. dmstate->num_tuples = -1; /* -1 means not set yet */
  2166. /* Get private info created by planner functions. */
  2167. dmstate->query = strVal(list_nth(fsplan->fdw_private,
  2168. FdwDirectModifyPrivateUpdateSql));
  2169. dmstate->has_returning = intVal(list_nth(fsplan->fdw_private,
  2170. FdwDirectModifyPrivateHasReturning));
  2171. dmstate->retrieved_attrs = (List *) list_nth(fsplan->fdw_private,
  2172. FdwDirectModifyPrivateRetrievedAttrs);
  2173. dmstate->set_processed = intVal(list_nth(fsplan->fdw_private,
  2174. FdwDirectModifyPrivateSetProcessed));
  2175. /* Create context for per-tuple temp workspace. */
  2176. dmstate->temp_cxt = AllocSetContextCreate(estate->es_query_cxt,
  2177. "postgres_fdw temporary data",
  2178. ALLOCSET_SMALL_SIZES);
  2179. /* Prepare for input conversion of RETURNING results. */
  2180. if (dmstate->has_returning)
  2181. {
  2182. TupleDesc tupdesc;
  2183. if (fsplan->scan.scanrelid == 0)
  2184. tupdesc = node->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
  2185. else
  2186. tupdesc = RelationGetDescr(dmstate->rel);
  2187. dmstate->attinmeta = TupleDescGetAttInMetadata(tupdesc);
  2188. /*
  2189. * When performing an UPDATE/DELETE .. RETURNING on a join directly,
  2190. * initialize a filter to extract an updated/deleted tuple from a scan
  2191. * tuple.
  2192. */
  2193. if (fsplan->scan.scanrelid == 0)
  2194. init_returning_filter(dmstate, fsplan->fdw_scan_tlist, rtindex);
  2195. }
  2196. /*
  2197. * Prepare for processing of parameters used in remote query, if any.
  2198. */
  2199. numParams = list_length(fsplan->fdw_exprs);
  2200. dmstate->numParams = numParams;
  2201. if (numParams > 0)
  2202. prepare_query_params((PlanState *) node,
  2203. fsplan->fdw_exprs,
  2204. numParams,
  2205. &dmstate->param_flinfo,
  2206. &dmstate->param_exprs,
  2207. &dmstate->param_values);
  2208. }
  2209. /*
  2210. * postgresIterateDirectModify
  2211. * Execute a direct foreign table modification
  2212. */
  2213. static TupleTableSlot *
  2214. postgresIterateDirectModify(ForeignScanState *node)
  2215. {
  2216. PgFdwDirectModifyState *dmstate = (PgFdwDirectModifyState *) node->fdw_state;
  2217. EState *estate = node->ss.ps.state;
  2218. ResultRelInfo *resultRelInfo = estate->es_result_relation_info;
  2219. /*
  2220. * If this is the first call after Begin, execute the statement.
  2221. */
  2222. if (dmstate->num_tuples == -1)
  2223. execute_dml_stmt(node);
  2224. /*
  2225. * If the local query doesn't specify RETURNING, just clear tuple slot.
  2226. */
  2227. if (!resultRelInfo->ri_projectReturning)
  2228. {
  2229. TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
  2230. Instrumentation *instr = node->ss.ps.instrument;
  2231. Assert(!dmstate->has_returning);
  2232. /* Increment the command es_processed count if necessary. */
  2233. if (dmstate->set_processed)
  2234. estate->es_processed += dmstate->num_tuples;
  2235. /* Increment the tuple count for EXPLAIN ANALYZE if necessary. */
  2236. if (instr)
  2237. instr->tuplecount += dmstate->num_tuples;
  2238. return ExecClearTuple(slot);
  2239. }
  2240. /*
  2241. * Get the next RETURNING tuple.
  2242. */
  2243. return get_returning_data(node);
  2244. }
  2245. /*
  2246. * postgresEndDirectModify
  2247. * Finish a direct foreign table modification
  2248. */
  2249. static void
  2250. postgresEndDirectModify(ForeignScanState *node)
  2251. {
  2252. PgFdwDirectModifyState *dmstate = (PgFdwDirectModifyState *) node->fdw_state;
  2253. /* if dmstate is NULL, we are in EXPLAIN; nothing to do */
  2254. if (dmstate == NULL)
  2255. return;
  2256. /* Release PGresult */
  2257. if (dmstate->result)
  2258. PQclear(dmstate->result);
  2259. /* Release remote connection */
  2260. ReleaseConnection(dmstate->conn);
  2261. dmstate->conn = NULL;
  2262. /* MemoryContext will be deleted automatically. */
  2263. }
  2264. /*
  2265. * postgresExplainForeignScan
  2266. * Produce extra output for EXPLAIN of a ForeignScan on a foreign table
  2267. */
  2268. static void
  2269. postgresExplainForeignScan(ForeignScanState *node, ExplainState *es)
  2270. {
  2271. List *fdw_private;
  2272. char *sql;
  2273. char *relations;
  2274. fdw_private = ((ForeignScan *) node->ss.ps.plan)->fdw_private;
  2275. /*
  2276. * Add names of relation handled by the foreign scan when the scan is a
  2277. * join
  2278. */
  2279. if (list_length(fdw_private) > FdwScanPrivateRelations)
  2280. {
  2281. relations = strVal(list_nth(fdw_private, FdwScanPrivateRelations));
  2282. ExplainPropertyText("Relations", relations, es);
  2283. }
  2284. /*
  2285. * Add remote query, when VERBOSE option is specified.
  2286. */
  2287. if (es->verbose)
  2288. {
  2289. sql = strVal(list_nth(fdw_private, FdwScanPrivateSelectSql));
  2290. ExplainPropertyText("Remote SQL", sql, es);
  2291. }
  2292. }
  2293. /*
  2294. * postgresExplainForeignModify
  2295. * Produce extra output for EXPLAIN of a ModifyTable on a foreign table
  2296. */
  2297. static void
  2298. postgresExplainForeignModify(ModifyTableState *mtstate,
  2299. ResultRelInfo *rinfo,
  2300. List *fdw_private,
  2301. int subplan_index,
  2302. ExplainState *es)
  2303. {
  2304. if (es->verbose)
  2305. {
  2306. char *sql = strVal(list_nth(fdw_private,
  2307. FdwModifyPrivateUpdateSql));
  2308. ExplainPropertyText("Remote SQL", sql, es);
  2309. }
  2310. }
  2311. /*
  2312. * postgresExplainDirectModify
  2313. * Produce extra output for EXPLAIN of a ForeignScan that modifies a
  2314. * foreign table directly
  2315. */
  2316. static void
  2317. postgresExplainDirectModify(ForeignScanState *node, ExplainState *es)
  2318. {
  2319. List *fdw_private;
  2320. char *sql;
  2321. if (es->verbose)
  2322. {
  2323. fdw_private = ((ForeignScan *) node->ss.ps.plan)->fdw_private;
  2324. sql = strVal(list_nth(fdw_private, FdwDirectModifyPrivateUpdateSql));
  2325. ExplainPropertyText("Remote SQL", sql, es);
  2326. }
  2327. }
  2328. /*
  2329. * estimate_path_cost_size
  2330. * Get cost and size estimates for a foreign scan on given foreign relation
  2331. * either a base relation or a join between foreign relations or an upper
  2332. * relation containing foreign relations.
  2333. *
  2334. * param_join_conds are the parameterization clauses with outer relations.
  2335. * pathkeys specify the expected sort order if any for given path being costed.
  2336. *
  2337. * The function returns the cost and size estimates in p_row, p_width,
  2338. * p_startup_cost and p_total_cost variables.
  2339. */
  2340. static void
  2341. estimate_path_cost_size(PlannerInfo *root,
  2342. RelOptInfo *foreignrel,
  2343. List *param_join_conds,
  2344. List *pathkeys,
  2345. double *p_rows, int *p_width,
  2346. Cost *p_startup_cost, Cost *p_total_cost)
  2347. {
  2348. PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
  2349. double rows;
  2350. double retrieved_rows;
  2351. int width;
  2352. Cost startup_cost;
  2353. Cost total_cost;
  2354. Cost cpu_per_tuple;
  2355. /*
  2356. * If the table or the server is configured to use remote estimates,
  2357. * connect to the foreign server and execute EXPLAIN to estimate the
  2358. * number of rows selected by the restriction+join clauses. Otherwise,
  2359. * estimate rows using whatever statistics we have locally, in a way
  2360. * similar to ordinary tables.
  2361. */
  2362. if (fpinfo->use_remote_estimate)
  2363. {
  2364. List *remote_param_join_conds;
  2365. List *local_param_join_conds;
  2366. StringInfoData sql;
  2367. PGconn *conn;
  2368. Selectivity local_sel;
  2369. QualCost local_cost;
  2370. List *fdw_scan_tlist = NIL;
  2371. List *remote_conds;
  2372. /* Required only to be passed to deparseSelectStmtForRel */
  2373. List *retrieved_attrs;
  2374. /*
  2375. * param_join_conds might contain both clauses that are safe to send
  2376. * across, and clauses that aren't.
  2377. */
  2378. classifyConditions(root, foreignrel, param_join_conds,
  2379. &remote_param_join_conds, &local_param_join_conds);
  2380. /* Build the list of columns to be fetched from the foreign server. */
  2381. if (IS_JOIN_REL(foreignrel) || IS_UPPER_REL(foreignrel))
  2382. fdw_scan_tlist = build_tlist_to_deparse(foreignrel);
  2383. else
  2384. fdw_scan_tlist = NIL;
  2385. /*
  2386. * The complete list of remote conditions includes everything from
  2387. * baserestrictinfo plus any extra join_conds relevant to this
  2388. * particular path.
  2389. */
  2390. remote_conds = list_concat(list_copy(remote_param_join_conds),
  2391. fpinfo->remote_conds);
  2392. /*
  2393. * Construct EXPLAIN query including the desired SELECT, FROM, and
  2394. * WHERE clauses. Params and other-relation Vars are replaced by dummy
  2395. * values, so don't request params_list.
  2396. */
  2397. initStringInfo(&sql);
  2398. appendStringInfoString(&sql, "EXPLAIN ");
  2399. deparseSelectStmtForRel(&sql, root, foreignrel, fdw_scan_tlist,
  2400. remote_conds, pathkeys, false,
  2401. &retrieved_attrs, NULL);
  2402. /* Get the remote estimate */
  2403. conn = GetConnection(fpinfo->user, false);
  2404. get_remote_estimate(sql.data, conn, &rows, &width,
  2405. &startup_cost, &total_cost);
  2406. ReleaseConnection(conn);
  2407. retrieved_rows = rows;
  2408. /* Factor in the selectivity of the locally-checked quals */
  2409. local_sel = clauselist_selectivity(root,
  2410. local_param_join_conds,
  2411. foreignrel->relid,
  2412. JOIN_INNER,
  2413. NULL);
  2414. local_sel *= fpinfo->local_conds_sel;
  2415. rows = clamp_row_est(rows * local_sel);
  2416. /* Add in the eval cost of the locally-checked quals */
  2417. startup_cost += fpinfo->local_conds_cost.startup;
  2418. total_cost += fpinfo->local_conds_cost.per_tuple * retrieved_rows;
  2419. cost_qual_eval(&local_cost, local_param_join_conds, root);
  2420. startup_cost += local_cost.startup;
  2421. total_cost += local_cost.per_tuple * retrieved_rows;
  2422. }
  2423. else
  2424. {
  2425. Cost run_cost = 0;
  2426. /*
  2427. * We don't support join conditions in this mode (hence, no
  2428. * parameterized paths can be made).
  2429. */
  2430. Assert(param_join_conds == NIL);
  2431. /*
  2432. * Use rows/width estimates made by set_baserel_size_estimates() for
  2433. * base foreign relations and set_joinrel_size_estimates() for join
  2434. * between foreign relations.
  2435. */
  2436. rows = foreignrel->rows;
  2437. width = foreignrel->reltarget->width;
  2438. /* Back into an estimate of the number of retrieved rows. */
  2439. retrieved_rows = clamp_row_est(rows / fpinfo->local_conds_sel);
  2440. /*
  2441. * We will come here again and again with different set of pathkeys
  2442. * that caller wants to cost. We don't need to calculate the cost of
  2443. * bare scan each time. Instead, use the costs if we have cached them
  2444. * already.
  2445. */
  2446. if (fpinfo->rel_startup_cost > 0 && fpinfo->rel_total_cost > 0)
  2447. {
  2448. startup_cost = fpinfo->rel_startup_cost;
  2449. run_cost = fpinfo->rel_total_cost - fpinfo->rel_startup_cost;
  2450. }
  2451. else if (IS_JOIN_REL(foreignrel))
  2452. {
  2453. PgFdwRelationInfo *fpinfo_i;
  2454. PgFdwRelationInfo *fpinfo_o;
  2455. QualCost join_cost;
  2456. QualCost remote_conds_cost;
  2457. double nrows;
  2458. /* For join we expect inner and outer relations set */
  2459. Assert(fpinfo->innerrel && fpinfo->outerrel);
  2460. fpinfo_i = (PgFdwRelationInfo *) fpinfo->innerrel->fdw_private;
  2461. fpinfo_o = (PgFdwRelationInfo *) fpinfo->outerrel->fdw_private;
  2462. /* Estimate of number of rows in cross product */
  2463. nrows = fpinfo_i->rows * fpinfo_o->rows;
  2464. /* Clamp retrieved rows estimate to at most size of cross product */
  2465. retrieved_rows = Min(retrieved_rows, nrows);
  2466. /*
  2467. * The cost of foreign join is estimated as cost of generating
  2468. * rows for the joining relations + cost for applying quals on the
  2469. * rows.
  2470. */
  2471. /*
  2472. * Calculate the cost of clauses pushed down to the foreign server
  2473. */
  2474. cost_qual_eval(&remote_conds_cost, fpinfo->remote_conds, root);
  2475. /* Calculate the cost of applying join clauses */
  2476. cost_qual_eval(&join_cost, fpinfo->joinclauses, root);
  2477. /*
  2478. * Startup cost includes startup cost of joining relations and the
  2479. * startup cost for join and other clauses. We do not include the
  2480. * startup cost specific to join strategy (e.g. setting up hash
  2481. * tables) since we do not know what strategy the foreign server
  2482. * is going to use.
  2483. */
  2484. startup_cost = fpinfo_i->rel_startup_cost + fpinfo_o->rel_startup_cost;
  2485. startup_cost += join_cost.startup;
  2486. startup_cost += remote_conds_cost.startup;
  2487. startup_cost += fpinfo->local_conds_cost.startup;
  2488. /*
  2489. * Run time cost includes:
  2490. *
  2491. * 1. Run time cost (total_cost - startup_cost) of relations being
  2492. * joined
  2493. *
  2494. * 2. Run time cost of applying join clauses on the cross product
  2495. * of the joining relations.
  2496. *
  2497. * 3. Run time cost of applying pushed down other clauses on the
  2498. * result of join
  2499. *
  2500. * 4. Run time cost of applying nonpushable other clauses locally
  2501. * on the result fetched from the foreign server.
  2502. */
  2503. run_cost = fpinfo_i->rel_total_cost - fpinfo_i->rel_startup_cost;
  2504. run_cost += fpinfo_o->rel_total_cost - fpinfo_o->rel_startup_cost;
  2505. run_cost += nrows * join_cost.per_tuple;
  2506. nrows = clamp_row_est(nrows * fpinfo->joinclause_sel);
  2507. run_cost += nrows * remote_conds_cost.per_tuple;
  2508. run_cost += fpinfo->local_conds_cost.per_tuple * retrieved_rows;
  2509. }
  2510. else if (IS_UPPER_REL(foreignrel))
  2511. {
  2512. PgFdwRelationInfo *ofpinfo;
  2513. PathTarget *ptarget = foreignrel->reltarget;
  2514. AggClauseCosts aggcosts;
  2515. double input_rows;
  2516. int numGroupCols;
  2517. double numGroups = 1;
  2518. /* Make sure the core code set the pathtarget. */
  2519. Assert(ptarget != NULL);
  2520. /*
  2521. * This cost model is mixture of costing done for sorted and
  2522. * hashed aggregates in cost_agg(). We are not sure which
  2523. * strategy will be considered at remote side, thus for
  2524. * simplicity, we put all startup related costs in startup_cost
  2525. * and all finalization and run cost are added in total_cost.
  2526. */
  2527. ofpinfo = (PgFdwRelationInfo *) fpinfo->outerrel->fdw_private;
  2528. /* Get rows and width from input rel */
  2529. input_rows = ofpinfo->rows;
  2530. width = ofpinfo->width;
  2531. /* Collect statistics about aggregates for estimating costs. */
  2532. MemSet(&aggcosts, 0, sizeof(AggClauseCosts));
  2533. if (root->parse->hasAggs)
  2534. {
  2535. get_agg_clause_costs(root, (Node *) fpinfo->grouped_tlist,
  2536. AGGSPLIT_SIMPLE, &aggcosts);
  2537. /*
  2538. * The cost of aggregates in the HAVING qual will be the same
  2539. * for each child as it is for the parent, so there's no need
  2540. * to use a translated version of havingQual.
  2541. */
  2542. get_agg_clause_costs(root, (Node *) root->parse->havingQual,
  2543. AGGSPLIT_SIMPLE, &aggcosts);
  2544. }
  2545. /* Get number of grouping columns and possible number of groups */
  2546. numGroupCols = list_length(root->parse->groupClause);
  2547. numGroups = estimate_num_groups(root,
  2548. get_sortgrouplist_exprs(root->parse->groupClause,
  2549. fpinfo->grouped_tlist),
  2550. input_rows, NULL);
  2551. /*
  2552. * Get the retrieved_rows and rows estimates. If there are HAVING
  2553. * quals, account for their selectivity.
  2554. */
  2555. if (root->parse->havingQual)
  2556. {
  2557. /* Factor in the selectivity of the remotely-checked quals */
  2558. retrieved_rows =
  2559. clamp_row_est(numGroups *
  2560. clauselist_selectivity(root,
  2561. fpinfo->remote_conds,
  2562. 0,
  2563. JOIN_INNER,
  2564. NULL));
  2565. /* Factor in the selectivity of the locally-checked quals */
  2566. rows = clamp_row_est(retrieved_rows * fpinfo->local_conds_sel);
  2567. }
  2568. else
  2569. {
  2570. rows = retrieved_rows = numGroups;
  2571. }
  2572. /*-----
  2573. * Startup cost includes:
  2574. * 1. Startup cost for underneath input relation
  2575. * 2. Cost of performing aggregation, per cost_agg()
  2576. * 3. Startup cost for PathTarget eval
  2577. *-----
  2578. */
  2579. startup_cost = ofpinfo->rel_startup_cost;
  2580. startup_cost += aggcosts.transCost.startup;
  2581. startup_cost += aggcosts.transCost.per_tuple * input_rows;
  2582. startup_cost += (cpu_operator_cost * numGroupCols) * input_rows;
  2583. startup_cost += ptarget->cost.startup;
  2584. /*-----
  2585. * Run time cost includes:
  2586. * 1. Run time cost of underneath input relation
  2587. * 2. Run time cost of performing aggregation, per cost_agg()
  2588. * 3. PathTarget eval cost for each output row
  2589. *-----
  2590. */
  2591. run_cost = ofpinfo->rel_total_cost - ofpinfo->rel_startup_cost;
  2592. run_cost += aggcosts.finalCost * numGroups;
  2593. run_cost += cpu_tuple_cost * numGroups;
  2594. run_cost += ptarget->cost.per_tuple * numGroups;
  2595. /* Accout for the eval cost of HAVING quals, if any */
  2596. if (root->parse->havingQual)
  2597. {
  2598. QualCost remote_cost;
  2599. /* Add in the eval cost of the remotely-checked quals */
  2600. cost_qual_eval(&remote_cost, fpinfo->remote_conds, root);
  2601. startup_cost += remote_cost.startup;
  2602. run_cost += remote_cost.per_tuple * numGroups;
  2603. /* Add in the eval cost of the locally-checked quals */
  2604. startup_cost += fpinfo->local_conds_cost.startup;
  2605. run_cost += fpinfo->local_conds_cost.per_tuple * retrieved_rows;
  2606. }
  2607. }
  2608. else
  2609. {
  2610. /* Clamp retrieved rows estimates to at most foreignrel->tuples. */
  2611. retrieved_rows = Min(retrieved_rows, foreignrel->tuples);
  2612. /*
  2613. * Cost as though this were a seqscan, which is pessimistic. We
  2614. * effectively imagine the local_conds are being evaluated
  2615. * remotely, too.
  2616. */
  2617. startup_cost = 0;
  2618. run_cost = 0;
  2619. run_cost += seq_page_cost * foreignrel->pages;
  2620. startup_cost += foreignrel->baserestrictcost.startup;
  2621. cpu_per_tuple = cpu_tuple_cost + foreignrel->baserestrictcost.per_tuple;
  2622. run_cost += cpu_per_tuple * foreignrel->tuples;
  2623. }
  2624. /*
  2625. * Without remote estimates, we have no real way to estimate the cost
  2626. * of generating sorted output. It could be free if the query plan
  2627. * the remote side would have chosen generates properly-sorted output
  2628. * anyway, but in most cases it will cost something. Estimate a value
  2629. * high enough that we won't pick the sorted path when the ordering
  2630. * isn't locally useful, but low enough that we'll err on the side of
  2631. * pushing down the ORDER BY clause when it's useful to do so.
  2632. */
  2633. if (pathkeys != NIL)
  2634. {
  2635. startup_cost *= DEFAULT_FDW_SORT_MULTIPLIER;
  2636. run_cost *= DEFAULT_FDW_SORT_MULTIPLIER;
  2637. }
  2638. total_cost = startup_cost + run_cost;
  2639. }
  2640. /*
  2641. * Cache the costs for scans without any pathkeys or parameterization
  2642. * before adding the costs for transferring data from the foreign server.
  2643. * These costs are useful for costing the join between this relation and
  2644. * another foreign relation or to calculate the costs of paths with
  2645. * pathkeys for this relation, when the costs can not be obtained from the
  2646. * foreign server. This function will be called at least once for every
  2647. * foreign relation without pathkeys and parameterization.
  2648. */
  2649. if (pathkeys == NIL && param_join_conds == NIL)
  2650. {
  2651. fpinfo->rel_startup_cost = startup_cost;
  2652. fpinfo->rel_total_cost = total_cost;
  2653. }
  2654. /*
  2655. * Add some additional cost factors to account for connection overhead
  2656. * (fdw_startup_cost), transferring data across the network
  2657. * (fdw_tuple_cost per retrieved row), and local manipulation of the data
  2658. * (cpu_tuple_cost per retrieved row).
  2659. */
  2660. startup_cost += fpinfo->fdw_startup_cost;
  2661. total_cost += fpinfo->fdw_startup_cost;
  2662. total_cost += fpinfo->fdw_tuple_cost * retrieved_rows;
  2663. total_cost += cpu_tuple_cost * retrieved_rows;
  2664. /* Return results. */
  2665. *p_rows = rows;
  2666. *p_width = width;
  2667. *p_startup_cost = startup_cost;
  2668. *p_total_cost = total_cost;
  2669. }
  2670. /*
  2671. * Estimate costs of executing a SQL statement remotely.
  2672. * The given "sql" must be an EXPLAIN command.
  2673. */
  2674. static void
  2675. get_remote_estimate(const char *sql, PGconn *conn,
  2676. double *rows, int *width,
  2677. Cost *startup_cost, Cost *total_cost)
  2678. {
  2679. PGresult *volatile res = NULL;
  2680. /* PGresult must be released before leaving this function. */
  2681. PG_TRY();
  2682. {
  2683. char *line;
  2684. char *p;
  2685. int n;
  2686. /*
  2687. * Execute EXPLAIN remotely.
  2688. */
  2689. res = pgfdw_exec_query(conn, sql);
  2690. if (PQresultStatus(res) != PGRES_TUPLES_OK)
  2691. pgfdw_report_error(ERROR, res, conn, false, sql);
  2692. /*
  2693. * Extract cost numbers for topmost plan node. Note we search for a
  2694. * left paren from the end of the line to avoid being confused by
  2695. * other uses of parentheses.
  2696. */
  2697. line = PQgetvalue(res, 0, 0);
  2698. p = strrchr(line, '(');
  2699. if (p == NULL)
  2700. elog(ERROR, "could not interpret EXPLAIN output: \"%s\"", line);
  2701. n = sscanf(p, "(cost=%lf..%lf rows=%lf width=%d)",
  2702. startup_cost, total_cost, rows, width);
  2703. if (n != 4)
  2704. elog(ERROR, "could not interpret EXPLAIN output: \"%s\"", line);
  2705. PQclear(res);
  2706. res = NULL;
  2707. }
  2708. PG_CATCH();
  2709. {
  2710. if (res)
  2711. PQclear(res);
  2712. PG_RE_THROW();
  2713. }
  2714. PG_END_TRY();
  2715. }
  2716. /*
  2717. * Detect whether we want to process an EquivalenceClass member.
  2718. *
  2719. * This is a callback for use by generate_implied_equalities_for_column.
  2720. */
  2721. static bool
  2722. ec_member_matches_foreign(PlannerInfo *root, RelOptInfo *rel,
  2723. EquivalenceClass *ec, EquivalenceMember *em,
  2724. void *arg)
  2725. {
  2726. ec_member_foreign_arg *state = (ec_member_foreign_arg *) arg;
  2727. Expr *expr = em->em_expr;
  2728. /*
  2729. * If we've identified what we're processing in the current scan, we only
  2730. * want to match that expression.
  2731. */
  2732. if (state->current != NULL)
  2733. return equal(expr, state->current);
  2734. /*
  2735. * Otherwise, ignore anything we've already processed.
  2736. */
  2737. if (list_member(state->already_used, expr))
  2738. return false;
  2739. /* This is the new target to process. */
  2740. state->current = expr;
  2741. return true;
  2742. }
  2743. /*
  2744. * Create cursor for node's query with current parameter values.
  2745. */
  2746. static void
  2747. create_cursor(ForeignScanState *node)
  2748. {
  2749. PgFdwScanState *fsstate = (PgFdwScanState *) node->fdw_state;
  2750. ExprContext *econtext = node->ss.ps.ps_ExprContext;
  2751. int numParams = fsstate->numParams;
  2752. const char **values = fsstate->param_values;
  2753. PGconn *conn = fsstate->conn;
  2754. StringInfoData buf;
  2755. PGresult *res;
  2756. /*
  2757. * Construct array of query parameter values in text format. We do the
  2758. * conversions in the short-lived per-tuple context, so as not to cause a
  2759. * memory leak over repeated scans.
  2760. */
  2761. if (numParams > 0)
  2762. {
  2763. MemoryContext oldcontext;
  2764. oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
  2765. process_query_params(econtext,
  2766. fsstate->param_flinfo,
  2767. fsstate->param_exprs,
  2768. values);
  2769. MemoryContextSwitchTo(oldcontext);
  2770. }
  2771. /* Construct the DECLARE CURSOR command */
  2772. initStringInfo(&buf);
  2773. appendStringInfo(&buf, "DECLARE c%u CURSOR FOR\n%s",
  2774. fsstate->cursor_number, fsstate->query);
  2775. /*
  2776. * Notice that we pass NULL for paramTypes, thus forcing the remote server
  2777. * to infer types for all parameters. Since we explicitly cast every
  2778. * parameter (see deparse.c), the "inference" is trivial and will produce
  2779. * the desired result. This allows us to avoid assuming that the remote
  2780. * server has the same OIDs we do for the parameters' types.
  2781. */
  2782. if (!PQsendQueryParams(conn, buf.data, numParams,
  2783. NULL, values, NULL, NULL, 0))
  2784. pgfdw_report_error(ERROR, NULL, conn, false, buf.data);
  2785. /*
  2786. * Get the result, and check for success.
  2787. *
  2788. * We don't use a PG_TRY block here, so be careful not to throw error
  2789. * without releasing the PGresult.
  2790. */
  2791. res = pgfdw_get_result(conn, buf.data);
  2792. if (PQresultStatus(res) != PGRES_COMMAND_OK)
  2793. pgfdw_report_error(ERROR, res, conn, true, fsstate->query);
  2794. PQclear(res);
  2795. /* Mark the cursor as created, and show no tuples have been retrieved */
  2796. fsstate->cursor_exists = true;
  2797. fsstate->tuples = NULL;
  2798. fsstate->num_tuples = 0;
  2799. fsstate->next_tuple = 0;
  2800. fsstate->fetch_ct_2 = 0;
  2801. fsstate->eof_reached = false;
  2802. /* Clean up */
  2803. pfree(buf.data);
  2804. }
  2805. /*
  2806. * Fetch some more rows from the node's cursor.
  2807. */
  2808. static void
  2809. fetch_more_data(ForeignScanState *node)
  2810. {
  2811. PgFdwScanState *fsstate = (PgFdwScanState *) node->fdw_state;
  2812. PGresult *volatile res = NULL;
  2813. MemoryContext oldcontext;
  2814. /*
  2815. * We'll store the tuples in the batch_cxt. First, flush the previous
  2816. * batch.
  2817. */
  2818. fsstate->tuples = NULL;
  2819. MemoryContextReset(fsstate->batch_cxt);
  2820. oldcontext = MemoryContextSwitchTo(fsstate->batch_cxt);
  2821. /* PGresult must be released before leaving this function. */
  2822. PG_TRY();
  2823. {
  2824. PGconn *conn = fsstate->conn;
  2825. char sql[64];
  2826. int numrows;
  2827. int i;
  2828. snprintf(sql, sizeof(sql), "FETCH %d FROM c%u",
  2829. fsstate->fetch_size, fsstate->cursor_number);
  2830. res = pgfdw_exec_query(conn, sql);
  2831. /* On error, report the original query, not the FETCH. */
  2832. if (PQresultStatus(res) != PGRES_TUPLES_OK)
  2833. pgfdw_report_error(ERROR, res, conn, false, fsstate->query);
  2834. /* Convert the data into HeapTuples */
  2835. numrows = PQntuples(res);
  2836. fsstate->tuples = (HeapTuple *) palloc0(numrows * sizeof(HeapTuple));
  2837. fsstate->num_tuples = numrows;
  2838. fsstate->next_tuple = 0;
  2839. for (i = 0; i < numrows; i++)
  2840. {
  2841. Assert(IsA(node->ss.ps.plan, ForeignScan));
  2842. fsstate->tuples[i] =
  2843. make_tuple_from_result_row(res, i,
  2844. fsstate->rel,
  2845. fsstate->attinmeta,
  2846. fsstate->retrieved_attrs,
  2847. node,
  2848. fsstate->temp_cxt);
  2849. }
  2850. /* Update fetch_ct_2 */
  2851. if (fsstate->fetch_ct_2 < 2)
  2852. fsstate->fetch_ct_2++;
  2853. /* Must be EOF if we didn't get as many tuples as we asked for. */
  2854. fsstate->eof_reached = (numrows < fsstate->fetch_size);
  2855. PQclear(res);
  2856. res = NULL;
  2857. }
  2858. PG_CATCH();
  2859. {
  2860. if (res)
  2861. PQclear(res);
  2862. PG_RE_THROW();
  2863. }
  2864. PG_END_TRY();
  2865. MemoryContextSwitchTo(oldcontext);
  2866. }
  2867. /*
  2868. * Force assorted GUC parameters to settings that ensure that we'll output
  2869. * data values in a form that is unambiguous to the remote server.
  2870. *
  2871. * This is rather expensive and annoying to do once per row, but there's
  2872. * little choice if we want to be sure values are transmitted accurately;
  2873. * we can't leave the settings in place between rows for fear of affecting
  2874. * user-visible computations.
  2875. *
  2876. * We use the equivalent of a function SET option to allow the settings to
  2877. * persist only until the caller calls reset_transmission_modes(). If an
  2878. * error is thrown in between, guc.c will take care of undoing the settings.
  2879. *
  2880. * The return value is the nestlevel that must be passed to
  2881. * reset_transmission_modes() to undo things.
  2882. */
  2883. int
  2884. set_transmission_modes(void)
  2885. {
  2886. int nestlevel = NewGUCNestLevel();
  2887. /*
  2888. * The values set here should match what pg_dump does. See also
  2889. * configure_remote_session in connection.c.
  2890. */
  2891. if (DateStyle != USE_ISO_DATES)
  2892. (void) set_config_option("datestyle", "ISO",
  2893. PGC_USERSET, PGC_S_SESSION,
  2894. GUC_ACTION_SAVE, true, 0, false);
  2895. if (IntervalStyle != INTSTYLE_POSTGRES)
  2896. (void) set_config_option("intervalstyle", "postgres",
  2897. PGC_USERSET, PGC_S_SESSION,
  2898. GUC_ACTION_SAVE, true, 0, false);
  2899. if (extra_float_digits < 3)
  2900. (void) set_config_option("extra_float_digits", "3",
  2901. PGC_USERSET, PGC_S_SESSION,
  2902. GUC_ACTION_SAVE, true, 0, false);
  2903. return nestlevel;
  2904. }
  2905. /*
  2906. * Undo the effects of set_transmission_modes().
  2907. */
  2908. void
  2909. reset_transmission_modes(int nestlevel)
  2910. {
  2911. AtEOXact_GUC(true, nestlevel);
  2912. }
  2913. /*
  2914. * Utility routine to close a cursor.
  2915. */
  2916. static void
  2917. close_cursor(PGconn *conn, unsigned int cursor_number)
  2918. {
  2919. char sql[64];
  2920. PGresult *res;
  2921. snprintf(sql, sizeof(sql), "CLOSE c%u", cursor_number);
  2922. /*
  2923. * We don't use a PG_TRY block here, so be careful not to throw error
  2924. * without releasing the PGresult.
  2925. */
  2926. res = pgfdw_exec_query(conn, sql);
  2927. if (PQresultStatus(res) != PGRES_COMMAND_OK)
  2928. pgfdw_report_error(ERROR, res, conn, true, sql);
  2929. PQclear(res);
  2930. }
  2931. /*
  2932. * create_foreign_modify
  2933. * Construct an execution state of a foreign insert/update/delete
  2934. * operation
  2935. */
  2936. static PgFdwModifyState *
  2937. create_foreign_modify(EState *estate,
  2938. RangeTblEntry *rte,
  2939. ResultRelInfo *resultRelInfo,
  2940. CmdType operation,
  2941. Plan *subplan,
  2942. char *query,
  2943. List *target_attrs,
  2944. bool has_returning,
  2945. List *retrieved_attrs)
  2946. {
  2947. PgFdwModifyState *fmstate;
  2948. Relation rel = resultRelInfo->ri_RelationDesc;
  2949. TupleDesc tupdesc = RelationGetDescr(rel);
  2950. Oid userid;
  2951. ForeignTable *table;
  2952. UserMapping *user;
  2953. AttrNumber n_params;
  2954. Oid typefnoid;
  2955. bool isvarlena;
  2956. ListCell *lc;
  2957. /* Begin constructing PgFdwModifyState. */
  2958. fmstate = (PgFdwModifyState *) palloc0(sizeof(PgFdwModifyState));
  2959. fmstate->rel = rel;
  2960. /*
  2961. * Identify which user to do the remote access as. This should match what
  2962. * ExecCheckRTEPerms() does.
  2963. */
  2964. userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
  2965. /* Get info about foreign table. */
  2966. table = GetForeignTable(RelationGetRelid(rel));
  2967. user = GetUserMapping(userid, table->serverid);
  2968. /* Open connection; report that we'll create a prepared statement. */
  2969. fmstate->conn = GetConnection(user, true);
  2970. fmstate->p_name = NULL; /* prepared statement not made yet */
  2971. /* Set up remote query information. */
  2972. fmstate->query = query;
  2973. fmstate->target_attrs = target_attrs;
  2974. fmstate->has_returning = has_returning;
  2975. fmstate->retrieved_attrs = retrieved_attrs;
  2976. /* Create context for per-tuple temp workspace. */
  2977. fmstate->temp_cxt = AllocSetContextCreate(estate->es_query_cxt,
  2978. "postgres_fdw temporary data",
  2979. ALLOCSET_SMALL_SIZES);
  2980. /* Prepare for input conversion of RETURNING results. */
  2981. if (fmstate->has_returning)
  2982. fmstate->attinmeta = TupleDescGetAttInMetadata(tupdesc);
  2983. /* Prepare for output conversion of parameters used in prepared stmt. */
  2984. n_params = list_length(fmstate->target_attrs) + 1;
  2985. fmstate->p_flinfo = (FmgrInfo *) palloc0(sizeof(FmgrInfo) * n_params);
  2986. fmstate->p_nums = 0;
  2987. if (operation == CMD_UPDATE || operation == CMD_DELETE)
  2988. {
  2989. Assert(subplan != NULL);
  2990. /* Find the ctid resjunk column in the subplan's result */
  2991. fmstate->ctidAttno = ExecFindJunkAttributeInTlist(subplan->targetlist,
  2992. "ctid");
  2993. if (!AttributeNumberIsValid(fmstate->ctidAttno))
  2994. elog(ERROR, "could not find junk ctid column");
  2995. /* First transmittable parameter will be ctid */
  2996. getTypeOutputInfo(TIDOID, &typefnoid, &isvarlena);
  2997. fmgr_info(typefnoid, &fmstate->p_flinfo[fmstate->p_nums]);
  2998. fmstate->p_nums++;
  2999. }
  3000. if (operation == CMD_INSERT || operation == CMD_UPDATE)
  3001. {
  3002. /* Set up for remaining transmittable parameters */
  3003. foreach(lc, fmstate->target_attrs)
  3004. {
  3005. int attnum = lfirst_int(lc);
  3006. Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1);
  3007. Assert(!attr->attisdropped);
  3008. getTypeOutputInfo(attr->atttypid, &typefnoid, &isvarlena);
  3009. fmgr_info(typefnoid, &fmstate->p_flinfo[fmstate->p_nums]);
  3010. fmstate->p_nums++;
  3011. }
  3012. }
  3013. Assert(fmstate->p_nums <= n_params);
  3014. return fmstate;
  3015. }
  3016. /*
  3017. * prepare_foreign_modify
  3018. * Establish a prepared statement for execution of INSERT/UPDATE/DELETE
  3019. */
  3020. static void
  3021. prepare_foreign_modify(PgFdwModifyState *fmstate)
  3022. {
  3023. char prep_name[NAMEDATALEN];
  3024. char *p_name;
  3025. PGresult *res;
  3026. /* Construct name we'll use for the prepared statement. */
  3027. snprintf(prep_name, sizeof(prep_name), "pgsql_fdw_prep_%u",
  3028. GetPrepStmtNumber(fmstate->conn));
  3029. p_name = pstrdup(prep_name);
  3030. /*
  3031. * We intentionally do not specify parameter types here, but leave the
  3032. * remote server to derive them by default. This avoids possible problems
  3033. * with the remote server using different type OIDs than we do. All of
  3034. * the prepared statements we use in this module are simple enough that
  3035. * the remote server will make the right choices.
  3036. */
  3037. if (!PQsendPrepare(fmstate->conn,
  3038. p_name,
  3039. fmstate->query,
  3040. 0,
  3041. NULL))
  3042. pgfdw_report_error(ERROR, NULL, fmstate->conn, false, fmstate->query);
  3043. /*
  3044. * Get the result, and check for success.
  3045. *
  3046. * We don't use a PG_TRY block here, so be careful not to throw error
  3047. * without releasing the PGresult.
  3048. */
  3049. res = pgfdw_get_result(fmstate->conn, fmstate->query);
  3050. if (PQresultStatus(res) != PGRES_COMMAND_OK)
  3051. pgfdw_report_error(ERROR, res, fmstate->conn, true, fmstate->query);
  3052. PQclear(res);
  3053. /* This action shows that the prepare has been done. */
  3054. fmstate->p_name = p_name;
  3055. }
  3056. /*
  3057. * convert_prep_stmt_params
  3058. * Create array of text strings representing parameter values
  3059. *
  3060. * tupleid is ctid to send, or NULL if none
  3061. * slot is slot to get remaining parameters from, or NULL if none
  3062. *
  3063. * Data is constructed in temp_cxt; caller should reset that after use.
  3064. */
  3065. static const char **
  3066. convert_prep_stmt_params(PgFdwModifyState *fmstate,
  3067. ItemPointer tupleid,
  3068. TupleTableSlot *slot)
  3069. {
  3070. const char **p_values;
  3071. int pindex = 0;
  3072. MemoryContext oldcontext;
  3073. oldcontext = MemoryContextSwitchTo(fmstate->temp_cxt);
  3074. p_values = (const char **) palloc(sizeof(char *) * fmstate->p_nums);
  3075. /* 1st parameter should be ctid, if it's in use */
  3076. if (tupleid != NULL)
  3077. {
  3078. /* don't need set_transmission_modes for TID output */
  3079. p_values[pindex] = OutputFunctionCall(&fmstate->p_flinfo[pindex],
  3080. PointerGetDatum(tupleid));
  3081. pindex++;
  3082. }
  3083. /* get following parameters from slot */
  3084. if (slot != NULL && fmstate->target_attrs != NIL)
  3085. {
  3086. int nestlevel;
  3087. ListCell *lc;
  3088. nestlevel = set_transmission_modes();
  3089. foreach(lc, fmstate->target_attrs)
  3090. {
  3091. int attnum = lfirst_int(lc);
  3092. Datum value;
  3093. bool isnull;
  3094. value = slot_getattr(slot, attnum, &isnull);
  3095. if (isnull)
  3096. p_values[pindex] = NULL;
  3097. else
  3098. p_values[pindex] = OutputFunctionCall(&fmstate->p_flinfo[pindex],
  3099. value);
  3100. pindex++;
  3101. }
  3102. reset_transmission_modes(nestlevel);
  3103. }
  3104. Assert(pindex == fmstate->p_nums);
  3105. MemoryContextSwitchTo(oldcontext);
  3106. return p_values;
  3107. }
  3108. /*
  3109. * store_returning_result
  3110. * Store the result of a RETURNING clause
  3111. *
  3112. * On error, be sure to release the PGresult on the way out. Callers do not
  3113. * have PG_TRY blocks to ensure this happens.
  3114. */
  3115. static void
  3116. store_returning_result(PgFdwModifyState *fmstate,
  3117. TupleTableSlot *slot, PGresult *res)
  3118. {
  3119. PG_TRY();
  3120. {
  3121. HeapTuple newtup;
  3122. newtup = make_tuple_from_result_row(res, 0,
  3123. fmstate->rel,
  3124. fmstate->attinmeta,
  3125. fmstate->retrieved_attrs,
  3126. NULL,
  3127. fmstate->temp_cxt);
  3128. /* tuple will be deleted when it is cleared from the slot */
  3129. ExecStoreHeapTuple(newtup, slot, true);
  3130. }
  3131. PG_CATCH();
  3132. {
  3133. if (res)
  3134. PQclear(res);
  3135. PG_RE_THROW();
  3136. }
  3137. PG_END_TRY();
  3138. }
  3139. /*
  3140. * finish_foreign_modify
  3141. * Release resources for a foreign insert/update/delete operation
  3142. */
  3143. static void
  3144. finish_foreign_modify(PgFdwModifyState *fmstate)
  3145. {
  3146. Assert(fmstate != NULL);
  3147. /* If we created a prepared statement, destroy it */
  3148. if (fmstate->p_name)
  3149. {
  3150. char sql[64];
  3151. PGresult *res;
  3152. snprintf(sql, sizeof(sql), "DEALLOCATE %s", fmstate->p_name);
  3153. /*
  3154. * We don't use a PG_TRY block here, so be careful not to throw error
  3155. * without releasing the PGresult.
  3156. */
  3157. res = pgfdw_exec_query(fmstate->conn, sql);
  3158. if (PQresultStatus(res) != PGRES_COMMAND_OK)
  3159. pgfdw_report_error(ERROR, res, fmstate->conn, true, sql);
  3160. PQclear(res);
  3161. fmstate->p_name = NULL;
  3162. }
  3163. /* Release remote connection */
  3164. ReleaseConnection(fmstate->conn);
  3165. fmstate->conn = NULL;
  3166. }
  3167. /*
  3168. * build_remote_returning
  3169. * Build a RETURNING targetlist of a remote query for performing an
  3170. * UPDATE/DELETE .. RETURNING on a join directly
  3171. */
  3172. static List *
  3173. build_remote_returning(Index rtindex, Relation rel, List *returningList)
  3174. {
  3175. bool have_wholerow = false;
  3176. List *tlist = NIL;
  3177. List *vars;
  3178. ListCell *lc;
  3179. Assert(returningList);
  3180. vars = pull_var_clause((Node *) returningList, PVC_INCLUDE_PLACEHOLDERS);
  3181. /*
  3182. * If there's a whole-row reference to the target relation, then we'll
  3183. * need all the columns of the relation.
  3184. */
  3185. foreach(lc, vars)
  3186. {
  3187. Var *var = (Var *) lfirst(lc);
  3188. if (IsA(var, Var) &&
  3189. var->varno == rtindex &&
  3190. var->varattno == InvalidAttrNumber)
  3191. {
  3192. have_wholerow = true;
  3193. break;
  3194. }
  3195. }
  3196. if (have_wholerow)
  3197. {
  3198. TupleDesc tupdesc = RelationGetDescr(rel);
  3199. int i;
  3200. for (i = 1; i <= tupdesc->natts; i++)
  3201. {
  3202. Form_pg_attribute attr = TupleDescAttr(tupdesc, i - 1);
  3203. Var *var;
  3204. /* Ignore dropped attributes. */
  3205. if (attr->attisdropped)
  3206. continue;
  3207. var = makeVar(rtindex,
  3208. i,
  3209. attr->atttypid,
  3210. attr->atttypmod,
  3211. attr->attcollation,
  3212. 0);
  3213. tlist = lappend(tlist,
  3214. makeTargetEntry((Expr *) var,
  3215. list_length(tlist) + 1,
  3216. NULL,
  3217. false));
  3218. }
  3219. }
  3220. /* Now add any remaining columns to tlist. */
  3221. foreach(lc, vars)
  3222. {
  3223. Var *var = (Var *) lfirst(lc);
  3224. /*
  3225. * No need for whole-row references to the target relation. We don't
  3226. * need system columns other than ctid and oid either, since those are
  3227. * set locally.
  3228. */
  3229. if (IsA(var, Var) &&
  3230. var->varno == rtindex &&
  3231. var->varattno <= InvalidAttrNumber &&
  3232. var->varattno != SelfItemPointerAttributeNumber)
  3233. continue; /* don't need it */
  3234. if (tlist_member((Expr *) var, tlist))
  3235. continue; /* already got it */
  3236. tlist = lappend(tlist,
  3237. makeTargetEntry((Expr *) var,
  3238. list_length(tlist) + 1,
  3239. NULL,
  3240. false));
  3241. }
  3242. list_free(vars);
  3243. return tlist;
  3244. }
  3245. /*
  3246. * rebuild_fdw_scan_tlist
  3247. * Build new fdw_scan_tlist of given foreign-scan plan node from given
  3248. * tlist
  3249. *
  3250. * There might be columns that the fdw_scan_tlist of the given foreign-scan
  3251. * plan node contains that the given tlist doesn't. The fdw_scan_tlist would
  3252. * have contained resjunk columns such as 'ctid' of the target relation and
  3253. * 'wholerow' of non-target relations, but the tlist might not contain them,
  3254. * for example. So, adjust the tlist so it contains all the columns specified
  3255. * in the fdw_scan_tlist; else setrefs.c will get confused.
  3256. */
  3257. static void
  3258. rebuild_fdw_scan_tlist(ForeignScan *fscan, List *tlist)
  3259. {
  3260. List *new_tlist = tlist;
  3261. List *old_tlist = fscan->fdw_scan_tlist;
  3262. ListCell *lc;
  3263. foreach(lc, old_tlist)
  3264. {
  3265. TargetEntry *tle = (TargetEntry *) lfirst(lc);
  3266. if (tlist_member(tle->expr, new_tlist))
  3267. continue; /* already got it */
  3268. new_tlist = lappend(new_tlist,
  3269. makeTargetEntry(tle->expr,
  3270. list_length(new_tlist) + 1,
  3271. NULL,
  3272. false));
  3273. }
  3274. fscan->fdw_scan_tlist = new_tlist;
  3275. }
  3276. /*
  3277. * Execute a direct UPDATE/DELETE statement.
  3278. */
  3279. static void
  3280. execute_dml_stmt(ForeignScanState *node)
  3281. {
  3282. PgFdwDirectModifyState *dmstate = (PgFdwDirectModifyState *) node->fdw_state;
  3283. ExprContext *econtext = node->ss.ps.ps_ExprContext;
  3284. int numParams = dmstate->numParams;
  3285. const char **values = dmstate->param_values;
  3286. /*
  3287. * Construct array of query parameter values in text format.
  3288. */
  3289. if (numParams > 0)
  3290. process_query_params(econtext,
  3291. dmstate->param_flinfo,
  3292. dmstate->param_exprs,
  3293. values);
  3294. /*
  3295. * Notice that we pass NULL for paramTypes, thus forcing the remote server
  3296. * to infer types for all parameters. Since we explicitly cast every
  3297. * parameter (see deparse.c), the "inference" is trivial and will produce
  3298. * the desired result. This allows us to avoid assuming that the remote
  3299. * server has the same OIDs we do for the parameters' types.
  3300. */
  3301. if (!PQsendQueryParams(dmstate->conn, dmstate->query, numParams,
  3302. NULL, values, NULL, NULL, 0))
  3303. pgfdw_report_error(ERROR, NULL, dmstate->conn, false, dmstate->query);
  3304. /*
  3305. * Get the result, and check for success.
  3306. *
  3307. * We don't use a PG_TRY block here, so be careful not to throw error
  3308. * without releasing the PGresult.
  3309. */
  3310. dmstate->result = pgfdw_get_result(dmstate->conn, dmstate->query);
  3311. if (PQresultStatus(dmstate->result) !=
  3312. (dmstate->has_returning ? PGRES_TUPLES_OK : PGRES_COMMAND_OK))
  3313. pgfdw_report_error(ERROR, dmstate->result, dmstate->conn, true,
  3314. dmstate->query);
  3315. /* Get the number of rows affected. */
  3316. if (dmstate->has_returning)
  3317. dmstate->num_tuples = PQntuples(dmstate->result);
  3318. else
  3319. dmstate->num_tuples = atoi(PQcmdTuples(dmstate->result));
  3320. }
  3321. /*
  3322. * Get the result of a RETURNING clause.
  3323. */
  3324. static TupleTableSlot *
  3325. get_returning_data(ForeignScanState *node)
  3326. {
  3327. PgFdwDirectModifyState *dmstate = (PgFdwDirectModifyState *) node->fdw_state;
  3328. EState *estate = node->ss.ps.state;
  3329. ResultRelInfo *resultRelInfo = estate->es_result_relation_info;
  3330. TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
  3331. TupleTableSlot *resultSlot;
  3332. Assert(resultRelInfo->ri_projectReturning);
  3333. /* If we didn't get any tuples, must be end of data. */
  3334. if (dmstate->next_tuple >= dmstate->num_tuples)
  3335. return ExecClearTuple(slot);
  3336. /* Increment the command es_processed count if necessary. */
  3337. if (dmstate->set_processed)
  3338. estate->es_processed += 1;
  3339. /*
  3340. * Store a RETURNING tuple. If has_returning is false, just emit a dummy
  3341. * tuple. (has_returning is false when the local query is of the form
  3342. * "UPDATE/DELETE .. RETURNING 1" for example.)
  3343. */
  3344. if (!dmstate->has_returning)
  3345. {
  3346. ExecStoreAllNullTuple(slot);
  3347. resultSlot = slot;
  3348. }
  3349. else
  3350. {
  3351. /*
  3352. * On error, be sure to release the PGresult on the way out. Callers
  3353. * do not have PG_TRY blocks to ensure this happens.
  3354. */
  3355. PG_TRY();
  3356. {
  3357. HeapTuple newtup;
  3358. newtup = make_tuple_from_result_row(dmstate->result,
  3359. dmstate->next_tuple,
  3360. dmstate->rel,
  3361. dmstate->attinmeta,
  3362. dmstate->retrieved_attrs,
  3363. node,
  3364. dmstate->temp_cxt);
  3365. ExecStoreHeapTuple(newtup, slot, false);
  3366. }
  3367. PG_CATCH();
  3368. {
  3369. if (dmstate->result)
  3370. PQclear(dmstate->result);
  3371. PG_RE_THROW();
  3372. }
  3373. PG_END_TRY();
  3374. /* Get the updated/deleted tuple. */
  3375. if (dmstate->rel)
  3376. resultSlot = slot;
  3377. else
  3378. resultSlot = apply_returning_filter(dmstate, slot, estate);
  3379. }
  3380. dmstate->next_tuple++;
  3381. /* Make slot available for evaluation of the local query RETURNING list. */
  3382. resultRelInfo->ri_projectReturning->pi_exprContext->ecxt_scantuple =
  3383. resultSlot;
  3384. return slot;
  3385. }
  3386. /*
  3387. * Initialize a filter to extract an updated/deleted tuple from a scan tuple.
  3388. */
  3389. static void
  3390. init_returning_filter(PgFdwDirectModifyState *dmstate,
  3391. List *fdw_scan_tlist,
  3392. Index rtindex)
  3393. {
  3394. TupleDesc resultTupType = RelationGetDescr(dmstate->resultRel);
  3395. ListCell *lc;
  3396. int i;
  3397. /*
  3398. * Calculate the mapping between the fdw_scan_tlist's entries and the
  3399. * result tuple's attributes.
  3400. *
  3401. * The "map" is an array of indexes of the result tuple's attributes in
  3402. * fdw_scan_tlist, i.e., one entry for every attribute of the result
  3403. * tuple. We store zero for any attributes that don't have the
  3404. * corresponding entries in that list, marking that a NULL is needed in
  3405. * the result tuple.
  3406. *
  3407. * Also get the indexes of the entries for ctid and oid if any.
  3408. */
  3409. dmstate->attnoMap = (AttrNumber *)
  3410. palloc0(resultTupType->natts * sizeof(AttrNumber));
  3411. dmstate->ctidAttno = dmstate->oidAttno = 0;
  3412. i = 1;
  3413. dmstate->hasSystemCols = false;
  3414. foreach(lc, fdw_scan_tlist)
  3415. {
  3416. TargetEntry *tle = (TargetEntry *) lfirst(lc);
  3417. Var *var = (Var *) tle->expr;
  3418. Assert(IsA(var, Var));
  3419. /*
  3420. * If the Var is a column of the target relation to be retrieved from
  3421. * the foreign server, get the index of the entry.
  3422. */
  3423. if (var->varno == rtindex &&
  3424. list_member_int(dmstate->retrieved_attrs, i))
  3425. {
  3426. int attrno = var->varattno;
  3427. if (attrno < 0)
  3428. {
  3429. /*
  3430. * We don't retrieve system columns other than ctid and oid.
  3431. */
  3432. if (attrno == SelfItemPointerAttributeNumber)
  3433. dmstate->ctidAttno = i;
  3434. else
  3435. Assert(false);
  3436. dmstate->hasSystemCols = true;
  3437. }
  3438. else
  3439. {
  3440. /*
  3441. * We don't retrieve whole-row references to the target
  3442. * relation either.
  3443. */
  3444. Assert(attrno > 0);
  3445. dmstate->attnoMap[attrno - 1] = i;
  3446. }
  3447. }
  3448. i++;
  3449. }
  3450. }
  3451. /*
  3452. * Extract and return an updated/deleted tuple from a scan tuple.
  3453. */
  3454. static TupleTableSlot *
  3455. apply_returning_filter(PgFdwDirectModifyState *dmstate,
  3456. TupleTableSlot *slot,
  3457. EState *estate)
  3458. {
  3459. TupleDesc resultTupType = RelationGetDescr(dmstate->resultRel);
  3460. TupleTableSlot *resultSlot;
  3461. Datum *values;
  3462. bool *isnull;
  3463. Datum *old_values;
  3464. bool *old_isnull;
  3465. int i;
  3466. /*
  3467. * Use the trigger tuple slot as a place to store the result tuple.
  3468. */
  3469. resultSlot = estate->es_trig_tuple_slot;
  3470. if (resultSlot->tts_tupleDescriptor != resultTupType)
  3471. ExecSetSlotDescriptor(resultSlot, resultTupType);
  3472. /*
  3473. * Extract all the values of the scan tuple.
  3474. */
  3475. slot_getallattrs(slot);
  3476. old_values = slot->tts_values;
  3477. old_isnull = slot->tts_isnull;
  3478. /*
  3479. * Prepare to build the result tuple.
  3480. */
  3481. ExecClearTuple(resultSlot);
  3482. values = resultSlot->tts_values;
  3483. isnull = resultSlot->tts_isnull;
  3484. /*
  3485. * Transpose data into proper fields of the result tuple.
  3486. */
  3487. for (i = 0; i < resultTupType->natts; i++)
  3488. {
  3489. int j = dmstate->attnoMap[i];
  3490. if (j == 0)
  3491. {
  3492. values[i] = (Datum) 0;
  3493. isnull[i] = true;
  3494. }
  3495. else
  3496. {
  3497. values[i] = old_values[j - 1];
  3498. isnull[i] = old_isnull[j - 1];
  3499. }
  3500. }
  3501. /*
  3502. * Build the virtual tuple.
  3503. */
  3504. ExecStoreVirtualTuple(resultSlot);
  3505. /*
  3506. * If we have any system columns to return, materialize a heap tuple in the
  3507. * slot from column values set above and install system columns in that tuple.
  3508. */
  3509. if (dmstate->hasSystemCols)
  3510. {
  3511. HeapTuple resultTup = ExecFetchSlotHeapTuple(resultSlot, true, NULL);
  3512. /* ctid */
  3513. if (dmstate->ctidAttno)
  3514. {
  3515. ItemPointer ctid = NULL;
  3516. ctid = (ItemPointer) DatumGetPointer(old_values[dmstate->ctidAttno - 1]);
  3517. resultTup->t_self = *ctid;
  3518. }
  3519. /*
  3520. * And remaining columns
  3521. *
  3522. * Note: since we currently don't allow the target relation to appear
  3523. * on the nullable side of an outer join, any system columns wouldn't
  3524. * go to NULL.
  3525. *
  3526. * Note: no need to care about tableoid here because it will be
  3527. * initialized in ExecProcessReturning().
  3528. */
  3529. HeapTupleHeaderSetXmin(resultTup->t_data, InvalidTransactionId);
  3530. HeapTupleHeaderSetXmax(resultTup->t_data, InvalidTransactionId);
  3531. HeapTupleHeaderSetCmin(resultTup->t_data, InvalidTransactionId);
  3532. }
  3533. /*
  3534. * And return the result tuple.
  3535. */
  3536. return resultSlot;
  3537. }
  3538. /*
  3539. * Prepare for processing of parameters used in remote query.
  3540. */
  3541. static void
  3542. prepare_query_params(PlanState *node,
  3543. List *fdw_exprs,
  3544. int numParams,
  3545. FmgrInfo **param_flinfo,
  3546. List **param_exprs,
  3547. const char ***param_values)
  3548. {
  3549. int i;
  3550. ListCell *lc;
  3551. Assert(numParams > 0);
  3552. /* Prepare for output conversion of parameters used in remote query. */
  3553. *param_flinfo = (FmgrInfo *) palloc0(sizeof(FmgrInfo) * numParams);
  3554. i = 0;
  3555. foreach(lc, fdw_exprs)
  3556. {
  3557. Node *param_expr = (Node *) lfirst(lc);
  3558. Oid typefnoid;
  3559. bool isvarlena;
  3560. getTypeOutputInfo(exprType(param_expr), &typefnoid, &isvarlena);
  3561. fmgr_info(typefnoid, &(*param_flinfo)[i]);
  3562. i++;
  3563. }
  3564. /*
  3565. * Prepare remote-parameter expressions for evaluation. (Note: in
  3566. * practice, we expect that all these expressions will be just Params, so
  3567. * we could possibly do something more efficient than using the full
  3568. * expression-eval machinery for this. But probably there would be little
  3569. * benefit, and it'd require postgres_fdw to know more than is desirable
  3570. * about Param evaluation.)
  3571. */
  3572. *param_exprs = ExecInitExprList(fdw_exprs, node);
  3573. /* Allocate buffer for text form of query parameters. */
  3574. *param_values = (const char **) palloc0(numParams * sizeof(char *));
  3575. }
  3576. /*
  3577. * Construct array of query parameter values in text format.
  3578. */
  3579. static void
  3580. process_query_params(ExprContext *econtext,
  3581. FmgrInfo *param_flinfo,
  3582. List *param_exprs,
  3583. const char **param_values)
  3584. {
  3585. int nestlevel;
  3586. int i;
  3587. ListCell *lc;
  3588. nestlevel = set_transmission_modes();
  3589. i = 0;
  3590. foreach(lc, param_exprs)
  3591. {
  3592. ExprState *expr_state = (ExprState *) lfirst(lc);
  3593. Datum expr_value;
  3594. bool isNull;
  3595. /* Evaluate the parameter expression */
  3596. expr_value = ExecEvalExpr(expr_state, econtext, &isNull);
  3597. /*
  3598. * Get string representation of each parameter value by invoking
  3599. * type-specific output function, unless the value is null.
  3600. */
  3601. if (isNull)
  3602. param_values[i] = NULL;
  3603. else
  3604. param_values[i] = OutputFunctionCall(&param_flinfo[i], expr_value);
  3605. i++;
  3606. }
  3607. reset_transmission_modes(nestlevel);
  3608. }
  3609. /*
  3610. * postgresAnalyzeForeignTable
  3611. * Test whether analyzing this foreign table is supported
  3612. */
  3613. static bool
  3614. postgresAnalyzeForeignTable(Relation relation,
  3615. AcquireSampleRowsFunc *func,
  3616. BlockNumber *totalpages)
  3617. {
  3618. ForeignTable *table;
  3619. UserMapping *user;
  3620. PGconn *conn;
  3621. StringInfoData sql;
  3622. PGresult *volatile res = NULL;
  3623. /* Return the row-analysis function pointer */
  3624. *func = postgresAcquireSampleRowsFunc;
  3625. /*
  3626. * Now we have to get the number of pages. It's annoying that the ANALYZE
  3627. * API requires us to return that now, because it forces some duplication
  3628. * of effort between this routine and postgresAcquireSampleRowsFunc. But
  3629. * it's probably not worth redefining that API at this point.
  3630. */
  3631. /*
  3632. * Get the connection to use. We do the remote access as the table's
  3633. * owner, even if the ANALYZE was started by some other user.
  3634. */
  3635. table = GetForeignTable(RelationGetRelid(relation));
  3636. user = GetUserMapping(relation->rd_rel->relowner, table->serverid);
  3637. conn = GetConnection(user, false);
  3638. /*
  3639. * Construct command to get page count for relation.
  3640. */
  3641. initStringInfo(&sql);
  3642. deparseAnalyzeSizeSql(&sql, relation);
  3643. /* In what follows, do not risk leaking any PGresults. */
  3644. PG_TRY();
  3645. {
  3646. res = pgfdw_exec_query(conn, sql.data);
  3647. if (PQresultStatus(res) != PGRES_TUPLES_OK)
  3648. pgfdw_report_error(ERROR, res, conn, false, sql.data);
  3649. if (PQntuples(res) != 1 || PQnfields(res) != 1)
  3650. elog(ERROR, "unexpected result from deparseAnalyzeSizeSql query");
  3651. *totalpages = strtoul(PQgetvalue(res, 0, 0), NULL, 10);
  3652. PQclear(res);
  3653. res = NULL;
  3654. }
  3655. PG_CATCH();
  3656. {
  3657. if (res)
  3658. PQclear(res);
  3659. PG_RE_THROW();
  3660. }
  3661. PG_END_TRY();
  3662. ReleaseConnection(conn);
  3663. return true;
  3664. }
  3665. /*
  3666. * Acquire a random sample of rows from foreign table managed by postgres_fdw.
  3667. *
  3668. * We fetch the whole table from the remote side and pick out some sample rows.
  3669. *
  3670. * Selected rows are returned in the caller-allocated array rows[],
  3671. * which must have at least targrows entries.
  3672. * The actual number of rows selected is returned as the function result.
  3673. * We also count the total number of rows in the table and return it into
  3674. * *totalrows. Note that *totaldeadrows is always set to 0.
  3675. *
  3676. * Note that the returned list of rows is not always in order by physical
  3677. * position in the table. Therefore, correlation estimates derived later
  3678. * may be meaningless, but it's OK because we don't use the estimates
  3679. * currently (the planner only pays attention to correlation for indexscans).
  3680. */
  3681. static int
  3682. postgresAcquireSampleRowsFunc(Relation relation, int elevel,
  3683. HeapTuple *rows, int targrows,
  3684. double *totalrows,
  3685. double *totaldeadrows)
  3686. {
  3687. PgFdwAnalyzeState astate;
  3688. ForeignTable *table;
  3689. ForeignServer *server;
  3690. UserMapping *user;
  3691. PGconn *conn;
  3692. unsigned int cursor_number;
  3693. StringInfoData sql;
  3694. PGresult *volatile res = NULL;
  3695. /* Initialize workspace state */
  3696. astate.rel = relation;
  3697. astate.attinmeta = TupleDescGetAttInMetadata(RelationGetDescr(relation));
  3698. astate.rows = rows;
  3699. astate.targrows = targrows;
  3700. astate.numrows = 0;
  3701. astate.samplerows = 0;
  3702. astate.rowstoskip = -1; /* -1 means not set yet */
  3703. reservoir_init_selection_state(&astate.rstate, targrows);
  3704. /* Remember ANALYZE context, and create a per-tuple temp context */
  3705. astate.anl_cxt = CurrentMemoryContext;
  3706. astate.temp_cxt = AllocSetContextCreate(CurrentMemoryContext,
  3707. "postgres_fdw temporary data",
  3708. ALLOCSET_SMALL_SIZES);
  3709. /*
  3710. * Get the connection to use. We do the remote access as the table's
  3711. * owner, even if the ANALYZE was started by some other user.
  3712. */
  3713. table = GetForeignTable(RelationGetRelid(relation));
  3714. server = GetForeignServer(table->serverid);
  3715. user = GetUserMapping(relation->rd_rel->relowner, table->serverid);
  3716. conn = GetConnection(user, false);
  3717. /*
  3718. * Construct cursor that retrieves whole rows from remote.
  3719. */
  3720. cursor_number = GetCursorNumber(conn);
  3721. initStringInfo(&sql);
  3722. appendStringInfo(&sql, "DECLARE c%u CURSOR FOR ", cursor_number);
  3723. deparseAnalyzeSql(&sql, relation, &astate.retrieved_attrs);
  3724. /* In what follows, do not risk leaking any PGresults. */
  3725. PG_TRY();
  3726. {
  3727. res = pgfdw_exec_query(conn, sql.data);
  3728. if (PQresultStatus(res) != PGRES_COMMAND_OK)
  3729. pgfdw_report_error(ERROR, res, conn, false, sql.data);
  3730. PQclear(res);
  3731. res = NULL;
  3732. /* Retrieve and process rows a batch at a time. */
  3733. for (;;)
  3734. {
  3735. char fetch_sql[64];
  3736. int fetch_size;
  3737. int numrows;
  3738. int i;
  3739. ListCell *lc;
  3740. /* Allow users to cancel long query */
  3741. CHECK_FOR_INTERRUPTS();
  3742. /*
  3743. * XXX possible future improvement: if rowstoskip is large, we
  3744. * could issue a MOVE rather than physically fetching the rows,
  3745. * then just adjust rowstoskip and samplerows appropriately.
  3746. */
  3747. /* The fetch size is arbitrary, but shouldn't be enormous. */
  3748. fetch_size = 100;
  3749. foreach(lc, server->options)
  3750. {
  3751. DefElem *def = (DefElem *) lfirst(lc);
  3752. if (strcmp(def->defname, "fetch_size") == 0)
  3753. {
  3754. fetch_size = strtol(defGetString(def), NULL, 10);
  3755. break;
  3756. }
  3757. }
  3758. foreach(lc, table->options)
  3759. {
  3760. DefElem *def = (DefElem *) lfirst(lc);
  3761. if (strcmp(def->defname, "fetch_size") == 0)
  3762. {
  3763. fetch_size = strtol(defGetString(def), NULL, 10);
  3764. break;
  3765. }
  3766. }
  3767. /* Fetch some rows */
  3768. snprintf(fetch_sql, sizeof(fetch_sql), "FETCH %d FROM c%u",
  3769. fetch_size, cursor_number);
  3770. res = pgfdw_exec_query(conn, fetch_sql);
  3771. /* On error, report the original query, not the FETCH. */
  3772. if (PQresultStatus(res) != PGRES_TUPLES_OK)
  3773. pgfdw_report_error(ERROR, res, conn, false, sql.data);
  3774. /* Process whatever we got. */
  3775. numrows = PQntuples(res);
  3776. for (i = 0; i < numrows; i++)
  3777. analyze_row_processor(res, i, &astate);
  3778. PQclear(res);
  3779. res = NULL;
  3780. /* Must be EOF if we didn't get all the rows requested. */
  3781. if (numrows < fetch_size)
  3782. break;
  3783. }
  3784. /* Close the cursor, just to be tidy. */
  3785. close_cursor(conn, cursor_number);
  3786. }
  3787. PG_CATCH();
  3788. {
  3789. if (res)
  3790. PQclear(res);
  3791. PG_RE_THROW();
  3792. }
  3793. PG_END_TRY();
  3794. ReleaseConnection(conn);
  3795. /* We assume that we have no dead tuple. */
  3796. *totaldeadrows = 0.0;
  3797. /* We've retrieved all living tuples from foreign server. */
  3798. *totalrows = astate.samplerows;
  3799. /*
  3800. * Emit some interesting relation info
  3801. */
  3802. ereport(elevel,
  3803. (errmsg("\"%s\": table contains %.0f rows, %d rows in sample",
  3804. RelationGetRelationName(relation),
  3805. astate.samplerows, astate.numrows)));
  3806. return astate.numrows;
  3807. }
  3808. /*
  3809. * Collect sample rows from the result of query.
  3810. * - Use all tuples in sample until target # of samples are collected.
  3811. * - Subsequently, replace already-sampled tuples randomly.
  3812. */
  3813. static void
  3814. analyze_row_processor(PGresult *res, int row, PgFdwAnalyzeState *astate)
  3815. {
  3816. int targrows = astate->targrows;
  3817. int pos; /* array index to store tuple in */
  3818. MemoryContext oldcontext;
  3819. /* Always increment sample row counter. */
  3820. astate->samplerows += 1;
  3821. /*
  3822. * Determine the slot where this sample row should be stored. Set pos to
  3823. * negative value to indicate the row should be skipped.
  3824. */
  3825. if (astate->numrows < targrows)
  3826. {
  3827. /* First targrows rows are always included into the sample */
  3828. pos = astate->numrows++;
  3829. }
  3830. else
  3831. {
  3832. /*
  3833. * Now we start replacing tuples in the sample until we reach the end
  3834. * of the relation. Same algorithm as in acquire_sample_rows in
  3835. * analyze.c; see Jeff Vitter's paper.
  3836. */
  3837. if (astate->rowstoskip < 0)
  3838. astate->rowstoskip = reservoir_get_next_S(&astate->rstate, astate->samplerows, targrows);
  3839. if (astate->rowstoskip <= 0)
  3840. {
  3841. /* Choose a random reservoir element to replace. */
  3842. pos = (int) (targrows * sampler_random_fract(astate->rstate.randstate));
  3843. Assert(pos >= 0 && pos < targrows);
  3844. heap_freetuple(astate->rows[pos]);
  3845. }
  3846. else
  3847. {
  3848. /* Skip this tuple. */
  3849. pos = -1;
  3850. }
  3851. astate->rowstoskip -= 1;
  3852. }
  3853. if (pos >= 0)
  3854. {
  3855. /*
  3856. * Create sample tuple from current result row, and store it in the
  3857. * position determined above. The tuple has to be created in anl_cxt.
  3858. */
  3859. oldcontext = MemoryContextSwitchTo(astate->anl_cxt);
  3860. astate->rows[pos] = make_tuple_from_result_row(res, row,
  3861. astate->rel,
  3862. astate->attinmeta,
  3863. astate->retrieved_attrs,
  3864. NULL,
  3865. astate->temp_cxt);
  3866. MemoryContextSwitchTo(oldcontext);
  3867. }
  3868. }
  3869. /*
  3870. * Import a foreign schema
  3871. */
  3872. static List *
  3873. postgresImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid)
  3874. {
  3875. List *commands = NIL;
  3876. bool import_collate = true;
  3877. bool import_default = false;
  3878. bool import_not_null = true;
  3879. ForeignServer *server;
  3880. UserMapping *mapping;
  3881. PGconn *conn;
  3882. StringInfoData buf;
  3883. PGresult *volatile res = NULL;
  3884. int numrows,
  3885. i;
  3886. ListCell *lc;
  3887. /* Parse statement options */
  3888. foreach(lc, stmt->options)
  3889. {
  3890. DefElem *def = (DefElem *) lfirst(lc);
  3891. if (strcmp(def->defname, "import_collate") == 0)
  3892. import_collate = defGetBoolean(def);
  3893. else if (strcmp(def->defname, "import_default") == 0)
  3894. import_default = defGetBoolean(def);
  3895. else if (strcmp(def->defname, "import_not_null") == 0)
  3896. import_not_null = defGetBoolean(def);
  3897. else
  3898. ereport(ERROR,
  3899. (errcode(ERRCODE_FDW_INVALID_OPTION_NAME),
  3900. errmsg("invalid option \"%s\"", def->defname)));
  3901. }
  3902. /*
  3903. * Get connection to the foreign server. Connection manager will
  3904. * establish new connection if necessary.
  3905. */
  3906. server = GetForeignServer(serverOid);
  3907. mapping = GetUserMapping(GetUserId(), server->serverid);
  3908. conn = GetConnection(mapping, false);
  3909. /* Don't attempt to import collation if remote server hasn't got it */
  3910. if (PQserverVersion(conn) < 90100)
  3911. import_collate = false;
  3912. /* Create workspace for strings */
  3913. initStringInfo(&buf);
  3914. /* In what follows, do not risk leaking any PGresults. */
  3915. PG_TRY();
  3916. {
  3917. /* Check that the schema really exists */
  3918. appendStringInfoString(&buf, "SELECT 1 FROM pg_catalog.pg_namespace WHERE nspname = ");
  3919. deparseStringLiteral(&buf, stmt->remote_schema);
  3920. res = pgfdw_exec_query(conn, buf.data);
  3921. if (PQresultStatus(res) != PGRES_TUPLES_OK)
  3922. pgfdw_report_error(ERROR, res, conn, false, buf.data);
  3923. if (PQntuples(res) != 1)
  3924. ereport(ERROR,
  3925. (errcode(ERRCODE_FDW_SCHEMA_NOT_FOUND),
  3926. errmsg("schema \"%s\" is not present on foreign server \"%s\"",
  3927. stmt->remote_schema, server->servername)));
  3928. PQclear(res);
  3929. res = NULL;
  3930. resetStringInfo(&buf);
  3931. /*
  3932. * Fetch all table data from this schema, possibly restricted by
  3933. * EXCEPT or LIMIT TO. (We don't actually need to pay any attention
  3934. * to EXCEPT/LIMIT TO here, because the core code will filter the
  3935. * statements we return according to those lists anyway. But it
  3936. * should save a few cycles to not process excluded tables in the
  3937. * first place.)
  3938. *
  3939. * Ignore table data for partitions and only include the definitions
  3940. * of the root partitioned tables to allow access to the complete
  3941. * remote data set locally in the schema imported.
  3942. *
  3943. * Note: because we run the connection with search_path restricted to
  3944. * pg_catalog, the format_type() and pg_get_expr() outputs will always
  3945. * include a schema name for types/functions in other schemas, which
  3946. * is what we want.
  3947. */
  3948. if (import_collate)
  3949. appendStringInfoString(&buf,
  3950. "SELECT relname, "
  3951. " attname, "
  3952. " format_type(atttypid, atttypmod), "
  3953. " attnotnull, "
  3954. " pg_get_expr(adbin, adrelid), "
  3955. " collname, "
  3956. " collnsp.nspname "
  3957. "FROM pg_class c "
  3958. " JOIN pg_namespace n ON "
  3959. " relnamespace = n.oid "
  3960. " LEFT JOIN pg_attribute a ON "
  3961. " attrelid = c.oid AND attnum > 0 "
  3962. " AND NOT attisdropped "
  3963. " LEFT JOIN pg_attrdef ad ON "
  3964. " adrelid = c.oid AND adnum = attnum "
  3965. " LEFT JOIN pg_collation coll ON "
  3966. " coll.oid = attcollation "
  3967. " LEFT JOIN pg_namespace collnsp ON "
  3968. " collnsp.oid = collnamespace ");
  3969. else
  3970. appendStringInfoString(&buf,
  3971. "SELECT relname, "
  3972. " attname, "
  3973. " format_type(atttypid, atttypmod), "
  3974. " attnotnull, "
  3975. " pg_get_expr(adbin, adrelid), "
  3976. " NULL, NULL "
  3977. "FROM pg_class c "
  3978. " JOIN pg_namespace n ON "
  3979. " relnamespace = n.oid "
  3980. " LEFT JOIN pg_attribute a ON "
  3981. " attrelid = c.oid AND attnum > 0 "
  3982. " AND NOT attisdropped "
  3983. " LEFT JOIN pg_attrdef ad ON "
  3984. " adrelid = c.oid AND adnum = attnum ");
  3985. appendStringInfoString(&buf,
  3986. "WHERE c.relkind IN ("
  3987. CppAsString2(RELKIND_RELATION) ","
  3988. CppAsString2(RELKIND_VIEW) ","
  3989. CppAsString2(RELKIND_FOREIGN_TABLE) ","
  3990. CppAsString2(RELKIND_MATVIEW) ","
  3991. CppAsString2(RELKIND_PARTITIONED_TABLE) ") "
  3992. " AND n.nspname = ");
  3993. deparseStringLiteral(&buf, stmt->remote_schema);
  3994. /* Partitions are supported since Postgres 10 */
  3995. if (PQserverVersion(conn) >= 100000)
  3996. appendStringInfoString(&buf, " AND NOT c.relispartition ");
  3997. /* Apply restrictions for LIMIT TO and EXCEPT */
  3998. if (stmt->list_type == FDW_IMPORT_SCHEMA_LIMIT_TO ||
  3999. stmt->list_type == FDW_IMPORT_SCHEMA_EXCEPT)
  4000. {
  4001. bool first_item = true;
  4002. appendStringInfoString(&buf, " AND c.relname ");
  4003. if (stmt->list_type == FDW_IMPORT_SCHEMA_EXCEPT)
  4004. appendStringInfoString(&buf, "NOT ");
  4005. appendStringInfoString(&buf, "IN (");
  4006. /* Append list of table names within IN clause */
  4007. foreach(lc, stmt->table_list)
  4008. {
  4009. RangeVar *rv = (RangeVar *) lfirst(lc);
  4010. if (first_item)
  4011. first_item = false;
  4012. else
  4013. appendStringInfoString(&buf, ", ");
  4014. deparseStringLiteral(&buf, rv->relname);
  4015. }
  4016. appendStringInfoChar(&buf, ')');
  4017. }
  4018. /* Append ORDER BY at the end of query to ensure output ordering */
  4019. appendStringInfoString(&buf, " ORDER BY c.relname, a.attnum");
  4020. /* Fetch the data */
  4021. res = pgfdw_exec_query(conn, buf.data);
  4022. if (PQresultStatus(res) != PGRES_TUPLES_OK)
  4023. pgfdw_report_error(ERROR, res, conn, false, buf.data);
  4024. /* Process results */
  4025. numrows = PQntuples(res);
  4026. /* note: incrementation of i happens in inner loop's while() test */
  4027. for (i = 0; i < numrows;)
  4028. {
  4029. char *tablename = PQgetvalue(res, i, 0);
  4030. bool first_item = true;
  4031. resetStringInfo(&buf);
  4032. appendStringInfo(&buf, "CREATE FOREIGN TABLE %s (\n",
  4033. quote_identifier(tablename));
  4034. /* Scan all rows for this table */
  4035. do
  4036. {
  4037. char *attname;
  4038. char *typename;
  4039. char *attnotnull;
  4040. char *attdefault;
  4041. char *collname;
  4042. char *collnamespace;
  4043. /* If table has no columns, we'll see nulls here */
  4044. if (PQgetisnull(res, i, 1))
  4045. continue;
  4046. attname = PQgetvalue(res, i, 1);
  4047. typename = PQgetvalue(res, i, 2);
  4048. attnotnull = PQgetvalue(res, i, 3);
  4049. attdefault = PQgetisnull(res, i, 4) ? (char *) NULL :
  4050. PQgetvalue(res, i, 4);
  4051. collname = PQgetisnull(res, i, 5) ? (char *) NULL :
  4052. PQgetvalue(res, i, 5);
  4053. collnamespace = PQgetisnull(res, i, 6) ? (char *) NULL :
  4054. PQgetvalue(res, i, 6);
  4055. if (first_item)
  4056. first_item = false;
  4057. else
  4058. appendStringInfoString(&buf, ",\n");
  4059. /* Print column name and type */
  4060. appendStringInfo(&buf, " %s %s",
  4061. quote_identifier(attname),
  4062. typename);
  4063. /*
  4064. * Add column_name option so that renaming the foreign table's
  4065. * column doesn't break the association to the underlying
  4066. * column.
  4067. */
  4068. appendStringInfoString(&buf, " OPTIONS (column_name ");
  4069. deparseStringLiteral(&buf, attname);
  4070. appendStringInfoChar(&buf, ')');
  4071. /* Add COLLATE if needed */
  4072. if (import_collate && collname != NULL && collnamespace != NULL)
  4073. appendStringInfo(&buf, " COLLATE %s.%s",
  4074. quote_identifier(collnamespace),
  4075. quote_identifier(collname));
  4076. /* Add DEFAULT if needed */
  4077. if (import_default && attdefault != NULL)
  4078. appendStringInfo(&buf, " DEFAULT %s", attdefault);
  4079. /* Add NOT NULL if needed */
  4080. if (import_not_null && attnotnull[0] == 't')
  4081. appendStringInfoString(&buf, " NOT NULL");
  4082. }
  4083. while (++i < numrows &&
  4084. strcmp(PQgetvalue(res, i, 0), tablename) == 0);
  4085. /*
  4086. * Add server name and table-level options. We specify remote
  4087. * schema and table name as options (the latter to ensure that
  4088. * renaming the foreign table doesn't break the association).
  4089. */
  4090. appendStringInfo(&buf, "\n) SERVER %s\nOPTIONS (",
  4091. quote_identifier(server->servername));
  4092. appendStringInfoString(&buf, "schema_name ");
  4093. deparseStringLiteral(&buf, stmt->remote_schema);
  4094. appendStringInfoString(&buf, ", table_name ");
  4095. deparseStringLiteral(&buf, tablename);
  4096. appendStringInfoString(&buf, ");");
  4097. commands = lappend(commands, pstrdup(buf.data));
  4098. }
  4099. /* Clean up */
  4100. PQclear(res);
  4101. res = NULL;
  4102. }
  4103. PG_CATCH();
  4104. {
  4105. if (res)
  4106. PQclear(res);
  4107. PG_RE_THROW();
  4108. }
  4109. PG_END_TRY();
  4110. ReleaseConnection(conn);
  4111. return commands;
  4112. }
  4113. /*
  4114. * Assess whether the join between inner and outer relations can be pushed down
  4115. * to the foreign server. As a side effect, save information we obtain in this
  4116. * function to PgFdwRelationInfo passed in.
  4117. */
  4118. static bool
  4119. foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype,
  4120. RelOptInfo *outerrel, RelOptInfo *innerrel,
  4121. JoinPathExtraData *extra)
  4122. {
  4123. PgFdwRelationInfo *fpinfo;
  4124. PgFdwRelationInfo *fpinfo_o;
  4125. PgFdwRelationInfo *fpinfo_i;
  4126. ListCell *lc;
  4127. List *joinclauses;
  4128. /*
  4129. * We support pushing down INNER, LEFT, RIGHT and FULL OUTER joins.
  4130. * Constructing queries representing SEMI and ANTI joins is hard, hence
  4131. * not considered right now.
  4132. */
  4133. if (jointype != JOIN_INNER && jointype != JOIN_LEFT &&
  4134. jointype != JOIN_RIGHT && jointype != JOIN_FULL)
  4135. return false;
  4136. /*
  4137. * If either of the joining relations is marked as unsafe to pushdown, the
  4138. * join can not be pushed down.
  4139. */
  4140. fpinfo = (PgFdwRelationInfo *) joinrel->fdw_private;
  4141. fpinfo_o = (PgFdwRelationInfo *) outerrel->fdw_private;
  4142. fpinfo_i = (PgFdwRelationInfo *) innerrel->fdw_private;
  4143. if (!fpinfo_o || !fpinfo_o->pushdown_safe ||
  4144. !fpinfo_i || !fpinfo_i->pushdown_safe)
  4145. return false;
  4146. /*
  4147. * If joining relations have local conditions, those conditions are
  4148. * required to be applied before joining the relations. Hence the join can
  4149. * not be pushed down.
  4150. */
  4151. if (fpinfo_o->local_conds || fpinfo_i->local_conds)
  4152. return false;
  4153. /*
  4154. * Merge FDW options. We might be tempted to do this after we have deemed
  4155. * the foreign join to be OK. But we must do this beforehand so that we
  4156. * know which quals can be evaluated on the foreign server, which might
  4157. * depend on shippable_extensions.
  4158. */
  4159. fpinfo->server = fpinfo_o->server;
  4160. merge_fdw_options(fpinfo, fpinfo_o, fpinfo_i);
  4161. /*
  4162. * Separate restrict list into join quals and pushed-down (other) quals.
  4163. *
  4164. * Join quals belonging to an outer join must all be shippable, else we
  4165. * cannot execute the join remotely. Add such quals to 'joinclauses'.
  4166. *
  4167. * Add other quals to fpinfo->remote_conds if they are shippable, else to
  4168. * fpinfo->local_conds. In an inner join it's okay to execute conditions
  4169. * either locally or remotely; the same is true for pushed-down conditions
  4170. * at an outer join.
  4171. *
  4172. * Note we might return failure after having already scribbled on
  4173. * fpinfo->remote_conds and fpinfo->local_conds. That's okay because we
  4174. * won't consult those lists again if we deem the join unshippable.
  4175. */
  4176. joinclauses = NIL;
  4177. foreach(lc, extra->restrictlist)
  4178. {
  4179. RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
  4180. bool is_remote_clause = is_foreign_expr(root, joinrel,
  4181. rinfo->clause);
  4182. if (IS_OUTER_JOIN(jointype) &&
  4183. !RINFO_IS_PUSHED_DOWN(rinfo, joinrel->relids))
  4184. {
  4185. if (!is_remote_clause)
  4186. return false;
  4187. joinclauses = lappend(joinclauses, rinfo);
  4188. }
  4189. else
  4190. {
  4191. if (is_remote_clause)
  4192. fpinfo->remote_conds = lappend(fpinfo->remote_conds, rinfo);
  4193. else
  4194. fpinfo->local_conds = lappend(fpinfo->local_conds, rinfo);
  4195. }
  4196. }
  4197. /*
  4198. * deparseExplicitTargetList() isn't smart enough to handle anything other
  4199. * than a Var. In particular, if there's some PlaceHolderVar that would
  4200. * need to be evaluated within this join tree (because there's an upper
  4201. * reference to a quantity that may go to NULL as a result of an outer
  4202. * join), then we can't try to push the join down because we'll fail when
  4203. * we get to deparseExplicitTargetList(). However, a PlaceHolderVar that
  4204. * needs to be evaluated *at the top* of this join tree is OK, because we
  4205. * can do that locally after fetching the results from the remote side.
  4206. */
  4207. foreach(lc, root->placeholder_list)
  4208. {
  4209. PlaceHolderInfo *phinfo = lfirst(lc);
  4210. Relids relids;
  4211. /* PlaceHolderInfo refers to parent relids, not child relids. */
  4212. relids = IS_OTHER_REL(joinrel) ?
  4213. joinrel->top_parent_relids : joinrel->relids;
  4214. if (bms_is_subset(phinfo->ph_eval_at, relids) &&
  4215. bms_nonempty_difference(relids, phinfo->ph_eval_at))
  4216. return false;
  4217. }
  4218. /* Save the join clauses, for later use. */
  4219. fpinfo->joinclauses = joinclauses;
  4220. fpinfo->outerrel = outerrel;
  4221. fpinfo->innerrel = innerrel;
  4222. fpinfo->jointype = jointype;
  4223. /*
  4224. * By default, both the input relations are not required to be deparsed as
  4225. * subqueries, but there might be some relations covered by the input
  4226. * relations that are required to be deparsed as subqueries, so save the
  4227. * relids of those relations for later use by the deparser.
  4228. */
  4229. fpinfo->make_outerrel_subquery = false;
  4230. fpinfo->make_innerrel_subquery = false;
  4231. Assert(bms_is_subset(fpinfo_o->lower_subquery_rels, outerrel->relids));
  4232. Assert(bms_is_subset(fpinfo_i->lower_subquery_rels, innerrel->relids));
  4233. fpinfo->lower_subquery_rels = bms_union(fpinfo_o->lower_subquery_rels,
  4234. fpinfo_i->lower_subquery_rels);
  4235. /*
  4236. * Pull the other remote conditions from the joining relations into join
  4237. * clauses or other remote clauses (remote_conds) of this relation
  4238. * wherever possible. This avoids building subqueries at every join step.
  4239. *
  4240. * For an inner join, clauses from both the relations are added to the
  4241. * other remote clauses. For LEFT and RIGHT OUTER join, the clauses from
  4242. * the outer side are added to remote_conds since those can be evaluated
  4243. * after the join is evaluated. The clauses from inner side are added to
  4244. * the joinclauses, since they need to be evaluated while constructing the
  4245. * join.
  4246. *
  4247. * For a FULL OUTER JOIN, the other clauses from either relation can not
  4248. * be added to the joinclauses or remote_conds, since each relation acts
  4249. * as an outer relation for the other.
  4250. *
  4251. * The joining sides can not have local conditions, thus no need to test
  4252. * shippability of the clauses being pulled up.
  4253. */
  4254. switch (jointype)
  4255. {
  4256. case JOIN_INNER:
  4257. fpinfo->remote_conds = list_concat(fpinfo->remote_conds,
  4258. list_copy(fpinfo_i->remote_conds));
  4259. fpinfo->remote_conds = list_concat(fpinfo->remote_conds,
  4260. list_copy(fpinfo_o->remote_conds));
  4261. break;
  4262. case JOIN_LEFT:
  4263. fpinfo->joinclauses = list_concat(fpinfo->joinclauses,
  4264. list_copy(fpinfo_i->remote_conds));
  4265. fpinfo->remote_conds = list_concat(fpinfo->remote_conds,
  4266. list_copy(fpinfo_o->remote_conds));
  4267. break;
  4268. case JOIN_RIGHT:
  4269. fpinfo->joinclauses = list_concat(fpinfo->joinclauses,
  4270. list_copy(fpinfo_o->remote_conds));
  4271. fpinfo->remote_conds = list_concat(fpinfo->remote_conds,
  4272. list_copy(fpinfo_i->remote_conds));
  4273. break;
  4274. case JOIN_FULL:
  4275. /*
  4276. * In this case, if any of the input relations has conditions, we
  4277. * need to deparse that relation as a subquery so that the
  4278. * conditions can be evaluated before the join. Remember it in
  4279. * the fpinfo of this relation so that the deparser can take
  4280. * appropriate action. Also, save the relids of base relations
  4281. * covered by that relation for later use by the deparser.
  4282. */
  4283. if (fpinfo_o->remote_conds)
  4284. {
  4285. fpinfo->make_outerrel_subquery = true;
  4286. fpinfo->lower_subquery_rels =
  4287. bms_add_members(fpinfo->lower_subquery_rels,
  4288. outerrel->relids);
  4289. }
  4290. if (fpinfo_i->remote_conds)
  4291. {
  4292. fpinfo->make_innerrel_subquery = true;
  4293. fpinfo->lower_subquery_rels =
  4294. bms_add_members(fpinfo->lower_subquery_rels,
  4295. innerrel->relids);
  4296. }
  4297. break;
  4298. default:
  4299. /* Should not happen, we have just checked this above */
  4300. elog(ERROR, "unsupported join type %d", jointype);
  4301. }
  4302. /*
  4303. * For an inner join, all restrictions can be treated alike. Treating the
  4304. * pushed down conditions as join conditions allows a top level full outer
  4305. * join to be deparsed without requiring subqueries.
  4306. */
  4307. if (jointype == JOIN_INNER)
  4308. {
  4309. Assert(!fpinfo->joinclauses);
  4310. fpinfo->joinclauses = fpinfo->remote_conds;
  4311. fpinfo->remote_conds = NIL;
  4312. }
  4313. /* Mark that this join can be pushed down safely */
  4314. fpinfo->pushdown_safe = true;
  4315. /* Get user mapping */
  4316. if (fpinfo->use_remote_estimate)
  4317. {
  4318. if (fpinfo_o->use_remote_estimate)
  4319. fpinfo->user = fpinfo_o->user;
  4320. else
  4321. fpinfo->user = fpinfo_i->user;
  4322. }
  4323. else
  4324. fpinfo->user = NULL;
  4325. /*
  4326. * Set cached relation costs to some negative value, so that we can detect
  4327. * when they are set to some sensible costs, during one (usually the
  4328. * first) of the calls to estimate_path_cost_size().
  4329. */
  4330. fpinfo->rel_startup_cost = -1;
  4331. fpinfo->rel_total_cost = -1;
  4332. /*
  4333. * Set the string describing this join relation to be used in EXPLAIN
  4334. * output of corresponding ForeignScan.
  4335. */
  4336. fpinfo->relation_name = makeStringInfo();
  4337. appendStringInfo(fpinfo->relation_name, "(%s) %s JOIN (%s)",
  4338. fpinfo_o->relation_name->data,
  4339. get_jointype_name(fpinfo->jointype),
  4340. fpinfo_i->relation_name->data);
  4341. /*
  4342. * Set the relation index. This is defined as the position of this
  4343. * joinrel in the join_rel_list list plus the length of the rtable list.
  4344. * Note that since this joinrel is at the end of the join_rel_list list
  4345. * when we are called, we can get the position by list_length.
  4346. */
  4347. Assert(fpinfo->relation_index == 0); /* shouldn't be set yet */
  4348. fpinfo->relation_index =
  4349. list_length(root->parse->rtable) + list_length(root->join_rel_list);
  4350. return true;
  4351. }
  4352. static void
  4353. add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel,
  4354. Path *epq_path)
  4355. {
  4356. List *useful_pathkeys_list = NIL; /* List of all pathkeys */
  4357. ListCell *lc;
  4358. useful_pathkeys_list = get_useful_pathkeys_for_relation(root, rel);
  4359. /* Create one path for each set of pathkeys we found above. */
  4360. foreach(lc, useful_pathkeys_list)
  4361. {
  4362. double rows;
  4363. int width;
  4364. Cost startup_cost;
  4365. Cost total_cost;
  4366. List *useful_pathkeys = lfirst(lc);
  4367. Path *sorted_epq_path;
  4368. estimate_path_cost_size(root, rel, NIL, useful_pathkeys,
  4369. &rows, &width, &startup_cost, &total_cost);
  4370. /*
  4371. * The EPQ path must be at least as well sorted as the path itself, in
  4372. * case it gets used as input to a mergejoin.
  4373. */
  4374. sorted_epq_path = epq_path;
  4375. if (sorted_epq_path != NULL &&
  4376. !pathkeys_contained_in(useful_pathkeys,
  4377. sorted_epq_path->pathkeys))
  4378. sorted_epq_path = (Path *)
  4379. create_sort_path(root,
  4380. rel,
  4381. sorted_epq_path,
  4382. useful_pathkeys,
  4383. -1.0);
  4384. add_path(rel, (Path *)
  4385. create_foreignscan_path(root, rel,
  4386. NULL,
  4387. rows,
  4388. startup_cost,
  4389. total_cost,
  4390. useful_pathkeys,
  4391. NULL,
  4392. sorted_epq_path,
  4393. NIL));
  4394. }
  4395. }
  4396. /*
  4397. * Parse options from foreign server and apply them to fpinfo.
  4398. *
  4399. * New options might also require tweaking merge_fdw_options().
  4400. */
  4401. static void
  4402. apply_server_options(PgFdwRelationInfo *fpinfo)
  4403. {
  4404. ListCell *lc;
  4405. foreach(lc, fpinfo->server->options)
  4406. {
  4407. DefElem *def = (DefElem *) lfirst(lc);
  4408. if (strcmp(def->defname, "use_remote_estimate") == 0)
  4409. fpinfo->use_remote_estimate = defGetBoolean(def);
  4410. else if (strcmp(def->defname, "fdw_startup_cost") == 0)
  4411. fpinfo->fdw_startup_cost = strtod(defGetString(def), NULL);
  4412. else if (strcmp(def->defname, "fdw_tuple_cost") == 0)
  4413. fpinfo->fdw_tuple_cost = strtod(defGetString(def), NULL);
  4414. else if (strcmp(def->defname, "extensions") == 0)
  4415. fpinfo->shippable_extensions =
  4416. ExtractExtensionList(defGetString(def), false);
  4417. else if (strcmp(def->defname, "fetch_size") == 0)
  4418. fpinfo->fetch_size = strtol(defGetString(def), NULL, 10);
  4419. }
  4420. }
  4421. /*
  4422. * Parse options from foreign table and apply them to fpinfo.
  4423. *
  4424. * New options might also require tweaking merge_fdw_options().
  4425. */
  4426. static void
  4427. apply_table_options(PgFdwRelationInfo *fpinfo)
  4428. {
  4429. ListCell *lc;
  4430. foreach(lc, fpinfo->table->options)
  4431. {
  4432. DefElem *def = (DefElem *) lfirst(lc);
  4433. if (strcmp(def->defname, "use_remote_estimate") == 0)
  4434. fpinfo->use_remote_estimate = defGetBoolean(def);
  4435. else if (strcmp(def->defname, "fetch_size") == 0)
  4436. fpinfo->fetch_size = strtol(defGetString(def), NULL, 10);
  4437. }
  4438. }
  4439. /*
  4440. * Merge FDW options from input relations into a new set of options for a join
  4441. * or an upper rel.
  4442. *
  4443. * For a join relation, FDW-specific information about the inner and outer
  4444. * relations is provided using fpinfo_i and fpinfo_o. For an upper relation,
  4445. * fpinfo_o provides the information for the input relation; fpinfo_i is
  4446. * expected to NULL.
  4447. */
  4448. static void
  4449. merge_fdw_options(PgFdwRelationInfo *fpinfo,
  4450. const PgFdwRelationInfo *fpinfo_o,
  4451. const PgFdwRelationInfo *fpinfo_i)
  4452. {
  4453. /* We must always have fpinfo_o. */
  4454. Assert(fpinfo_o);
  4455. /* fpinfo_i may be NULL, but if present the servers must both match. */
  4456. Assert(!fpinfo_i ||
  4457. fpinfo_i->server->serverid == fpinfo_o->server->serverid);
  4458. /*
  4459. * Copy the server specific FDW options. (For a join, both relations come
  4460. * from the same server, so the server options should have the same value
  4461. * for both relations.)
  4462. */
  4463. fpinfo->fdw_startup_cost = fpinfo_o->fdw_startup_cost;
  4464. fpinfo->fdw_tuple_cost = fpinfo_o->fdw_tuple_cost;
  4465. fpinfo->shippable_extensions = fpinfo_o->shippable_extensions;
  4466. fpinfo->use_remote_estimate = fpinfo_o->use_remote_estimate;
  4467. fpinfo->fetch_size = fpinfo_o->fetch_size;
  4468. /* Merge the table level options from either side of the join. */
  4469. if (fpinfo_i)
  4470. {
  4471. /*
  4472. * We'll prefer to use remote estimates for this join if any table
  4473. * from either side of the join is using remote estimates. This is
  4474. * most likely going to be preferred since they're already willing to
  4475. * pay the price of a round trip to get the remote EXPLAIN. In any
  4476. * case it's not entirely clear how we might otherwise handle this
  4477. * best.
  4478. */
  4479. fpinfo->use_remote_estimate = fpinfo_o->use_remote_estimate ||
  4480. fpinfo_i->use_remote_estimate;
  4481. /*
  4482. * Set fetch size to maximum of the joining sides, since we are
  4483. * expecting the rows returned by the join to be proportional to the
  4484. * relation sizes.
  4485. */
  4486. fpinfo->fetch_size = Max(fpinfo_o->fetch_size, fpinfo_i->fetch_size);
  4487. }
  4488. }
  4489. /*
  4490. * postgresGetForeignJoinPaths
  4491. * Add possible ForeignPath to joinrel, if join is safe to push down.
  4492. */
  4493. static void
  4494. postgresGetForeignJoinPaths(PlannerInfo *root,
  4495. RelOptInfo *joinrel,
  4496. RelOptInfo *outerrel,
  4497. RelOptInfo *innerrel,
  4498. JoinType jointype,
  4499. JoinPathExtraData *extra)
  4500. {
  4501. PgFdwRelationInfo *fpinfo;
  4502. ForeignPath *joinpath;
  4503. double rows;
  4504. int width;
  4505. Cost startup_cost;
  4506. Cost total_cost;
  4507. Path *epq_path; /* Path to create plan to be executed when
  4508. * EvalPlanQual gets triggered. */
  4509. /*
  4510. * Skip if this join combination has been considered already.
  4511. */
  4512. if (joinrel->fdw_private)
  4513. return;
  4514. /*
  4515. * Create unfinished PgFdwRelationInfo entry which is used to indicate
  4516. * that the join relation is already considered, so that we won't waste
  4517. * time in judging safety of join pushdown and adding the same paths again
  4518. * if found safe. Once we know that this join can be pushed down, we fill
  4519. * the entry.
  4520. */
  4521. fpinfo = (PgFdwRelationInfo *) palloc0(sizeof(PgFdwRelationInfo));
  4522. fpinfo->pushdown_safe = false;
  4523. joinrel->fdw_private = fpinfo;
  4524. /* attrs_used is only for base relations. */
  4525. fpinfo->attrs_used = NULL;
  4526. /*
  4527. * If there is a possibility that EvalPlanQual will be executed, we need
  4528. * to be able to reconstruct the row using scans of the base relations.
  4529. * GetExistingLocalJoinPath will find a suitable path for this purpose in
  4530. * the path list of the joinrel, if one exists. We must be careful to
  4531. * call it before adding any ForeignPath, since the ForeignPath might
  4532. * dominate the only suitable local path available. We also do it before
  4533. * calling foreign_join_ok(), since that function updates fpinfo and marks
  4534. * it as pushable if the join is found to be pushable.
  4535. */
  4536. if (root->parse->commandType == CMD_DELETE ||
  4537. root->parse->commandType == CMD_UPDATE ||
  4538. root->rowMarks)
  4539. {
  4540. epq_path = GetExistingLocalJoinPath(joinrel);
  4541. if (!epq_path)
  4542. {
  4543. elog(DEBUG3, "could not push down foreign join because a local path suitable for EPQ checks was not found");
  4544. return;
  4545. }
  4546. }
  4547. else
  4548. epq_path = NULL;
  4549. if (!foreign_join_ok(root, joinrel, jointype, outerrel, innerrel, extra))
  4550. {
  4551. /* Free path required for EPQ if we copied one; we don't need it now */
  4552. if (epq_path)
  4553. pfree(epq_path);
  4554. return;
  4555. }
  4556. /*
  4557. * Compute the selectivity and cost of the local_conds, so we don't have
  4558. * to do it over again for each path. The best we can do for these
  4559. * conditions is to estimate selectivity on the basis of local statistics.
  4560. * The local conditions are applied after the join has been computed on
  4561. * the remote side like quals in WHERE clause, so pass jointype as
  4562. * JOIN_INNER.
  4563. */
  4564. fpinfo->local_conds_sel = clauselist_selectivity(root,
  4565. fpinfo->local_conds,
  4566. 0,
  4567. JOIN_INNER,
  4568. NULL);
  4569. cost_qual_eval(&fpinfo->local_conds_cost, fpinfo->local_conds, root);
  4570. /*
  4571. * If we are going to estimate costs locally, estimate the join clause
  4572. * selectivity here while we have special join info.
  4573. */
  4574. if (!fpinfo->use_remote_estimate)
  4575. fpinfo->joinclause_sel = clauselist_selectivity(root, fpinfo->joinclauses,
  4576. 0, fpinfo->jointype,
  4577. extra->sjinfo);
  4578. /* Estimate costs for bare join relation */
  4579. estimate_path_cost_size(root, joinrel, NIL, NIL, &rows,
  4580. &width, &startup_cost, &total_cost);
  4581. /* Now update this information in the joinrel */
  4582. joinrel->rows = rows;
  4583. joinrel->reltarget->width = width;
  4584. fpinfo->rows = rows;
  4585. fpinfo->width = width;
  4586. fpinfo->startup_cost = startup_cost;
  4587. fpinfo->total_cost = total_cost;
  4588. /*
  4589. * Create a new join path and add it to the joinrel which represents a
  4590. * join between foreign tables.
  4591. */
  4592. joinpath = create_foreignscan_path(root,
  4593. joinrel,
  4594. NULL, /* default pathtarget */
  4595. rows,
  4596. startup_cost,
  4597. total_cost,
  4598. NIL, /* no pathkeys */
  4599. NULL, /* no required_outer */
  4600. epq_path,
  4601. NIL); /* no fdw_private */
  4602. /* Add generated path into joinrel by add_path(). */
  4603. add_path(joinrel, (Path *) joinpath);
  4604. /* Consider pathkeys for the join relation */
  4605. add_paths_with_pathkeys_for_rel(root, joinrel, epq_path);
  4606. /* XXX Consider parameterized paths for the join relation */
  4607. }
  4608. /*
  4609. * Assess whether the aggregation, grouping and having operations can be pushed
  4610. * down to the foreign server. As a side effect, save information we obtain in
  4611. * this function to PgFdwRelationInfo of the input relation.
  4612. */
  4613. static bool
  4614. foreign_grouping_ok(PlannerInfo *root, RelOptInfo *grouped_rel,
  4615. Node *havingQual)
  4616. {
  4617. Query *query = root->parse;
  4618. PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) grouped_rel->fdw_private;
  4619. PathTarget *grouping_target = grouped_rel->reltarget;
  4620. PgFdwRelationInfo *ofpinfo;
  4621. List *aggvars;
  4622. ListCell *lc;
  4623. int i;
  4624. List *tlist = NIL;
  4625. /* We currently don't support pushing Grouping Sets. */
  4626. if (query->groupingSets)
  4627. return false;
  4628. /* Get the fpinfo of the underlying scan relation. */
  4629. ofpinfo = (PgFdwRelationInfo *) fpinfo->outerrel->fdw_private;
  4630. /*
  4631. * If underlying scan relation has any local conditions, those conditions
  4632. * are required to be applied before performing aggregation. Hence the
  4633. * aggregate cannot be pushed down.
  4634. */
  4635. if (ofpinfo->local_conds)
  4636. return false;
  4637. /*
  4638. * Examine grouping expressions, as well as other expressions we'd need to
  4639. * compute, and check whether they are safe to push down to the foreign
  4640. * server. All GROUP BY expressions will be part of the grouping target
  4641. * and thus there is no need to search for them separately. Add grouping
  4642. * expressions into target list which will be passed to foreign server.
  4643. */
  4644. i = 0;
  4645. foreach(lc, grouping_target->exprs)
  4646. {
  4647. Expr *expr = (Expr *) lfirst(lc);
  4648. Index sgref = get_pathtarget_sortgroupref(grouping_target, i);
  4649. ListCell *l;
  4650. /* Check whether this expression is part of GROUP BY clause */
  4651. if (sgref && get_sortgroupref_clause_noerr(sgref, query->groupClause))
  4652. {
  4653. TargetEntry *tle;
  4654. /*
  4655. * If any GROUP BY expression is not shippable, then we cannot
  4656. * push down aggregation to the foreign server.
  4657. */
  4658. if (!is_foreign_expr(root, grouped_rel, expr))
  4659. return false;
  4660. /*
  4661. * Pushable, so add to tlist. We need to create a TLE for this
  4662. * expression and apply the sortgroupref to it. We cannot use
  4663. * add_to_flat_tlist() here because that avoids making duplicate
  4664. * entries in the tlist. If there are duplicate entries with
  4665. * distinct sortgrouprefs, we have to duplicate that situation in
  4666. * the output tlist.
  4667. */
  4668. tle = makeTargetEntry(expr, list_length(tlist) + 1, NULL, false);
  4669. tle->ressortgroupref = sgref;
  4670. tlist = lappend(tlist, tle);
  4671. }
  4672. else
  4673. {
  4674. /*
  4675. * Non-grouping expression we need to compute. Is it shippable?
  4676. */
  4677. if (is_foreign_expr(root, grouped_rel, expr))
  4678. {
  4679. /* Yes, so add to tlist as-is; OK to suppress duplicates */
  4680. tlist = add_to_flat_tlist(tlist, list_make1(expr));
  4681. }
  4682. else
  4683. {
  4684. /* Not pushable as a whole; extract its Vars and aggregates */
  4685. aggvars = pull_var_clause((Node *) expr,
  4686. PVC_INCLUDE_AGGREGATES);
  4687. /*
  4688. * If any aggregate expression is not shippable, then we
  4689. * cannot push down aggregation to the foreign server.
  4690. */
  4691. if (!is_foreign_expr(root, grouped_rel, (Expr *) aggvars))
  4692. return false;
  4693. /*
  4694. * Add aggregates, if any, into the targetlist. Plain Vars
  4695. * outside an aggregate can be ignored, because they should be
  4696. * either same as some GROUP BY column or part of some GROUP
  4697. * BY expression. In either case, they are already part of
  4698. * the targetlist and thus no need to add them again. In fact
  4699. * including plain Vars in the tlist when they do not match a
  4700. * GROUP BY column would cause the foreign server to complain
  4701. * that the shipped query is invalid.
  4702. */
  4703. foreach(l, aggvars)
  4704. {
  4705. Expr *expr = (Expr *) lfirst(l);
  4706. if (IsA(expr, Aggref))
  4707. tlist = add_to_flat_tlist(tlist, list_make1(expr));
  4708. }
  4709. }
  4710. }
  4711. i++;
  4712. }
  4713. /*
  4714. * Classify the pushable and non-pushable HAVING clauses and save them in
  4715. * remote_conds and local_conds of the grouped rel's fpinfo.
  4716. */
  4717. if (havingQual)
  4718. {
  4719. ListCell *lc;
  4720. foreach(lc, (List *) havingQual)
  4721. {
  4722. Expr *expr = (Expr *) lfirst(lc);
  4723. RestrictInfo *rinfo;
  4724. /*
  4725. * Currently, the core code doesn't wrap havingQuals in
  4726. * RestrictInfos, so we must make our own.
  4727. */
  4728. Assert(!IsA(expr, RestrictInfo));
  4729. rinfo = make_restrictinfo(expr,
  4730. true,
  4731. false,
  4732. false,
  4733. root->qual_security_level,
  4734. grouped_rel->relids,
  4735. NULL,
  4736. NULL);
  4737. if (is_foreign_expr(root, grouped_rel, expr))
  4738. fpinfo->remote_conds = lappend(fpinfo->remote_conds, rinfo);
  4739. else
  4740. fpinfo->local_conds = lappend(fpinfo->local_conds, rinfo);
  4741. }
  4742. }
  4743. /*
  4744. * If there are any local conditions, pull Vars and aggregates from it and
  4745. * check whether they are safe to pushdown or not.
  4746. */
  4747. if (fpinfo->local_conds)
  4748. {
  4749. List *aggvars = NIL;
  4750. ListCell *lc;
  4751. foreach(lc, fpinfo->local_conds)
  4752. {
  4753. RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
  4754. aggvars = list_concat(aggvars,
  4755. pull_var_clause((Node *) rinfo->clause,
  4756. PVC_INCLUDE_AGGREGATES));
  4757. }
  4758. foreach(lc, aggvars)
  4759. {
  4760. Expr *expr = (Expr *) lfirst(lc);
  4761. /*
  4762. * If aggregates within local conditions are not safe to push
  4763. * down, then we cannot push down the query. Vars are already
  4764. * part of GROUP BY clause which are checked above, so no need to
  4765. * access them again here.
  4766. */
  4767. if (IsA(expr, Aggref))
  4768. {
  4769. if (!is_foreign_expr(root, grouped_rel, expr))
  4770. return false;
  4771. tlist = add_to_flat_tlist(tlist, list_make1(expr));
  4772. }
  4773. }
  4774. }
  4775. /* Store generated targetlist */
  4776. fpinfo->grouped_tlist = tlist;
  4777. /* Safe to pushdown */
  4778. fpinfo->pushdown_safe = true;
  4779. /*
  4780. * Set cached relation costs to some negative value, so that we can detect
  4781. * when they are set to some sensible costs, during one (usually the
  4782. * first) of the calls to estimate_path_cost_size().
  4783. */
  4784. fpinfo->rel_startup_cost = -1;
  4785. fpinfo->rel_total_cost = -1;
  4786. /*
  4787. * Set the string describing this grouped relation to be used in EXPLAIN
  4788. * output of corresponding ForeignScan.
  4789. */
  4790. fpinfo->relation_name = makeStringInfo();
  4791. appendStringInfo(fpinfo->relation_name, "Aggregate on (%s)",
  4792. ofpinfo->relation_name->data);
  4793. return true;
  4794. }
  4795. /*
  4796. * postgresGetForeignUpperPaths
  4797. * Add paths for post-join operations like aggregation, grouping etc. if
  4798. * corresponding operations are safe to push down.
  4799. *
  4800. * Right now, we only support aggregate, grouping and having clause pushdown.
  4801. */
  4802. static void
  4803. postgresGetForeignUpperPaths(PlannerInfo *root, UpperRelationKind stage,
  4804. RelOptInfo *input_rel, RelOptInfo *output_rel,
  4805. void *extra)
  4806. {
  4807. PgFdwRelationInfo *fpinfo;
  4808. /*
  4809. * If input rel is not safe to pushdown, then simply return as we cannot
  4810. * perform any post-join operations on the foreign server.
  4811. */
  4812. if (!input_rel->fdw_private ||
  4813. !((PgFdwRelationInfo *) input_rel->fdw_private)->pushdown_safe)
  4814. return;
  4815. /* Ignore stages we don't support; and skip any duplicate calls. */
  4816. if (stage != UPPERREL_GROUP_AGG || output_rel->fdw_private)
  4817. return;
  4818. fpinfo = (PgFdwRelationInfo *) palloc0(sizeof(PgFdwRelationInfo));
  4819. fpinfo->pushdown_safe = false;
  4820. output_rel->fdw_private = fpinfo;
  4821. add_foreign_grouping_paths(root, input_rel, output_rel,
  4822. (GroupPathExtraData *) extra);
  4823. }
  4824. /*
  4825. * add_foreign_grouping_paths
  4826. * Add foreign path for grouping and/or aggregation.
  4827. *
  4828. * Given input_rel represents the underlying scan. The paths are added to the
  4829. * given grouped_rel.
  4830. */
  4831. static void
  4832. add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel,
  4833. RelOptInfo *grouped_rel,
  4834. GroupPathExtraData *extra)
  4835. {
  4836. Query *parse = root->parse;
  4837. PgFdwRelationInfo *ifpinfo = input_rel->fdw_private;
  4838. PgFdwRelationInfo *fpinfo = grouped_rel->fdw_private;
  4839. ForeignPath *grouppath;
  4840. double rows;
  4841. int width;
  4842. Cost startup_cost;
  4843. Cost total_cost;
  4844. /* Nothing to be done, if there is no grouping or aggregation required. */
  4845. if (!parse->groupClause && !parse->groupingSets && !parse->hasAggs &&
  4846. !root->hasHavingQual)
  4847. return;
  4848. Assert(extra->patype == PARTITIONWISE_AGGREGATE_NONE ||
  4849. extra->patype == PARTITIONWISE_AGGREGATE_FULL);
  4850. /* save the input_rel as outerrel in fpinfo */
  4851. fpinfo->outerrel = input_rel;
  4852. /*
  4853. * Copy foreign table, foreign server, user mapping, FDW options etc.
  4854. * details from the input relation's fpinfo.
  4855. */
  4856. fpinfo->table = ifpinfo->table;
  4857. fpinfo->server = ifpinfo->server;
  4858. fpinfo->user = ifpinfo->user;
  4859. merge_fdw_options(fpinfo, ifpinfo, NULL);
  4860. /*
  4861. * Assess if it is safe to push down aggregation and grouping.
  4862. *
  4863. * Use HAVING qual from extra. In case of child partition, it will have
  4864. * translated Vars.
  4865. */
  4866. if (!foreign_grouping_ok(root, grouped_rel, extra->havingQual))
  4867. return;
  4868. /*
  4869. * Compute the selectivity and cost of the local_conds, so we don't have
  4870. * to do it over again for each path. (Currently we create just a single
  4871. * path here, but in future it would be possible that we build more paths
  4872. * such as pre-sorted paths as in postgresGetForeignPaths and
  4873. * postgresGetForeignJoinPaths.) The best we can do for these conditions
  4874. * is to estimate selectivity on the basis of local statistics.
  4875. */
  4876. fpinfo->local_conds_sel = clauselist_selectivity(root,
  4877. fpinfo->local_conds,
  4878. 0,
  4879. JOIN_INNER,
  4880. NULL);
  4881. cost_qual_eval(&fpinfo->local_conds_cost, fpinfo->local_conds, root);
  4882. /* Estimate the cost of push down */
  4883. estimate_path_cost_size(root, grouped_rel, NIL, NIL, &rows,
  4884. &width, &startup_cost, &total_cost);
  4885. /* Now update this information in the fpinfo */
  4886. fpinfo->rows = rows;
  4887. fpinfo->width = width;
  4888. fpinfo->startup_cost = startup_cost;
  4889. fpinfo->total_cost = total_cost;
  4890. /* Create and add foreign path to the grouping relation. */
  4891. grouppath = create_foreignscan_path(root,
  4892. grouped_rel,
  4893. grouped_rel->reltarget,
  4894. rows,
  4895. startup_cost,
  4896. total_cost,
  4897. NIL, /* no pathkeys */
  4898. NULL, /* no required_outer */
  4899. NULL,
  4900. NIL); /* no fdw_private */
  4901. /* Add generated path into grouped_rel by add_path(). */
  4902. add_path(grouped_rel, (Path *) grouppath);
  4903. }
  4904. /*
  4905. * Create a tuple from the specified row of the PGresult.
  4906. *
  4907. * rel is the local representation of the foreign table, attinmeta is
  4908. * conversion data for the rel's tupdesc, and retrieved_attrs is an
  4909. * integer list of the table column numbers present in the PGresult.
  4910. * temp_context is a working context that can be reset after each tuple.
  4911. */
  4912. static HeapTuple
  4913. make_tuple_from_result_row(PGresult *res,
  4914. int row,
  4915. Relation rel,
  4916. AttInMetadata *attinmeta,
  4917. List *retrieved_attrs,
  4918. ForeignScanState *fsstate,
  4919. MemoryContext temp_context)
  4920. {
  4921. HeapTuple tuple;
  4922. TupleDesc tupdesc;
  4923. Datum *values;
  4924. bool *nulls;
  4925. ItemPointer ctid = NULL;
  4926. ConversionLocation errpos;
  4927. ErrorContextCallback errcallback;
  4928. MemoryContext oldcontext;
  4929. ListCell *lc;
  4930. int j;
  4931. Assert(row < PQntuples(res));
  4932. /*
  4933. * Do the following work in a temp context that we reset after each tuple.
  4934. * This cleans up not only the data we have direct access to, but any
  4935. * cruft the I/O functions might leak.
  4936. */
  4937. oldcontext = MemoryContextSwitchTo(temp_context);
  4938. if (rel)
  4939. tupdesc = RelationGetDescr(rel);
  4940. else
  4941. {
  4942. Assert(fsstate);
  4943. tupdesc = fsstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
  4944. }
  4945. values = (Datum *) palloc0(tupdesc->natts * sizeof(Datum));
  4946. nulls = (bool *) palloc(tupdesc->natts * sizeof(bool));
  4947. /* Initialize to nulls for any columns not present in result */
  4948. memset(nulls, true, tupdesc->natts * sizeof(bool));
  4949. /*
  4950. * Set up and install callback to report where conversion error occurs.
  4951. */
  4952. errpos.rel = rel;
  4953. errpos.cur_attno = 0;
  4954. errpos.fsstate = fsstate;
  4955. errcallback.callback = conversion_error_callback;
  4956. errcallback.arg = (void *) &errpos;
  4957. errcallback.previous = error_context_stack;
  4958. error_context_stack = &errcallback;
  4959. /*
  4960. * i indexes columns in the relation, j indexes columns in the PGresult.
  4961. */
  4962. j = 0;
  4963. foreach(lc, retrieved_attrs)
  4964. {
  4965. int i = lfirst_int(lc);
  4966. char *valstr;
  4967. /* fetch next column's textual value */
  4968. if (PQgetisnull(res, row, j))
  4969. valstr = NULL;
  4970. else
  4971. valstr = PQgetvalue(res, row, j);
  4972. /*
  4973. * convert value to internal representation
  4974. *
  4975. * Note: we ignore system columns other than ctid and oid in result
  4976. */
  4977. errpos.cur_attno = i;
  4978. if (i > 0)
  4979. {
  4980. /* ordinary column */
  4981. Assert(i <= tupdesc->natts);
  4982. nulls[i - 1] = (valstr == NULL);
  4983. /* Apply the input function even to nulls, to support domains */
  4984. values[i - 1] = InputFunctionCall(&attinmeta->attinfuncs[i - 1],
  4985. valstr,
  4986. attinmeta->attioparams[i - 1],
  4987. attinmeta->atttypmods[i - 1]);
  4988. }
  4989. else if (i == SelfItemPointerAttributeNumber)
  4990. {
  4991. /* ctid */
  4992. if (valstr != NULL)
  4993. {
  4994. Datum datum;
  4995. datum = DirectFunctionCall1(tidin, CStringGetDatum(valstr));
  4996. ctid = (ItemPointer) DatumGetPointer(datum);
  4997. }
  4998. }
  4999. errpos.cur_attno = 0;
  5000. j++;
  5001. }
  5002. /* Uninstall error context callback. */
  5003. error_context_stack = errcallback.previous;
  5004. /*
  5005. * Check we got the expected number of columns. Note: j == 0 and
  5006. * PQnfields == 1 is expected, since deparse emits a NULL if no columns.
  5007. */
  5008. if (j > 0 && j != PQnfields(res))
  5009. elog(ERROR, "remote query result does not match the foreign table");
  5010. /*
  5011. * Build the result tuple in caller's memory context.
  5012. */
  5013. MemoryContextSwitchTo(oldcontext);
  5014. tuple = heap_form_tuple(tupdesc, values, nulls);
  5015. /*
  5016. * If we have a CTID to return, install it in both t_self and t_ctid.
  5017. * t_self is the normal place, but if the tuple is converted to a
  5018. * composite Datum, t_self will be lost; setting t_ctid allows CTID to be
  5019. * preserved during EvalPlanQual re-evaluations (see ROW_MARK_COPY code).
  5020. */
  5021. if (ctid)
  5022. tuple->t_self = tuple->t_data->t_ctid = *ctid;
  5023. /*
  5024. * Stomp on the xmin, xmax, and cmin fields from the tuple created by
  5025. * heap_form_tuple. heap_form_tuple actually creates the tuple with
  5026. * DatumTupleFields, not HeapTupleFields, but the executor expects
  5027. * HeapTupleFields and will happily extract system columns on that
  5028. * assumption. If we don't do this then, for example, the tuple length
  5029. * ends up in the xmin field, which isn't what we want.
  5030. */
  5031. HeapTupleHeaderSetXmax(tuple->t_data, InvalidTransactionId);
  5032. HeapTupleHeaderSetXmin(tuple->t_data, InvalidTransactionId);
  5033. HeapTupleHeaderSetCmin(tuple->t_data, InvalidTransactionId);
  5034. /* Clean up */
  5035. MemoryContextReset(temp_context);
  5036. return tuple;
  5037. }
  5038. /*
  5039. * Callback function which is called when error occurs during column value
  5040. * conversion. Print names of column and relation.
  5041. */
  5042. static void
  5043. conversion_error_callback(void *arg)
  5044. {
  5045. const char *attname = NULL;
  5046. const char *relname = NULL;
  5047. bool is_wholerow = false;
  5048. ConversionLocation *errpos = (ConversionLocation *) arg;
  5049. if (errpos->rel)
  5050. {
  5051. /* error occurred in a scan against a foreign table */
  5052. TupleDesc tupdesc = RelationGetDescr(errpos->rel);
  5053. Form_pg_attribute attr = TupleDescAttr(tupdesc, errpos->cur_attno - 1);
  5054. if (errpos->cur_attno > 0 && errpos->cur_attno <= tupdesc->natts)
  5055. attname = NameStr(attr->attname);
  5056. else if (errpos->cur_attno == SelfItemPointerAttributeNumber)
  5057. attname = "ctid";
  5058. relname = RelationGetRelationName(errpos->rel);
  5059. }
  5060. else
  5061. {
  5062. /* error occurred in a scan against a foreign join */
  5063. ForeignScanState *fsstate = errpos->fsstate;
  5064. ForeignScan *fsplan = castNode(ForeignScan, fsstate->ss.ps.plan);
  5065. EState *estate = fsstate->ss.ps.state;
  5066. TargetEntry *tle;
  5067. tle = list_nth_node(TargetEntry, fsplan->fdw_scan_tlist,
  5068. errpos->cur_attno - 1);
  5069. /*
  5070. * Target list can have Vars and expressions. For Vars, we can get
  5071. * its relation, however for expressions we can't. Thus for
  5072. * expressions, just show generic context message.
  5073. */
  5074. if (IsA(tle->expr, Var))
  5075. {
  5076. RangeTblEntry *rte;
  5077. Var *var = (Var *) tle->expr;
  5078. rte = exec_rt_fetch(var->varno, estate);
  5079. if (var->varattno == 0)
  5080. is_wholerow = true;
  5081. else
  5082. attname = get_attname(rte->relid, var->varattno, false);
  5083. relname = get_rel_name(rte->relid);
  5084. }
  5085. else
  5086. errcontext("processing expression at position %d in select list",
  5087. errpos->cur_attno);
  5088. }
  5089. if (relname)
  5090. {
  5091. if (is_wholerow)
  5092. errcontext("whole-row reference to foreign table \"%s\"", relname);
  5093. else if (attname)
  5094. errcontext("column \"%s\" of foreign table \"%s\"", attname, relname);
  5095. }
  5096. }
  5097. /*
  5098. * Find an equivalence class member expression, all of whose Vars, come from
  5099. * the indicated relation.
  5100. */
  5101. Expr *
  5102. find_em_expr_for_rel(EquivalenceClass *ec, RelOptInfo *rel)
  5103. {
  5104. ListCell *lc_em;
  5105. foreach(lc_em, ec->ec_members)
  5106. {
  5107. EquivalenceMember *em = lfirst(lc_em);
  5108. if (bms_is_subset(em->em_relids, rel->relids) &&
  5109. !bms_is_empty(em->em_relids))
  5110. {
  5111. /*
  5112. * If there is more than one equivalence member whose Vars are
  5113. * taken entirely from this relation, we'll be content to choose
  5114. * any one of those.
  5115. */
  5116. return em->em_expr;
  5117. }
  5118. }
  5119. /* We didn't find any suitable equivalence class expression */
  5120. return NULL;
  5121. }