hqlutil.cpp 306 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "jliball.hpp"
  14. #include "hql.hpp"
  15. #include "eclrtl.hpp"
  16. #include "rtldynfield.hpp"
  17. #include "platform.h"
  18. #include "jlib.hpp"
  19. #include "jmisc.hpp"
  20. #include "jstream.ipp"
  21. #include "hql.hpp"
  22. #include "hqlexpr.hpp"
  23. #include "hqlutil.hpp"
  24. #include "hqlpmap.hpp"
  25. #include "hqlfold.hpp"
  26. #include "hqlerrors.hpp"
  27. #include "hqltrans.ipp"
  28. #include "hqlusage.hpp"
  29. #include "hqlthql.hpp"
  30. #include "deffield.hpp"
  31. #include "workunit.hpp"
  32. #include "jencrypt.hpp"
  33. #include "hqlattr.hpp"
  34. #include "hqlerror.hpp"
  35. #include "hqlexpr.ipp"
  36. #include "hqlrepository.hpp"
  37. #define SIZET_CACHE_SIZE 5001
  38. #define FIXEDATTR_CACHE_SIZE 1001
  39. static ITypeInfo * sizetType;
  40. static ITypeInfo * signedType;
  41. static ITypeInfo * constUnknownVarStringType;
  42. static CriticalSection * sizetCacheCs;
  43. static IHqlExpression * sizetCache[SIZET_CACHE_SIZE];
  44. static IHqlExpression * fixedAttrSizeCache[FIXEDATTR_CACHE_SIZE];
  45. static IHqlExpression * defaultMaxRecordLengthExpr;
  46. static IHqlExpression * cacheAlignedAttr;
  47. static IHqlExpression * cacheEmbeddedAttr;
  48. static IHqlExpression * cacheInlineAttr;
  49. static IHqlExpression * cacheLinkCountedAttr;
  50. static IHqlExpression * cacheProjectedAttr;
  51. static IHqlExpression * cacheReferenceAttr;
  52. static IHqlExpression * cacheStreamedAttr;
  53. static IHqlExpression * cacheUnadornedAttr;
  54. static IHqlExpression * nlpParsePsuedoTable;
  55. static IHqlExpression * xmlParsePsuedoTable;
  56. static IHqlExpression * cachedQuotedNullExpr;
  57. static IHqlExpression * cachedGlobalSequenceNumber;
  58. static IHqlExpression * cachedLocalSequenceNumber;
  59. static IHqlExpression * cachedStoredSequenceNumber;
  60. static IHqlExpression * cachedOmittedValueExpr;
  61. static void initBoolAttr(IAtom * name, IHqlExpression * x[2])
  62. {
  63. x[0] = createExprAttribute(name, createConstant(false));
  64. x[1] = createExprAttribute(name, createConstant(true));
  65. }
  66. MODULE_INIT(INIT_PRIORITY_STANDARD)
  67. {
  68. sizetType = makeIntType(sizeof(size32_t), false);
  69. signedType = makeIntType(sizeof(signed), true);
  70. sizetCacheCs = new CriticalSection;
  71. constUnknownVarStringType = makeConstantModifier(makeVarStringType(UNKNOWN_LENGTH));
  72. defaultMaxRecordLengthExpr = createQuoted("<default-max-length>", makeIntType(sizeof(size32_t), false));
  73. cacheAlignedAttr = createAttribute(_propAligned_Atom);
  74. cacheEmbeddedAttr = createAttribute(embeddedAtom);
  75. cacheInlineAttr = createAttribute(inlineAtom);
  76. cacheLinkCountedAttr = createAttribute(_linkCounted_Atom);
  77. cacheProjectedAttr = createAttribute(projectedAtom);
  78. cacheReferenceAttr = createAttribute(referenceAtom);
  79. cacheStreamedAttr = createAttribute(streamedAtom);
  80. cacheUnadornedAttr = createAttribute(_propUnadorned_Atom);
  81. nlpParsePsuedoTable = createDataset(no_pseudods, createRecord()->closeExpr(), createAttribute(_nlpParse_Atom));
  82. xmlParsePsuedoTable = createDataset(no_pseudods, createRecord()->closeExpr(), createAttribute(_xmlParse_Atom));
  83. cachedQuotedNullExpr = createValue(no_nullptr, makeBoolType());
  84. cachedOmittedValueExpr = createValue(no_omitted, makeAnyType());
  85. cachedGlobalSequenceNumber = createConstant(signedType->castFrom(true, (__int64)ResultSequencePersist));
  86. cachedLocalSequenceNumber = createConstant(signedType->castFrom(true, (__int64)ResultSequenceInternal));
  87. cachedStoredSequenceNumber = createConstant(signedType->castFrom(true, (__int64)ResultSequenceStored));
  88. return true;
  89. }
  90. MODULE_EXIT()
  91. {
  92. delete sizetCacheCs;
  93. sizetType->Release();
  94. signedType->Release();
  95. defaultMaxRecordLengthExpr->Release();
  96. for (unsigned i=0; i < SIZET_CACHE_SIZE; i++)
  97. ::Release(sizetCache[i]);
  98. for (unsigned i2=0; i2 < FIXEDATTR_CACHE_SIZE; i2++)
  99. ::Release(fixedAttrSizeCache[i2]);
  100. cacheAlignedAttr->Release();
  101. cacheEmbeddedAttr->Release();
  102. cacheInlineAttr->Release();
  103. cacheLinkCountedAttr->Release();
  104. cacheProjectedAttr->Release();
  105. cacheReferenceAttr->Release();
  106. cacheStreamedAttr->Release();
  107. cacheUnadornedAttr->Release();
  108. xmlParsePsuedoTable->Release();
  109. nlpParsePsuedoTable->Release();
  110. cachedQuotedNullExpr->Release();
  111. cachedGlobalSequenceNumber->Release();
  112. cachedLocalSequenceNumber->Release();
  113. cachedStoredSequenceNumber->Release();
  114. cachedOmittedValueExpr->Release();
  115. constUnknownVarStringType->Release();
  116. }
  117. inline int TFI(bool value) { return value ? 0 : 1; }
  118. IHqlExpression * getSizetConstant(unsigned size)
  119. {
  120. if (size >= SIZET_CACHE_SIZE)
  121. return createConstant(sizetType->castFrom(false, (__int64)size));
  122. CriticalBlock block(*sizetCacheCs);
  123. IHqlExpression * match = sizetCache[size];
  124. if (!match)
  125. match = sizetCache[size] = createConstant(sizetType->castFrom(false, (__int64)size));
  126. return LINK(match);
  127. }
  128. IHqlExpression * createIntConstant(__int64 val)
  129. {
  130. return createConstant(createMinIntValue(val));
  131. }
  132. IHqlExpression * createUIntConstant(unsigned __int64 val)
  133. {
  134. return createConstant(createMinIntValue(val));
  135. }
  136. inline IIdAtom * createMangledName(IHqlExpression * module, IHqlExpression * child)
  137. {
  138. StringBuffer mangledName;
  139. mangledName.append(module->queryName()).append(".").append(child->queryName());
  140. return createIdAtom(mangledName.str());
  141. }
  142. IHqlExpression * queryDefaultMaxRecordLengthExpr()
  143. {
  144. return defaultMaxRecordLengthExpr;
  145. };
  146. HQL_API IHqlExpression * getFixedSizeAttr(unsigned size)
  147. {
  148. if (size >= FIXEDATTR_CACHE_SIZE)
  149. {
  150. OwnedHqlExpr sizeExpr = getSizetConstant(size);
  151. return createExprAttribute(_propSize_Atom, LINK(sizeExpr), LINK(sizeExpr), LINK(sizeExpr));
  152. }
  153. CriticalBlock block(*sizetCacheCs); // reuse the critical section
  154. IHqlExpression * match = fixedAttrSizeCache[size];
  155. if (!match)
  156. {
  157. OwnedHqlExpr sizeExpr = getSizetConstant(size);
  158. match = fixedAttrSizeCache[size] = createExprAttribute(_propSize_Atom, LINK(sizeExpr), LINK(sizeExpr), LINK(sizeExpr));
  159. }
  160. return LINK(match);
  161. }
  162. extern HQL_API IHqlExpression * queryQuotedNullExpr()
  163. {
  164. return cachedQuotedNullExpr;
  165. }
  166. extern HQL_API IHqlExpression * createOmittedValue()
  167. {
  168. return LINK(cachedOmittedValueExpr);
  169. }
  170. #if 0
  171. IHqlExpression * queryRequiresDestructorAttr(bool value)
  172. {
  173. return cacheRequiresDestructorAttr[TFI(value)];
  174. }
  175. #endif
  176. IHqlExpression * queryUnadornedAttr()
  177. {
  178. return cacheUnadornedAttr;
  179. }
  180. IHqlExpression * queryAlignedAttr()
  181. {
  182. return cacheAlignedAttr;
  183. }
  184. extern HQL_API IHqlExpression * queryLinkCountedAttr()
  185. {
  186. return cacheLinkCountedAttr;
  187. }
  188. extern HQL_API IHqlExpression * queryProjectedAttr()
  189. {
  190. return cacheProjectedAttr;
  191. }
  192. extern HQL_API IHqlExpression * getLinkCountedAttr()
  193. {
  194. return LINK(cacheLinkCountedAttr);
  195. }
  196. extern HQL_API IHqlExpression * getProjectedAttr()
  197. {
  198. return LINK(cacheProjectedAttr);
  199. }
  200. extern HQL_API IHqlExpression * getStreamedAttr()
  201. {
  202. return LINK(cacheStreamedAttr);
  203. }
  204. extern HQL_API IHqlExpression * getInlineAttr()
  205. {
  206. return LINK(cacheInlineAttr);
  207. }
  208. extern HQL_API IHqlExpression * getEmbeddedAttr()
  209. {
  210. return LINK(cacheEmbeddedAttr);
  211. }
  212. extern HQL_API IHqlExpression * getReferenceAttr()
  213. {
  214. return LINK(cacheReferenceAttr);
  215. }
  216. extern HQL_API IHqlExpression * queryNlpParsePseudoTable()
  217. {
  218. return nlpParsePsuedoTable;
  219. }
  220. extern HQL_API IHqlExpression * queryXmlParsePseudoTable()
  221. {
  222. return xmlParsePsuedoTable;
  223. }
  224. IHqlExpression * getGlobalSequenceNumber() { return LINK(cachedGlobalSequenceNumber); }
  225. IHqlExpression * getLocalSequenceNumber() { return LINK(cachedLocalSequenceNumber); }
  226. IHqlExpression * getStoredSequenceNumber() { return LINK(cachedStoredSequenceNumber); }
  227. IHqlExpression * getOnceSequenceNumber() { return createConstant(signedType->castFrom(true, (__int64)ResultSequenceOnce)); }
  228. //Does the record (or a base record) contain an ifblock? This could be tracking using a flag if it started being called a lot.
  229. bool recordContainsIfBlock(IHqlExpression * record)
  230. {
  231. ForEachChild(i, record)
  232. {
  233. IHqlExpression * cur = record->queryChild(i);
  234. switch (cur->getOperator())
  235. {
  236. case no_ifblock:
  237. return true;
  238. case no_record:
  239. if (recordContainsIfBlock(cur))
  240. return true;
  241. break;
  242. }
  243. }
  244. return false;
  245. }
  246. //---------------------------------------------------------------------------
  247. bool containsAggregate(IHqlExpression * expr)
  248. {
  249. return expr->isGroupAggregateFunction();
  250. }
  251. bool containsComplexAggregate(IHqlExpression * expr)
  252. {
  253. unsigned childIndex = (unsigned)-1;
  254. switch (expr->getOperator())
  255. {
  256. case no_record:
  257. childIndex = 0;
  258. break;
  259. case no_newtransform:
  260. case no_transform:
  261. childIndex = 1;
  262. break;
  263. default:
  264. UNIMPLEMENTED;
  265. }
  266. unsigned num = expr->numChildren();
  267. unsigned idx;
  268. for (idx = 0; idx < num; idx++)
  269. {
  270. IHqlExpression * cur = expr->queryChild(idx);
  271. if (cur->isAttribute())
  272. continue;
  273. IHqlExpression * value = cur->queryChild(childIndex);
  274. if (value && value->isGroupAggregateFunction())
  275. {
  276. //HOLe can cast aggregate values.
  277. node_operator op = value->getOperator();
  278. if ((op == no_cast) || (op == no_implicitcast))
  279. value = value->queryChild(0);
  280. switch (value->getOperator())
  281. {
  282. case NO_AGGREGATEGROUP:
  283. break;
  284. default:
  285. return true;
  286. }
  287. }
  288. }
  289. return false;
  290. }
  291. static node_operator containsSingleAggregate(IHqlExpression * expr)
  292. {
  293. switch (expr->getOperator())
  294. {
  295. case no_assign:
  296. {
  297. node_operator rhsOp = expr->queryChild(1)->getOperator();
  298. switch (rhsOp)
  299. {
  300. case NO_AGGREGATEGROUP:
  301. return rhsOp;
  302. }
  303. return no_none;
  304. }
  305. case no_assignall:
  306. case no_transform:
  307. case no_newtransform:
  308. {
  309. node_operator ret = no_none;
  310. ForEachChild(i, expr)
  311. {
  312. node_operator childOp = containsSingleAggregate(expr->queryChild(i));
  313. if (childOp != no_none)
  314. {
  315. if (ret == no_none)
  316. ret = childOp;
  317. else
  318. return no_all;
  319. }
  320. }
  321. return ret;
  322. }
  323. }
  324. return no_none;
  325. }
  326. node_operator queryTransformSingleAggregate(IHqlExpression * expr)
  327. {
  328. return containsSingleAggregate(expr);
  329. }
  330. static bool containsOnlyLeftTable(IHqlExpression * expr, bool ignoreSelfOrFilepos)
  331. {
  332. switch (expr->getOperator())
  333. {
  334. case no_self:
  335. return ignoreSelfOrFilepos;
  336. case no_left:
  337. return true;
  338. case no_selectnth:
  339. return containsOnlyLeftTable(expr->queryChild(0), ignoreSelfOrFilepos) && containsOnlyLeft(expr->queryChild(1), ignoreSelfOrFilepos);
  340. case no_select:
  341. return containsOnlyLeftTable(expr->queryChild(0), ignoreSelfOrFilepos);
  342. }
  343. return false;
  344. }
  345. bool containsOnlyLeft(IHqlExpression * expr, bool ignoreSelfOrFilepos)
  346. {
  347. switch (expr->getOperator())
  348. {
  349. case no_right:
  350. return false;
  351. case no_select:
  352. return containsOnlyLeftTable(expr, ignoreSelfOrFilepos);
  353. case no_field:
  354. case no_table:
  355. return false;
  356. case no_filepos:
  357. case no_file_logicalname:
  358. return ignoreSelfOrFilepos;
  359. default:
  360. {
  361. unsigned max = expr->numChildren();
  362. unsigned idx;
  363. for (idx = 0; idx < max; idx++)
  364. {
  365. if (!containsOnlyLeft(expr->queryChild(idx), ignoreSelfOrFilepos))
  366. return false;
  367. }
  368. return true;
  369. }
  370. }
  371. }
  372. IHqlExpression * queryPhysicalRootTable(IHqlExpression * expr)
  373. {
  374. for (;;)
  375. {
  376. switch (expr->getOperator())
  377. {
  378. case no_keyindex:
  379. case no_newkeyindex:
  380. case no_table:
  381. return expr;
  382. }
  383. switch (getNumChildTables(expr))
  384. {
  385. case 1:
  386. expr = expr->queryChild(0);
  387. break;
  388. default:
  389. return NULL;
  390. }
  391. }
  392. }
  393. IHqlExpression * queryTableFilename(IHqlExpression * expr)
  394. {
  395. IHqlExpression * table = queryPhysicalRootTable(expr);
  396. if (table)
  397. {
  398. switch (table->getOperator())
  399. {
  400. case no_keyindex:
  401. return table->queryChild(2);
  402. case no_newkeyindex:
  403. return table->queryChild(3);
  404. case no_table:
  405. return table->queryChild(0);
  406. }
  407. }
  408. return NULL;
  409. }
  410. IHqlExpression * createRawIndex(IHqlExpression * index)
  411. {
  412. IHqlExpression * indexRecord = index->queryRecord();
  413. HqlExprArray fields;
  414. unwindChildren(fields, indexRecord);
  415. fields.pop();
  416. return createDataset(no_null, createRecord(fields), NULL);
  417. }
  418. //---------------------------------------------------------------------------------------------
  419. IHqlExpression * queryStripCasts(IHqlExpression * expr)
  420. {
  421. while (isCast(expr))
  422. expr = expr->queryChild(0);
  423. return expr;
  424. }
  425. //---------------------------------------------------------------------------------------------
  426. IHqlExpression * createRecord(IHqlExpression * field)
  427. {
  428. HqlExprArray fields;
  429. fields.append(*LINK(field));
  430. return createRecord(fields);
  431. }
  432. IHqlExpression * queryLastField(IHqlExpression * record)
  433. {
  434. unsigned max = record->numChildren();
  435. while (max--)
  436. {
  437. IHqlExpression * cur = record->queryChild(max);
  438. switch (cur->getOperator())
  439. {
  440. case no_field:
  441. return cur;
  442. case no_ifblock:
  443. return queryLastField(cur->queryChild(1));
  444. case no_record:
  445. return queryLastField(cur);
  446. }
  447. }
  448. return NULL;
  449. }
  450. IHqlExpression * queryFirstField(IHqlExpression * record)
  451. {
  452. unsigned idx = 0;
  453. return queryNextRecordField(record, idx);
  454. }
  455. bool recordContainsBlobs(IHqlExpression * record)
  456. {
  457. ForEachChild(i, record)
  458. {
  459. IHqlExpression * cur = record->queryChild(i);
  460. switch (cur->getOperator())
  461. {
  462. case no_field:
  463. {
  464. if (cur->hasAttribute(blobAtom))
  465. return true;
  466. IHqlExpression * childRecord = cur->queryRecord();
  467. if (childRecord && recordContainsBlobs(childRecord))
  468. return true;
  469. break;
  470. }
  471. case no_ifblock:
  472. if (recordContainsBlobs(cur->queryChild(1)))
  473. return true;
  474. break;
  475. case no_record:
  476. if (recordContainsBlobs(cur))
  477. return true;
  478. break;
  479. case no_attr:
  480. case no_attr_expr:
  481. case no_attr_link:
  482. break;
  483. default:
  484. UNIMPLEMENTED;
  485. }
  486. }
  487. return false;
  488. }
  489. IHqlExpression * queryVirtualFileposField(IHqlExpression * record)
  490. {
  491. ForEachChild(idx, record)
  492. {
  493. IHqlExpression * cur = record->queryChild(idx);
  494. IHqlExpression * attr = cur->queryAttribute(virtualAtom);
  495. if (attr)
  496. return cur;
  497. }
  498. return NULL;
  499. }
  500. IHqlExpression * queryLastNonAttribute(IHqlExpression * expr)
  501. {
  502. unsigned max = expr->numChildren();
  503. while (max--)
  504. {
  505. IHqlExpression * cur = expr->queryChild(max);
  506. if (!cur->isAttribute())
  507. return cur;
  508. }
  509. return NULL;
  510. }
  511. extern HQL_API unsigned numNonAttributes(IHqlExpression * expr)
  512. {
  513. unsigned max = expr->numChildren();
  514. while (max--)
  515. {
  516. IHqlExpression * cur = expr->queryChild(max);
  517. if (!cur->isAttribute())
  518. return max+1;
  519. }
  520. return 0;
  521. }
  522. void expandRecord(HqlExprArray & selects, IHqlExpression * selector, IHqlExpression * expr)
  523. {
  524. switch (expr->getOperator())
  525. {
  526. case no_record:
  527. {
  528. ForEachChild(i, expr)
  529. expandRecord(selects, selector, expr->queryChild(i));
  530. break;
  531. }
  532. case no_field:
  533. {
  534. OwnedHqlExpr subSelector = createSelectExpr(LINK(selector), LINK(expr));
  535. if (expr->queryRecord() && !expr->isDataset() && !expr->isDictionary())
  536. expandRecord(selects, subSelector, expr->queryRecord());
  537. else
  538. {
  539. if (selects.find(*subSelector) == NotFound)
  540. selects.append(*subSelector.getClear());
  541. }
  542. break;
  543. }
  544. case no_ifblock:
  545. expandRecord(selects, selector, expr->queryChild(1));
  546. break;
  547. }
  548. }
  549. //---------------------------------------------------------------------------------------------------------------------
  550. static IHqlExpression * queryOnlyTableChild(IHqlExpression * expr)
  551. {
  552. switch (expr->getOperator())
  553. {
  554. case no_select: case no_evaluate:
  555. return NULL;
  556. }
  557. IHqlExpression * ret = NULL;
  558. ForEachChild(i, expr)
  559. {
  560. IHqlExpression * cur = expr->queryChild(i);
  561. if (containsActiveDataset(cur))
  562. {
  563. if (ret)
  564. return NULL;
  565. ret = cur;
  566. }
  567. }
  568. return ret;
  569. }
  570. //The common bit between upper and lower has to be a function of right, and therefore not table invariant.
  571. //Find it by unwinding all candidates from the lower, and then match from the upper.
  572. static IHqlExpression * findCommonExpression(IHqlExpression * lower, IHqlExpression * upper)
  573. {
  574. HqlExprCopyArray candidates;
  575. do
  576. {
  577. candidates.append(*lower);
  578. lower = queryOnlyTableChild(lower);
  579. } while (lower);
  580. do
  581. {
  582. if (candidates.find(*upper) != NotFound)
  583. return upper;
  584. upper = queryOnlyTableChild(upper);
  585. } while (upper);
  586. return NULL;
  587. }
  588. //---------------------------------------------------------------------------------------------------------------------
  589. bool isFileOutput(IHqlExpression * expr)
  590. {
  591. return (expr->getOperator() == no_output) && (queryRealChild(expr, 1) != NULL);
  592. }
  593. bool isWorkunitOutput(IHqlExpression * expr)
  594. {
  595. return (expr->getOperator() == no_output) && (queryRealChild(expr, 1) == NULL);
  596. }
  597. bool isCommonSubstringRange(IHqlExpression * expr)
  598. {
  599. if (expr->getOperator() != no_substring)
  600. return false;
  601. IHqlExpression * range = expr->queryChild(1);
  602. return (range->getOperator() == no_rangecommon);
  603. }
  604. IHqlExpression * removeCommonSubstringRange(IHqlExpression * expr)
  605. {
  606. if (expr->getOperator() != no_substring)
  607. return LINK(expr);
  608. IHqlExpression * range = expr->queryChild(1);
  609. if (range->getOperator() != no_rangecommon)
  610. return LINK(expr);
  611. IHqlExpression * value = expr->queryChild(0);
  612. IHqlExpression * from = range->queryChild(0);
  613. if (matchesConstantValue(from, 1))
  614. return LINK(value);
  615. OwnedHqlExpr newRange = createValue(no_rangefrom, makeNullType(), LINK(from));
  616. return replaceChild(expr, 1, newRange);
  617. }
  618. void AtmostLimit::extractAtmostArgs(IHqlExpression * atmost)
  619. {
  620. limit.setown(getSizetConstant(0));
  621. if (atmost)
  622. {
  623. unsigned cur = 0;
  624. IHqlExpression * arg = atmost->queryChild(0);
  625. if (arg && arg->isBoolean())
  626. {
  627. required.set(arg);
  628. arg = atmost->queryChild(++cur);
  629. }
  630. if (arg && arg->queryType()->getTypeCode() == type_sortlist)
  631. {
  632. unwindChildren(optional, arg);
  633. arg = atmost->queryChild(++cur);
  634. }
  635. if (arg)
  636. limit.set(arg);
  637. }
  638. }
  639. static bool matchesAtmostCondition(IHqlExpression * cond, HqlExprArray & atConds, unsigned & numMatched)
  640. {
  641. if (atConds.find(*cond) != NotFound)
  642. {
  643. numMatched++;
  644. return true;
  645. }
  646. if (cond->getOperator() != no_assertkeyed)
  647. return false;
  648. unsigned savedMatched = numMatched;
  649. HqlExprArray conds;
  650. cond->queryChild(0)->unwindList(conds, no_and);
  651. ForEachItemIn(i, conds)
  652. {
  653. if (!matchesAtmostCondition(&conds.item(i), atConds, numMatched))
  654. {
  655. numMatched = savedMatched;
  656. return false;
  657. }
  658. }
  659. return true;
  660. }
  661. static bool doSplitFuzzyCondition(IHqlExpression * condition, IHqlExpression * atmostCond, SharedHqlExpr & fuzzy, SharedHqlExpr & hard)
  662. {
  663. if (atmostCond)
  664. {
  665. //If join condition has evaluated to a constant then allow any atmost condition.
  666. if (!condition->isConstant())
  667. {
  668. HqlExprArray conds, atConds;
  669. condition->unwindList(conds, no_and);
  670. atmostCond->unwindList(atConds, no_and);
  671. unsigned numAtmostMatched = 0;
  672. ForEachItemIn(i, conds)
  673. {
  674. IHqlExpression & cur = conds.item(i);
  675. if (matchesAtmostCondition(&cur, atConds, numAtmostMatched))
  676. extendConditionOwn(hard, no_and, LINK(&cur));
  677. else
  678. extendConditionOwn(fuzzy, no_and, LINK(&cur));
  679. }
  680. if (atConds.ordinality() != numAtmostMatched)
  681. {
  682. hard.clear();
  683. fuzzy.clear();
  684. return false;
  685. }
  686. }
  687. }
  688. else
  689. hard.set(condition);
  690. return true;
  691. }
  692. void splitFuzzyCondition(IHqlExpression * condition, IHqlExpression * atmostCond, SharedHqlExpr & fuzzy, SharedHqlExpr & hard)
  693. {
  694. if (!doSplitFuzzyCondition(condition, atmostCond, fuzzy, hard))
  695. {
  696. //Ugly, but sometimes the condition only matches after it has been constant folded.
  697. //And this function can be called from the normalizer before the expression tree is folded.
  698. OwnedHqlExpr foldedCond = foldHqlExpression(condition);
  699. OwnedHqlExpr foldedAtmost = foldHqlExpression(atmostCond);
  700. if (!doSplitFuzzyCondition(foldedCond, foldedAtmost, fuzzy, hard))
  701. {
  702. StringBuffer s;
  703. getExprECL(atmostCond, s);
  704. throwError1(HQLERR_AtmostFailMatchCondition, s.str());
  705. }
  706. }
  707. }
  708. //---------------------------------------------------------------------------------------------------------------------
  709. class JoinOrderSpotter
  710. {
  711. public:
  712. JoinOrderSpotter(IHqlExpression * _leftDs, IHqlExpression * _rightDs, IHqlExpression * seq, JoinSortInfo & _joinOrder) : joinOrder(_joinOrder)
  713. {
  714. if (_leftDs)
  715. left.setown(createSelector(no_left, _leftDs, seq));
  716. if (_rightDs)
  717. right.setown(createSelector(no_right, _rightDs, seq));
  718. }
  719. IHqlExpression * doFindJoinSortOrders(IHqlExpression * condition, bool allowSlidingMatch, HqlExprCopyArray & matched);
  720. bool doProcessOptional(IHqlExpression * condition);
  721. void findImplicitBetween(IHqlExpression * condition, HqlExprArray & slidingMatches, HqlExprCopyArray & matched, HqlExprCopyArray & pending);
  722. protected:
  723. IHqlExpression * traverseStripSelect(IHqlExpression * expr, node_operator & kind);
  724. IHqlExpression * cachedTraverseStripSelect(IHqlExpression * expr, node_operator & kind);
  725. IHqlExpression * doTraverseStripSelect(IHqlExpression * expr, node_operator & kind);
  726. void unwindSelectorRecord(HqlExprArray & target, IHqlExpression * selector, IHqlExpression * record);
  727. protected:
  728. OwnedHqlExpr left;
  729. OwnedHqlExpr right;
  730. JoinSortInfo & joinOrder;
  731. };
  732. IHqlExpression * JoinOrderSpotter::traverseStripSelect(IHqlExpression * expr, node_operator & kind)
  733. {
  734. TransformMutexBlock block;
  735. return cachedTraverseStripSelect(expr, kind);
  736. }
  737. IHqlExpression * JoinOrderSpotter::cachedTraverseStripSelect(IHqlExpression * expr, node_operator & kind)
  738. {
  739. IHqlExpression * matched = static_cast<IHqlExpression *>(expr->queryTransformExtra());
  740. if (matched)
  741. return LINK(matched);
  742. IHqlExpression * ret = doTraverseStripSelect(expr, kind);
  743. expr->setTransformExtra(ret);
  744. return ret;
  745. }
  746. IHqlExpression * JoinOrderSpotter::doTraverseStripSelect(IHqlExpression * expr, node_operator & kind)
  747. {
  748. if (expr->getOperator()==no_select)
  749. {
  750. IHqlExpression * table = expr->queryChild(0);
  751. node_operator curKind = table->getOperator();
  752. if (curKind == no_select || expr->hasAttribute(newAtom))
  753. {
  754. //I'm not sure this is a good idea for elements with newAtom - can end up with weird join conditions
  755. HqlExprArray args;
  756. args.append(*cachedTraverseStripSelect(table, kind));
  757. unwindChildren(args, expr, 1);
  758. return cloneOrLink(expr, args);
  759. }
  760. else if ((table == left) || (table == right))
  761. {
  762. if ((kind == no_none) || (kind == curKind))
  763. {
  764. kind = curKind;
  765. //return the unselected id.
  766. return createSelectExpr(getActiveTableSelector(), LINK(expr->queryChild(1)));
  767. }
  768. kind = no_fail;
  769. }
  770. //Cope with case when called from the parser and the expression tree isn't normalized.
  771. else if (!left && !right && ((curKind == no_left) || (curKind == no_right)))
  772. {
  773. kind = curKind;
  774. //return the unselected id.
  775. return createSelectExpr(getActiveTableSelector(), LINK(expr->queryChild(1)));
  776. }
  777. }
  778. else
  779. {
  780. unsigned max = expr->numChildren();
  781. if (max != 0)
  782. {
  783. HqlExprArray args;
  784. args.ensure(max);
  785. unsigned idx;
  786. bool same = true;
  787. for (idx = 0; idx<max;idx++)
  788. {
  789. IHqlExpression * cur = expr->queryChild(idx);
  790. IHqlExpression * stripped = cachedTraverseStripSelect(cur, kind);
  791. args.append(*stripped);
  792. if (cur != stripped)
  793. same = false;
  794. }
  795. if (!same)
  796. return expr->clone(args);
  797. }
  798. }
  799. return LINK(expr);
  800. }
  801. void JoinOrderSpotter::unwindSelectorRecord(HqlExprArray & target, IHqlExpression * selector, IHqlExpression * record)
  802. {
  803. ForEachChild(i, record)
  804. {
  805. IHqlExpression * cur = record->queryChild(i);
  806. switch (cur->getOperator())
  807. {
  808. case no_record:
  809. unwindSelectorRecord(target, selector, cur);
  810. break;
  811. case no_ifblock:
  812. unwindSelectorRecord(target, selector, cur->queryChild(1));
  813. break;
  814. case no_field:
  815. {
  816. OwnedHqlExpr selected = createSelectExpr(LINK(selector), LINK(cur));
  817. target.append(*selected.getClear());
  818. //MORE: Could expand nested rows
  819. break;
  820. }
  821. }
  822. }
  823. }
  824. IHqlExpression * JoinOrderSpotter::doFindJoinSortOrders(IHqlExpression * condition, bool allowSlidingMatch, HqlExprCopyArray & matched)
  825. {
  826. IHqlExpression *l = condition->queryChild(0);
  827. IHqlExpression *r = condition->queryChild(1);
  828. switch(condition->getOperator())
  829. {
  830. case no_and:
  831. {
  832. IHqlExpression *lmatch = doFindJoinSortOrders(l, allowSlidingMatch, matched);
  833. IHqlExpression *rmatch = doFindJoinSortOrders(r, allowSlidingMatch, matched);
  834. if (lmatch)
  835. {
  836. if (rmatch)
  837. return createValue(no_and, lmatch, rmatch);
  838. else
  839. return lmatch;
  840. }
  841. else
  842. return rmatch;
  843. }
  844. case no_constant:
  845. //remove silly "and true" conditions
  846. if (condition->queryValue()->getBoolValue())
  847. return NULL;
  848. return LINK(condition);
  849. case no_eq:
  850. {
  851. node_operator leftSelectKind = no_none;
  852. node_operator rightSelectKind = no_none;
  853. OwnedHqlExpr leftStrip = traverseStripSelect(l, leftSelectKind);
  854. OwnedHqlExpr rightStrip = traverseStripSelect(r, rightSelectKind);
  855. if ((leftSelectKind == no_left) && (rightSelectKind == no_right))
  856. {
  857. joinOrder.leftReq.append(*leftStrip.getClear());
  858. joinOrder.rightReq.append(*rightStrip.getClear());
  859. return NULL;
  860. }
  861. if ((leftSelectKind == no_right) && (rightSelectKind == no_left))
  862. {
  863. joinOrder.leftReq.append(*rightStrip.getClear());
  864. joinOrder.rightReq.append(*leftStrip.getClear());
  865. return NULL;
  866. }
  867. if (((l == left) && (r == right)) || ((l == right) && (r == left)))
  868. {
  869. unwindSelectorRecord(joinOrder.leftReq, queryActiveTableSelector(), left->queryRecord());
  870. unwindSelectorRecord(joinOrder.rightReq, queryActiveTableSelector(), right->queryRecord());
  871. return NULL;
  872. }
  873. }
  874. return LINK(condition);
  875. case no_between:
  876. if (allowSlidingMatch)
  877. {
  878. node_operator leftSelectKind = no_none;
  879. node_operator rightSelectKind = no_none;
  880. OwnedHqlExpr leftStrip = traverseStripSelect(l, leftSelectKind);
  881. OwnedHqlExpr lowerStrip = traverseStripSelect(r, rightSelectKind);
  882. OwnedHqlExpr upperStrip = traverseStripSelect(condition->queryChild(2), rightSelectKind);
  883. if ((leftSelectKind == no_left) && (rightSelectKind == no_right))
  884. {
  885. //Find the expression of the rhs that is common to lower and upper
  886. IHqlExpression * common = findCommonExpression(lowerStrip,upperStrip);
  887. if (common)
  888. {
  889. joinOrder.slidingMatches.append(*createValue(no_between, makeBoolType(), LINK(leftStrip), LINK(lowerStrip), LINK(upperStrip), createExprAttribute(commonAtom, LINK(common))));
  890. return NULL;
  891. }
  892. }
  893. }
  894. return LINK(condition);
  895. case no_le:
  896. case no_ge:
  897. if (matched.find(*condition) != NotFound)
  898. return NULL;
  899. return LINK(condition);
  900. case no_assertkeyed:
  901. {
  902. OwnedHqlExpr ret = doFindJoinSortOrders(l, allowSlidingMatch, matched);
  903. if (ret)
  904. return createValue(no_assertkeyed, condition->getType(), ret.getClear());
  905. return NULL;
  906. }
  907. case no_assertwild:
  908. return NULL;
  909. default:
  910. return LINK(condition);
  911. }
  912. }
  913. bool JoinOrderSpotter::doProcessOptional(IHqlExpression * condition)
  914. {
  915. switch(condition->getOperator())
  916. {
  917. //MORE We could support no_and by adding a list to both sides, but I can't see it being worth the effort.
  918. case no_constant:
  919. //remove silly "and true" conditions
  920. if (condition->queryValue()->getBoolValue())
  921. return true;
  922. return false;
  923. case no_eq:
  924. {
  925. IHqlExpression *l = condition->queryChild(0);
  926. IHqlExpression *r = condition->queryChild(1);
  927. node_operator leftSelectKind = no_none;
  928. node_operator rightSelectKind = no_none;
  929. OwnedHqlExpr leftStrip = traverseStripSelect(l, leftSelectKind);
  930. OwnedHqlExpr rightStrip = traverseStripSelect(r, rightSelectKind);
  931. if ((leftSelectKind == no_left) && (rightSelectKind == no_right))
  932. {
  933. joinOrder.leftOpt.append(*leftStrip.getClear());
  934. joinOrder.rightOpt.append(*rightStrip.getClear());
  935. return true;
  936. }
  937. if ((leftSelectKind == no_right) && (rightSelectKind == no_left))
  938. {
  939. joinOrder.leftOpt.append(*rightStrip.getClear());
  940. joinOrder.rightOpt.append(*leftStrip.getClear());
  941. return true;
  942. }
  943. if (((l == left) && (r == right)) || ((l == right) && (r == left)))
  944. {
  945. unwindSelectorRecord(joinOrder.leftOpt, queryActiveTableSelector(), left->queryRecord());
  946. unwindSelectorRecord(joinOrder.rightOpt, queryActiveTableSelector(), right->queryRecord());
  947. return true;
  948. }
  949. }
  950. return false;
  951. default:
  952. return false;
  953. }
  954. }
  955. void JoinOrderSpotter::findImplicitBetween(IHqlExpression * condition, HqlExprArray & slidingMatches, HqlExprCopyArray & matched, HqlExprCopyArray & pending)
  956. {
  957. IHqlExpression *l = condition->queryChild(0);
  958. IHqlExpression *r = condition->queryChild(1);
  959. node_operator op = condition->getOperator();
  960. switch (op)
  961. {
  962. case no_and:
  963. {
  964. findImplicitBetween(l, slidingMatches, matched, pending);
  965. findImplicitBetween(r, slidingMatches, matched, pending);
  966. break;
  967. }
  968. case no_ge:
  969. case no_le:
  970. {
  971. node_operator search = (op == no_ge) ? no_le : no_ge;
  972. ForEachItemIn(idx, pending)
  973. {
  974. IHqlExpression & cur = pending.item(idx);
  975. if ((cur.getOperator() == search) && (cur.queryChild(0) == condition->queryChild(0)))
  976. {
  977. node_operator leftSelectKind = no_none;
  978. node_operator rightSelectKind = no_none;
  979. IHqlExpression * lower = (op == no_ge) ? condition->queryChild(1) : cur.queryChild(1);
  980. IHqlExpression * upper = (op == no_ge) ? cur.queryChild(1) : condition->queryChild(1);
  981. OwnedHqlExpr leftStrip = traverseStripSelect(condition->queryChild(0), leftSelectKind);
  982. OwnedHqlExpr lowerStrip = traverseStripSelect(lower, rightSelectKind);
  983. OwnedHqlExpr upperStrip = traverseStripSelect(upper, rightSelectKind);
  984. if ((leftSelectKind == no_left) && (rightSelectKind == no_right))
  985. {
  986. //Find the expression of the rhs that is common to lower and upper
  987. IHqlExpression * common = findCommonExpression(lowerStrip,upperStrip);
  988. if (common)
  989. {
  990. slidingMatches.append(*createValue(no_between, makeBoolType(), LINK(leftStrip), LINK(lowerStrip), LINK(upperStrip), createExprAttribute(commonAtom, LINK(common))));
  991. matched.append(*condition);
  992. matched.append(cur);
  993. pending.zap(cur);
  994. return;
  995. }
  996. }
  997. }
  998. }
  999. pending.append(*condition);
  1000. break;
  1001. }
  1002. }
  1003. }
  1004. JoinSortInfo::JoinSortInfo(IHqlExpression * expr)
  1005. : lhs(expr->queryChild(0)), rhs(queryJoinRhs(expr)), cond(expr->queryChild(2)), seq(querySelSeq(expr)), atmostAttr(expr->queryAttribute(atmostAtom))
  1006. {
  1007. init();
  1008. }
  1009. JoinSortInfo::JoinSortInfo(IHqlExpression * _condition, IHqlExpression * _leftDs, IHqlExpression * _rightDs, IHqlExpression * _seq, IHqlExpression * _atmost)
  1010. : lhs(_leftDs), rhs(_rightDs), cond(_condition), seq(_seq), atmostAttr(_atmost)
  1011. {
  1012. init();
  1013. }
  1014. void JoinSortInfo::init()
  1015. {
  1016. conditionAllEqualities = false;
  1017. hasRightNonEquality = false;
  1018. if (lhs)
  1019. left.setown(createSelector(no_left, lhs, seq));
  1020. if (rhs)
  1021. right.setown(createSelector(no_right, rhs, seq));
  1022. }
  1023. void JoinSortInfo::doFindJoinSortOrders(IHqlExpression * condition, bool allowSlidingMatch)
  1024. {
  1025. JoinOrderSpotter spotter(lhs, rhs, seq, *this);
  1026. HqlExprCopyArray matched;
  1027. if (allowSlidingMatch)
  1028. {
  1029. //First spot any implicit betweens using x >= a and x <= b. Do it first so that the second pass doesn't
  1030. //reorder the join condition (this still reorders it slightly by moving the implicit betweens before explicit)
  1031. HqlExprCopyArray pending;
  1032. spotter.findImplicitBetween(condition, slidingMatches, matched, pending);
  1033. }
  1034. extraMatch.setown(spotter.doFindJoinSortOrders(condition, allowSlidingMatch, matched));
  1035. conditionAllEqualities = (extraMatch == NULL);
  1036. if (extraMatch)
  1037. {
  1038. if (extraMatch->usesSelector(right))
  1039. hasRightNonEquality = true;
  1040. }
  1041. //Support for legacy syntax where x[n..*] was present in join and atmost condition
  1042. //Ensure they are tagged as optional join fields.
  1043. ForEachItemInRev(i, leftReq)
  1044. {
  1045. IHqlExpression & left = leftReq.item(i);
  1046. IHqlExpression & right = rightReq.item(i);
  1047. if (isCommonSubstringRange(&left))
  1048. {
  1049. if (isCommonSubstringRange(&right))
  1050. {
  1051. if (leftOpt.ordinality())
  1052. throwError(HQLERR_AtmostLegacyMismatch);
  1053. leftOpt.append(OLINK(left));
  1054. leftReq.remove(i);
  1055. rightOpt.append(OLINK(right));
  1056. rightReq.remove(i);
  1057. }
  1058. else
  1059. throwError(HQLERR_AtmostSubstringNotMatch);
  1060. }
  1061. else
  1062. {
  1063. if (isCommonSubstringRange(&right))
  1064. throwError(HQLERR_AtmostSubstringNotMatch);
  1065. }
  1066. }
  1067. if (!hasOptionalEqualities() && allowSlidingMatch)
  1068. {
  1069. ForEachItemIn(i, slidingMatches)
  1070. {
  1071. IHqlExpression & cur = slidingMatches.item(i);
  1072. leftReq.append(*LINK(cur.queryChild(0)));
  1073. rightReq.append(*LINK(cur.queryChild(3)->queryChild(0)));
  1074. }
  1075. }
  1076. }
  1077. void JoinSortInfo::findJoinSortOrders(bool allowSlidingMatch)
  1078. {
  1079. atmost.extractAtmostArgs(atmostAttr);
  1080. if (atmost.optional.ordinality())
  1081. {
  1082. JoinOrderSpotter spotter(lhs, rhs, seq, *this);
  1083. ForEachItemIn(i, atmost.optional)
  1084. {
  1085. if (!spotter.doProcessOptional(&atmost.optional.item(i)))
  1086. throwError(HQLERR_AtmostCannotImplementOpt);
  1087. }
  1088. }
  1089. OwnedHqlExpr fuzzy, hard;
  1090. splitFuzzyCondition(cond, atmost.required, fuzzy, hard);
  1091. if (hard)
  1092. doFindJoinSortOrders(hard, allowSlidingMatch);
  1093. extraMatch.setown(extendConditionOwn(no_and, extraMatch.getClear(), fuzzy.getClear()));
  1094. }
  1095. IHqlExpression * JoinSortInfo::getContiguousJoinCondition(unsigned numRhsFields)
  1096. {
  1097. //Ensure that numRhsFields from RIGHT are joined, and if so return the join condition
  1098. IHqlExpression * rightRecord = rhs->queryRecord();
  1099. HqlExprCopyArray leftMatches, rightMatches;
  1100. RecordSelectIterator iter(rightRecord, queryActiveTableSelector());
  1101. unsigned numMatched = 0;
  1102. ForEach(iter)
  1103. {
  1104. unsigned match = rightReq.find(*iter.query());
  1105. if (match == NotFound)
  1106. return NULL;
  1107. leftMatches.append(leftReq.item(match));
  1108. rightMatches.append(rightReq.item(match));
  1109. if (++numMatched == numRhsFields)
  1110. {
  1111. HqlExprAttr cond;
  1112. ForEachItemIn(i, leftMatches)
  1113. {
  1114. OwnedHqlExpr eq = createBoolExpr(no_eq,
  1115. replaceSelector(&leftMatches.item(i), queryActiveTableSelector(), left),
  1116. replaceSelector(&rightMatches.item(i), queryActiveTableSelector(), right));
  1117. extendConditionOwn(cond, no_and, eq.getClear());
  1118. }
  1119. return cond.getClear();
  1120. }
  1121. }
  1122. return NULL;
  1123. }
  1124. static void appendOptElements(HqlExprArray & target, const HqlExprArray & src)
  1125. {
  1126. ForEachItemIn(i, src)
  1127. {
  1128. IHqlExpression & cur = src.item(i);
  1129. //Strip the substring syntax when adding the optional compares to the sort list
  1130. target.append(*removeCommonSubstringRange(&cur));
  1131. }
  1132. }
  1133. void JoinSortInfo::initSorts()
  1134. {
  1135. if (!leftSorts.ordinality())
  1136. {
  1137. appendArray(leftSorts, leftReq);
  1138. appendOptElements(leftSorts, leftOpt);
  1139. appendArray(rightSorts, rightReq);
  1140. appendOptElements(rightSorts, rightOpt);
  1141. }
  1142. }
  1143. static bool isSameFieldSelected(IHqlExpression * leftExpr, IHqlExpression * rightExpr, IHqlExpression * left, IHqlExpression * right)
  1144. {
  1145. if ((leftExpr->getOperator() != no_select) || (rightExpr->getOperator() != no_select))
  1146. return false;
  1147. if (leftExpr->queryChild(1) != rightExpr->queryChild(1))
  1148. return false;
  1149. IHqlExpression * leftSelector = leftExpr->queryChild(0);
  1150. IHqlExpression * rightSelector = rightExpr->queryChild(0);
  1151. if (leftSelector == left || rightSelector == right)
  1152. return (leftSelector == left) && (rightSelector == right);
  1153. if (leftSelector == right || rightSelector == left)
  1154. return (leftSelector == right) && (rightSelector == left);
  1155. return isSameFieldSelected(leftSelector, rightSelector, left, right);
  1156. }
  1157. static bool hasNeverMatchCompare(IHqlExpression * expr, IHqlExpression * left, IHqlExpression * right)
  1158. {
  1159. switch (expr->getOperator())
  1160. {
  1161. case no_and:
  1162. return hasNeverMatchCompare(expr->queryChild(0), left, right) ||
  1163. hasNeverMatchCompare(expr->queryChild(1), left, right);
  1164. case no_ne:
  1165. case no_gt:
  1166. case no_lt:
  1167. return isSameFieldSelected(expr->queryChild(0), expr->queryChild(1), left, right);
  1168. default:
  1169. return false;
  1170. }
  1171. }
  1172. bool JoinSortInfo::neverMatchSelf() const
  1173. {
  1174. if (!extraMatch)
  1175. return false;
  1176. if (!recordTypesMatch(lhs, rhs))
  1177. return false;
  1178. return hasNeverMatchCompare(extraMatch, left, right);
  1179. }
  1180. extern HQL_API bool joinHasRightOnlyHardMatch(IHqlExpression * expr, bool allowSlidingMatch)
  1181. {
  1182. JoinSortInfo joinInfo(expr);
  1183. joinInfo.findJoinSortOrders(false);
  1184. return joinInfo.hasHardRightNonEquality();
  1185. }
  1186. IHqlExpression * createImpureOwn(IHqlExpression * expr)
  1187. {
  1188. return createValue(no_impure, expr->getType(), expr);
  1189. }
  1190. IHqlExpression * getNormalizedFilename(IHqlExpression * filename)
  1191. {
  1192. NullErrorReceiver errorProcessor;
  1193. OwnedHqlExpr folded = foldHqlExpression(errorProcessor, filename, NULL, HFOloseannotations);
  1194. return normalizeFilenameExpr(folded);
  1195. }
  1196. bool canBeSlidingJoin(IHqlExpression * expr)
  1197. {
  1198. if (expr->hasAttribute(hashAtom) || expr->hasAttribute(lookupAtom) || expr->hasAttribute(smartAtom)|| expr->hasAttribute(allAtom))
  1199. return false;
  1200. if (expr->hasAttribute(rightouterAtom) || expr->hasAttribute(fullouterAtom) ||
  1201. expr->hasAttribute(leftonlyAtom) || expr->hasAttribute(rightonlyAtom) || expr->hasAttribute(fullonlyAtom))
  1202. return false;
  1203. if (expr->hasAttribute(atmostAtom))
  1204. return false;
  1205. return true;
  1206. }
  1207. //==============================================================================================================
  1208. extern HQL_API bool dedupMatchesWholeRecord(IHqlExpression * expr)
  1209. {
  1210. assertex(expr->getOperator() == no_dedup);
  1211. unsigned max = expr->numChildren();
  1212. unsigned idx;
  1213. for (idx = 1; idx < max; idx++)
  1214. {
  1215. IHqlExpression * cur = expr->queryChild(idx);
  1216. switch (cur->getOperator())
  1217. {
  1218. case no_attr:
  1219. case no_attr_expr:
  1220. case no_attr_link:
  1221. break;
  1222. default:
  1223. return false;
  1224. }
  1225. }
  1226. return true;
  1227. }
  1228. IHqlExpression * getEquality(IHqlExpression * equality, IHqlExpression * left, IHqlExpression * right, IHqlExpression * activeSelector)
  1229. {
  1230. IHqlExpression * lhs = equality->queryChild(0);
  1231. IHqlExpression * rhs = equality->queryChild(1);
  1232. if (containsSelector(lhs, left))
  1233. {
  1234. OwnedHqlExpr mappedLeft = replaceSelector(lhs, left, activeSelector);
  1235. OwnedHqlExpr mappedRight = replaceSelector(rhs, right, activeSelector);
  1236. if (mappedLeft == mappedRight)
  1237. return mappedLeft.getClear();
  1238. }
  1239. else if (containsSelector(lhs, right))
  1240. {
  1241. OwnedHqlExpr mappedLeft = replaceSelector(lhs, right, activeSelector);
  1242. OwnedHqlExpr mappedRight = replaceSelector(rhs, left, activeSelector);
  1243. if (mappedLeft == mappedRight)
  1244. return mappedLeft.getClear();
  1245. }
  1246. return NULL;
  1247. }
  1248. DedupInfoExtractor::DedupInfoExtractor(IHqlExpression * expr)
  1249. {
  1250. IHqlExpression * dataset = expr->queryChild(0);
  1251. IHqlExpression * record = dataset->queryRecord();
  1252. IHqlExpression * selSeq = querySelSeq(expr);
  1253. OwnedHqlExpr left = createSelector(no_left, dataset, selSeq);
  1254. OwnedHqlExpr right = createSelector(no_right, dataset, selSeq);
  1255. compareAllRows = false;
  1256. compareAllFields = false;
  1257. isLocal = false;
  1258. keepLeft = true;
  1259. keepBest = false;
  1260. numToKeep.setown(createConstantOne());
  1261. unsigned max = expr->numChildren();
  1262. unsigned idx;
  1263. for (idx = 1; idx < max; idx++)
  1264. {
  1265. IHqlExpression * cur = expr->queryChild(idx);
  1266. switch (cur->getOperator())
  1267. {
  1268. case no_attr:
  1269. case no_attr_expr:
  1270. case no_attr_link:
  1271. {
  1272. IAtom * name = cur->queryName();
  1273. if (name == hashAtom)
  1274. compareAllRows = true;
  1275. else if (name == localAtom)
  1276. isLocal = true;
  1277. else if (name == allAtom)
  1278. compareAllRows = true;
  1279. else if (name == keepAtom)
  1280. numToKeep.set(cur->queryChild(0));
  1281. else if (name == leftAtom)
  1282. keepLeft = true;
  1283. else if (name == rightAtom)
  1284. keepLeft = false;
  1285. else if (name == bestAtom)
  1286. keepBest = true;
  1287. }
  1288. break;
  1289. case no_negate:
  1290. {
  1291. IHqlExpression * field = cur->queryChild(0);
  1292. if (field->getOperator() == no_select)
  1293. field = field->queryChild(1);
  1294. if (!equalities.zap(*field))
  1295. throwError(HQLERR_DedupFieldNotFound);
  1296. }
  1297. break;
  1298. case no_eq:
  1299. {
  1300. OwnedHqlExpr mapped = getEquality(cur, left, right, dataset->queryNormalizedSelector());
  1301. if (mapped)
  1302. {
  1303. equalities.append(*mapped.getClear());
  1304. break;
  1305. }
  1306. //fall through
  1307. }
  1308. default:
  1309. if (containsSelector(cur, left) || containsSelector(cur, right))
  1310. conds.append(*LINK(cur));
  1311. else
  1312. equalities.append(*LINK(cur));
  1313. break;
  1314. }
  1315. }
  1316. if ((equalities.ordinality() == 0) && (conds.ordinality() == 0))
  1317. {
  1318. unwindRecordAsSelects(equalities, record, dataset->queryNormalizedSelector());
  1319. compareAllFields = true;
  1320. }
  1321. #ifdef _DEBUG
  1322. //Check to ensure the function stays in sync with the code above
  1323. assertex(compareAllFields == dedupMatchesWholeRecord(expr));
  1324. #endif
  1325. }
  1326. DedupInfoExtractor::DedupKeyCompareKind DedupInfoExtractor::compareKeys(const DedupInfoExtractor & other)
  1327. {
  1328. //MORE: These could be coped with a bit better...
  1329. if ((conds.ordinality() != 0) || (other.conds.ordinality() != 0))
  1330. return DedupKeyIsDifferent;
  1331. const HqlExprArray & otherEqualities = other.equalities;
  1332. unsigned num1 = equalities.ordinality();
  1333. unsigned num2 = otherEqualities.ordinality();
  1334. unsigned numMissing = 0;
  1335. ForEachItemIn(i, equalities)
  1336. {
  1337. if (otherEqualities.find(equalities.item(i)) == NotFound)
  1338. numMissing++;
  1339. }
  1340. if (numMissing)
  1341. {
  1342. if (num1 == num2 + numMissing)
  1343. return DedupKeyIsSuperset;
  1344. return DedupKeyIsDifferent;
  1345. }
  1346. if (num1 == num2)
  1347. return DedupKeyIsSame;
  1348. return DedupKeyIsSubset;
  1349. }
  1350. DedupInfoExtractor::DedupCompareKind DedupInfoExtractor::compareWith(const DedupInfoExtractor & other)
  1351. {
  1352. if ((keepLeft != other.keepLeft) || !getConstantKeep() || !other.getConstantKeep())
  1353. return DedupIsDifferent;
  1354. if (isLocal != other.isLocal)
  1355. return DedupIsDifferent;
  1356. switch (compareKeys(other))
  1357. {
  1358. case DedupKeyIsSame:
  1359. if (compareAllRows == other.compareAllRows)
  1360. {
  1361. if (getConstantKeep() < other.getConstantKeep())
  1362. return DedupDoesAll;
  1363. else
  1364. return DedupDoesNothing;
  1365. }
  1366. else
  1367. {
  1368. //dedup(dedup(x,y),y,all) cannot be reduced to dedup(x,y,all) because it may include
  1369. //records that wouldn't have otherwise got through. dedup(dedup(x,y,all),y) can be though
  1370. if (other.compareAllRows)
  1371. {
  1372. if (getConstantKeep() >= other.getConstantKeep())
  1373. return DedupDoesNothing;
  1374. }
  1375. }
  1376. break;
  1377. case DedupKeyIsSubset:
  1378. //optimize dedup(dedup(x,y1,y2,keep(2)),y1,keep(2)) to dedup(x,y1,keep(2)) if keep is same
  1379. if (compareAllRows == other.compareAllRows && (getConstantKeep() == other.getConstantKeep()))
  1380. return DedupDoesAll;
  1381. //optimize dedup(dedup(x,y1,y2,keep(2),all),y1,keep(1)) to dedup(x,y1,keep(1))
  1382. if (compareAllRows && other.compareAllRows && (getConstantKeep() <= other.getConstantKeep()))
  1383. return DedupDoesAll;
  1384. break;
  1385. case DedupKeyIsSuperset:
  1386. if (compareAllRows == other.compareAllRows && (getConstantKeep() == other.getConstantKeep()))
  1387. return DedupDoesNothing;
  1388. if (compareAllRows && other.compareAllRows && (getConstantKeep() >= other.getConstantKeep()))
  1389. return DedupDoesNothing;
  1390. break;
  1391. }
  1392. return DedupIsDifferent;
  1393. }
  1394. IHqlExpression * replaceChild(IHqlExpression * expr, unsigned childIndex, IHqlExpression * newChild)
  1395. {
  1396. IHqlExpression * oldChild = expr->queryChild(childIndex);
  1397. if (oldChild == newChild)
  1398. return LINK(expr);
  1399. HqlExprArray args;
  1400. if (childIndex == 0)
  1401. {
  1402. args.append(*LINK(newChild));
  1403. unwindChildren(args, expr, 1);
  1404. }
  1405. else
  1406. {
  1407. unwindChildren(args, expr);
  1408. args.replace(*LINK(newChild), childIndex);
  1409. }
  1410. return expr->clone(args);
  1411. }
  1412. IHqlExpression * createIf(IHqlExpression * cond, IHqlExpression * left, IHqlExpression * right)
  1413. {
  1414. assertex(right);
  1415. if (left->isDataset() || right->isDataset())
  1416. return createDataset(no_if, cond, createComma(left, right));
  1417. if (left->isDictionary() || right->isDictionary())
  1418. return createDictionary(no_if, cond, createComma(left, right));
  1419. if (left->isDatarow() || right->isDatarow())
  1420. return createRow(no_if, cond, createComma(left, right));
  1421. ITypeInfo * leftType = left->queryType();
  1422. ITypeInfo * rightType = right->queryType();
  1423. Owned<ITypeInfo> type = ::getPromotedECLType(leftType, rightType);
  1424. if ((isStringType(type) || isUnicodeType(type)) && (leftType->getStringLen() != rightType->getStringLen()))
  1425. type.setown(getStretchedType(UNKNOWN_LENGTH, type));
  1426. return createValue(no_if, type.getClear(), cond, left, right);
  1427. }
  1428. extern HQL_API unsigned numRealChildren(IHqlExpression * expr)
  1429. {
  1430. unsigned max = expr->numChildren();
  1431. //Assumes all attributes occur at the end of the operand lists
  1432. while (max && expr->queryChild(max-1)->isAttribute())
  1433. max--;
  1434. return max;
  1435. }
  1436. //---------------------------------------------------------------------------
  1437. static IHqlExpression * getExpandSelectExprTest(IHqlExpression * expr)
  1438. {
  1439. assertex(expr->getOperator() == no_select);
  1440. IHqlExpression * ds = expr->queryChild(0);
  1441. IHqlExpression * field = expr->queryChild(1);
  1442. if (field->queryRecord() || !queryNewColumnProvider(ds))
  1443. return NULL;
  1444. TableProjectMapper mapper(ds);
  1445. return mapper.expandFields(expr, ds, ds->queryChild(0)->queryNormalizedSelector());
  1446. }
  1447. IHqlExpression * getExpandSelectExpr(IHqlExpression * expr)
  1448. {
  1449. assertex(expr->getOperator() == no_select);
  1450. IHqlExpression * ds = expr->queryChild(0);
  1451. IHqlExpression * field = expr->queryChild(1);
  1452. if (field->queryRecord())
  1453. return NULL;
  1454. IHqlExpression * mappingExpr = queryNewColumnProvider(ds);
  1455. if (mappingExpr)
  1456. {
  1457. IHqlExpression * ret = NULL;
  1458. switch (mappingExpr->getOperator())
  1459. {
  1460. case no_record:
  1461. {
  1462. IHqlSimpleScope * scope = mappingExpr->querySimpleScope();
  1463. OwnedHqlExpr matched = scope->lookupSymbol(field->queryId());
  1464. assertex(matched == field);
  1465. ret = LINK(queryRealChild(field, 0));
  1466. break;
  1467. }
  1468. case no_newtransform:
  1469. {
  1470. ForEachChild(idx, mappingExpr)
  1471. {
  1472. IHqlExpression * cur = mappingExpr->queryChild(idx);
  1473. IHqlExpression * tgt = cur->queryChild(0);
  1474. if (tgt->getOperator() == no_select && tgt->queryChild(1) == field)
  1475. {
  1476. IHqlExpression * src = cur->queryChild(1);
  1477. ret = ensureExprType(src, tgt->queryType());
  1478. break;
  1479. }
  1480. }
  1481. assertex(ret);
  1482. break;
  1483. }
  1484. case no_transform:
  1485. {
  1486. //probably just as efficient..., and not used.
  1487. ret = getExpandSelectExprTest(expr);
  1488. break;
  1489. }
  1490. }
  1491. //OwnedHqlExpr test = getExpandSelectExprTest(expr);
  1492. //assertex(ret==test);
  1493. return ret;
  1494. }
  1495. return NULL;
  1496. }
  1497. //---------------------------------------------------------------------------
  1498. IHqlExpression * replaceChildDataset(IHqlExpression * expr, IHqlExpression * newChild, unsigned whichChild)
  1499. {
  1500. if (!(getChildDatasetType(expr) & childdataset_hasdataset))
  1501. {
  1502. HqlExprArray args;
  1503. unwindChildren(args, expr);
  1504. args.replace(*LINK(newChild), whichChild);
  1505. return expr->clone(args);
  1506. }
  1507. IHqlExpression * oldChild = expr->queryChild(whichChild);
  1508. HqlMapSelectorTransformer mapper(oldChild, newChild);
  1509. HqlExprArray args;
  1510. ForEachChild(i, expr)
  1511. {
  1512. IHqlExpression * cur = expr->queryChild(i);
  1513. if (i == whichChild)
  1514. args.append(*LINK(newChild));
  1515. else
  1516. args.append(*mapper.transformRoot(cur));
  1517. }
  1518. return expr->clone(args);
  1519. }
  1520. IHqlExpression * insertChildDataset(IHqlExpression * expr, IHqlExpression * newChild, unsigned whichChild)
  1521. {
  1522. assertex(expr->queryChild(whichChild) == newChild->queryChild(0));
  1523. //No need to map because children are still valid...
  1524. HqlExprArray args;
  1525. unwindChildren(args, expr);
  1526. args.replace(*LINK(newChild), whichChild);
  1527. return expr->clone(args);
  1528. }
  1529. IHqlExpression * swapDatasets(IHqlExpression * parent)
  1530. {
  1531. IHqlExpression * child = parent->queryChild(0);
  1532. OwnedHqlExpr newChild = replaceChildDataset(parent, child->queryChild(0), 0); // any refs to child must be mapped.
  1533. return insertChildDataset(child, newChild, 0);
  1534. }
  1535. //---------------------------------------------------------------------------
  1536. interface IHintVisitor
  1537. {
  1538. virtual IHqlExpression * visit(IHqlExpression * hint) = 0;
  1539. };
  1540. class SearchHintVisitor : implements IHintVisitor
  1541. {
  1542. public:
  1543. SearchHintVisitor(IAtom * _name) : name(_name) {}
  1544. virtual IHqlExpression * visit(IHqlExpression * hint)
  1545. {
  1546. return hint->queryAttribute(name);
  1547. }
  1548. IAtom * name;
  1549. };
  1550. class GatherHintVisitor : implements IHintVisitor
  1551. {
  1552. public:
  1553. GatherHintVisitor(HqlExprCopyArray & _target) : target(_target) {}
  1554. virtual IHqlExpression * visit(IHqlExpression * hint)
  1555. {
  1556. unwindChildren(target, hint);
  1557. return NULL;
  1558. }
  1559. HqlExprCopyArray & target;
  1560. };
  1561. static IHqlExpression * walkHints(IHqlExpression * expr, IHintVisitor & visitor)
  1562. {
  1563. //First look for any hint annotations.
  1564. for (;;)
  1565. {
  1566. annotate_kind kind = expr->getAnnotationKind();
  1567. if (kind == annotate_meta)
  1568. {
  1569. unsigned i=0;
  1570. IHqlExpression * cur;
  1571. while ((cur = expr->queryAnnotationParameter(i++)) != NULL)
  1572. {
  1573. if (cur->queryName() == hintAtom && cur->isAttribute())
  1574. {
  1575. IHqlExpression * ret = visitor.visit(cur);
  1576. if (ret)
  1577. return ret;
  1578. }
  1579. }
  1580. }
  1581. if (kind == annotate_none)
  1582. break;
  1583. expr = expr->queryBody(true);
  1584. }
  1585. //Then look for any hint attributes.
  1586. ForEachChild(i, expr)
  1587. {
  1588. IHqlExpression * cur = expr->queryChild(i);
  1589. if ((cur->queryName() == hintAtom) && cur->isAttribute())
  1590. {
  1591. IHqlExpression * match = visitor.visit(cur);
  1592. if (match)
  1593. return match;
  1594. }
  1595. }
  1596. return NULL;
  1597. }
  1598. IHqlExpression * queryHint(IHqlExpression * expr, IAtom * name)
  1599. {
  1600. SearchHintVisitor visitor(name);
  1601. return walkHints(expr, visitor);
  1602. }
  1603. void gatherHints(HqlExprCopyArray & target, IHqlExpression * expr)
  1604. {
  1605. GatherHintVisitor visitor(target);
  1606. walkHints(expr, visitor);
  1607. }
  1608. IHqlExpression * queryHintChild(IHqlExpression * expr, IAtom * name, unsigned idx)
  1609. {
  1610. IHqlExpression * match = queryHint(expr, name);
  1611. if (match)
  1612. return match->queryChild(idx);
  1613. return NULL;
  1614. }
  1615. void unwindHintAttrs(HqlExprArray & args, IHqlExpression * expr)
  1616. {
  1617. ForEachChild(i, expr)
  1618. {
  1619. IHqlExpression * cur = expr->queryChild(i);
  1620. if ((cur->queryName() == hintAtom) && cur->isAttribute())
  1621. args.append(*LINK(cur));
  1622. }
  1623. }
  1624. //---------------------------------------------------------------------------
  1625. IHqlExpression * createCompare(node_operator op, IHqlExpression * l, IHqlExpression * r)
  1626. {
  1627. if ((l->getOperator() == no_constant) && (r->getOperator() != no_constant))
  1628. return createCompare(getReverseOp(op), r, l);
  1629. ITypeInfo * t1 = l->queryType();
  1630. ITypeInfo * t2 = r->queryType();
  1631. //Check for comparisons that are always true/false....
  1632. IValue * value = r->queryValue();
  1633. if (value)
  1634. {
  1635. //Sometimes comparing an unsigned field with a constant can cause both parameters to be promoted
  1636. //to a larger type, because constants default to signed if small enough.
  1637. if (t1->getTypeCode() == type_int)
  1638. {
  1639. if (!t1->isSigned() && t2->isSigned() && t1->getSize() >= t2->getSize())
  1640. {
  1641. if (value->getIntValue() >= 0)
  1642. return createValue(op, makeBoolType(), LINK(l), ensureExprType(r, t1));
  1643. }
  1644. if ((queryUnqualifiedType(t1) != queryUnqualifiedType(t2)) && preservesValue(t1, r))
  1645. {
  1646. OwnedHqlExpr cast = ensureExprType(r, t1);
  1647. if (r != cast)
  1648. return createCompare(op, l, cast);
  1649. }
  1650. }
  1651. }
  1652. Owned<ITypeInfo> compareType = getPromotedECLCompareType(t1, t2);
  1653. return createValue(op, makeBoolType(), ensureExprType(l, compareType), ensureExprType(r, compareType));
  1654. }
  1655. IHqlExpression * flattenListOwn(IHqlExpression * list)
  1656. {
  1657. HqlExprArray args;
  1658. ITypeInfo * type = list->getType();
  1659. flattenListOwn(args, list);
  1660. return createValue(no_comma, type, args);
  1661. }
  1662. void flattenListOwn(HqlExprArray & out, IHqlExpression * list)
  1663. {
  1664. list->unwindList(out, no_comma);
  1665. releaseList(list);
  1666. }
  1667. void releaseList(IHqlExpression * list)
  1668. {
  1669. //normally lists are (((((a,b),c),d),e),f)
  1670. //so release rhs, and loop through lhs to reduce stack usage
  1671. while (list->getOperator() == no_comma)
  1672. {
  1673. IHqlExpression * next = LINK(list->queryChild(0));
  1674. list->Release();
  1675. list = next;
  1676. }
  1677. list->Release();
  1678. }
  1679. void expandRowSelectors(HqlExprArray & target, HqlExprArray const & source)
  1680. {
  1681. ForEachItemIn(i, source)
  1682. {
  1683. IHqlExpression & cur = source.item(i);
  1684. if (cur.isDatarow())
  1685. {
  1686. RecordSelectIterator iter(cur.queryRecord(), &cur);
  1687. ForEach(iter)
  1688. target.append(*iter.get());
  1689. }
  1690. else
  1691. target.append(OLINK(cur));
  1692. }
  1693. }
  1694. //---------------------------------------------------------------------------
  1695. unsigned getFirstActivityArgument(IHqlExpression * expr)
  1696. {
  1697. switch (expr->getOperator())
  1698. {
  1699. case no_mapto:
  1700. case no_if:
  1701. case no_case:
  1702. case no_fetch:
  1703. case no_libraryselect:
  1704. case no_chooseds:
  1705. case no_choose:
  1706. return 1;
  1707. }
  1708. return 0;
  1709. }
  1710. unsigned getNumActivityArguments(IHqlExpression * expr)
  1711. {
  1712. switch (expr->getOperator())
  1713. {
  1714. case no_compound_diskread:
  1715. case no_compound_indexread:
  1716. case no_compound_disknormalize:
  1717. case no_compound_diskaggregate:
  1718. case no_compound_diskcount:
  1719. case no_compound_diskgroupaggregate:
  1720. case no_compound_indexnormalize:
  1721. case no_compound_indexaggregate:
  1722. case no_compound_indexcount:
  1723. case no_compound_indexgroupaggregate:
  1724. case no_compound_childread:
  1725. case no_compound_childnormalize:
  1726. case no_compound_childaggregate:
  1727. case no_compound_childcount:
  1728. case no_compound_childgroupaggregate:
  1729. case no_compound_inline:
  1730. case no_keyindex:
  1731. case no_newkeyindex:
  1732. case no_table:
  1733. case no_preload:
  1734. case no_allnodes:
  1735. case no_thisnode:
  1736. case no_keydiff:
  1737. case no_keypatch:
  1738. case no_datasetfromdictionary:
  1739. return 0;
  1740. case no_setresult:
  1741. if (expr->queryChild(0)->isAction())
  1742. return 1;
  1743. return 0;
  1744. case no_compound_selectnew:
  1745. case no_libraryselect:
  1746. case no_definesideeffect:
  1747. return 1;
  1748. case no_libraryscopeinstance:
  1749. {
  1750. //It would be very nice to be able to cache this, but because the arguments are associated with the
  1751. //no_funcdef instead of the no_libraryscope it is a bit tricky. It could be optimized onto the
  1752. //no_libraryscopeinstance I guess.
  1753. IHqlExpression * libraryFuncDef = expr->queryDefinition();
  1754. IHqlExpression * library = libraryFuncDef->queryChild(0);
  1755. if (library->hasAttribute(_noStreaming_Atom))
  1756. return 0;
  1757. IHqlExpression * libraryFormals = libraryFuncDef->queryChild(1);
  1758. unsigned numStreaming = 0;
  1759. ForEachChild(i, libraryFormals)
  1760. {
  1761. if (libraryFormals->queryChild(i)->isDataset())
  1762. numStreaming++;
  1763. }
  1764. return numStreaming;
  1765. }
  1766. case no_select:
  1767. if (isNewSelector(expr))
  1768. return 1;
  1769. return 0;
  1770. case no_datasetfromrow:
  1771. case no_projectrow:
  1772. case no_fetch:
  1773. case no_mapto:
  1774. case no_evaluate:
  1775. case no_extractresult:
  1776. case no_outputscalar:
  1777. case no_keyeddistribute:
  1778. case no_normalize:
  1779. case no_process:
  1780. case no_mergejoin:
  1781. case no_nwayjoin:
  1782. case no_nwaymerge:
  1783. case no_related: // not an activity
  1784. return 1;
  1785. case no_denormalize:
  1786. case no_denormalizegroup:
  1787. case no_join:
  1788. case no_joincount:
  1789. if (isKeyedJoin(expr) && !expr->hasAttribute(_complexKeyed_Atom))
  1790. return 1;
  1791. return 2;
  1792. case no_combine:
  1793. case no_combinegroup:
  1794. case no_executewhen:
  1795. return 2;
  1796. case no_if:
  1797. if (queryRealChild(expr, 2))
  1798. return 2;
  1799. return 1;
  1800. case no_sequential:
  1801. case no_parallel:
  1802. case no_orderedactionlist:
  1803. case no_actionlist:
  1804. case no_comma:
  1805. case no_compound:
  1806. case no_addfiles:
  1807. case no_map:
  1808. return expr->numChildren();
  1809. case no_case:
  1810. return expr->numChildren()-1;
  1811. case no_forcelocal:
  1812. return 0;
  1813. default:
  1814. return getNumChildTables(expr);
  1815. }
  1816. }
  1817. bool isDistributedSourceActivity(IHqlExpression * expr)
  1818. {
  1819. switch (expr->getOperator())
  1820. {
  1821. case no_table:
  1822. case no_keyindex:
  1823. case no_newkeyindex:
  1824. case no_compound_indexread:
  1825. case no_compound_diskread:
  1826. case no_compound_disknormalize:
  1827. case no_compound_diskaggregate:
  1828. case no_compound_diskcount:
  1829. case no_compound_diskgroupaggregate:
  1830. case no_compound_indexnormalize:
  1831. case no_compound_indexaggregate:
  1832. case no_compound_indexcount:
  1833. case no_compound_indexgroupaggregate:
  1834. return true;
  1835. case no_getgraphresult:
  1836. return expr->hasAttribute(_distributed_Atom);
  1837. case no_workunit_dataset:
  1838. case no_getgraphloopresult:
  1839. case no_temptable:
  1840. case no_inlinetable:
  1841. case no_xmlproject:
  1842. case no_datasetfromrow:
  1843. case no_null:
  1844. case no_all:
  1845. case no_select:
  1846. case no_soapcall:
  1847. case no_newsoapcall:
  1848. case no_compound_childread:
  1849. case no_compound_childnormalize:
  1850. case no_compound_childaggregate:
  1851. case no_compound_childcount:
  1852. case no_compound_childgroupaggregate:
  1853. case no_compound_selectnew:
  1854. case no_compound_inline:
  1855. case no_rows:
  1856. case no_datasetfromdictionary:
  1857. return false;
  1858. default:
  1859. UNIMPLEMENTED;
  1860. }
  1861. }
  1862. bool isSourceActivity(IHqlExpression * expr, bool ignoreCompound)
  1863. {
  1864. switch (expr->getOperator())
  1865. {
  1866. case no_table:
  1867. case no_keyindex:
  1868. case no_newkeyindex:
  1869. case no_workunit_dataset:
  1870. case no_getgraphresult:
  1871. case no_getgraphloopresult:
  1872. case no_temptable:
  1873. case no_inlinetable:
  1874. case no_xmlproject:
  1875. // case no_all:
  1876. case no_httpcall:
  1877. case no_soapcall:
  1878. case no_newsoapcall:
  1879. case no_rows:
  1880. case no_allnodes:
  1881. case no_thisnode:
  1882. case no_datasetfromdictionary:
  1883. return true;
  1884. case no_null:
  1885. return expr->isDataset();
  1886. case no_select:
  1887. if (isNewSelector(expr))
  1888. return false;
  1889. return expr->isDataset();
  1890. case no_compound_indexread:
  1891. case no_compound_diskread:
  1892. case no_compound_disknormalize:
  1893. case no_compound_diskaggregate:
  1894. case no_compound_diskcount:
  1895. case no_compound_diskgroupaggregate:
  1896. case no_compound_indexnormalize:
  1897. case no_compound_indexaggregate:
  1898. case no_compound_indexcount:
  1899. case no_compound_indexgroupaggregate:
  1900. case no_compound_childread:
  1901. case no_compound_childnormalize:
  1902. case no_compound_childaggregate:
  1903. case no_compound_childcount:
  1904. case no_compound_childgroupaggregate:
  1905. case no_compound_inline:
  1906. return !ignoreCompound;
  1907. }
  1908. return false;
  1909. }
  1910. bool isSinkActivity(IHqlExpression * expr)
  1911. {
  1912. switch (expr->getOperator())
  1913. {
  1914. case no_parallel:
  1915. case no_actionlist:
  1916. case no_sequential:
  1917. case no_orderedactionlist:
  1918. case no_apply:
  1919. case no_output:
  1920. case no_buildindex:
  1921. case no_distribution:
  1922. case no_keydiff:
  1923. case no_keypatch:
  1924. case no_returnresult:
  1925. case no_extractresult:
  1926. case no_setresult:
  1927. case no_setgraphresult:
  1928. case no_setgraphloopresult:
  1929. case no_definesideeffect:
  1930. //case no_callsideeffect: //??
  1931. return true;
  1932. case no_soapcall:
  1933. case no_newsoapcall:
  1934. case no_if:
  1935. case no_null:
  1936. case no_choose:
  1937. return expr->isAction();
  1938. }
  1939. return false;
  1940. }
  1941. bool isDistributedActivity(IHqlExpression * expr)
  1942. {
  1943. switch (expr->getOperator())
  1944. {
  1945. case no_table:
  1946. case no_keyindex:
  1947. case no_newkeyindex:
  1948. case no_compound_indexread:
  1949. case no_compound_diskread:
  1950. case no_compound_disknormalize:
  1951. case no_compound_diskaggregate:
  1952. case no_compound_diskcount:
  1953. case no_compound_diskgroupaggregate:
  1954. case no_compound_indexnormalize:
  1955. case no_compound_indexaggregate:
  1956. case no_compound_indexcount:
  1957. case no_compound_indexgroupaggregate:
  1958. return true;
  1959. case no_join:
  1960. case no_joincount:
  1961. case no_denormalize:
  1962. case no_denormalizegroup:
  1963. return isKeyedJoin(expr);
  1964. case no_fetch:
  1965. case no_compound_fetch:
  1966. return true;
  1967. }
  1968. return false;
  1969. }
  1970. unsigned getFieldCount(IHqlExpression * expr)
  1971. {
  1972. switch (expr->getOperator())
  1973. {
  1974. case no_record:
  1975. {
  1976. unsigned count = 0;
  1977. ForEachChild(i, expr)
  1978. count += getFieldCount(expr->queryChild(i));
  1979. return count;
  1980. }
  1981. case no_ifblock:
  1982. return getFieldCount(expr->queryChild(1));
  1983. case no_field:
  1984. {
  1985. ITypeInfo * type = expr->queryType();
  1986. if (type->getTypeCode() == type_row)
  1987. return getFieldCount(expr->queryRecord());
  1988. return 1;
  1989. }
  1990. case no_attr:
  1991. case no_attr_link:
  1992. case no_attr_expr:
  1993. return 0;
  1994. default:
  1995. //UNIMPLEMENTED;
  1996. return 0;
  1997. }
  1998. }
  1999. IHqlExpression * queryChildActivity(IHqlExpression * expr, unsigned index)
  2000. {
  2001. unsigned firstActivityIndex = 0;
  2002. switch (expr->getOperator())
  2003. {
  2004. case no_compound_selectnew:
  2005. if (index == 0)
  2006. return queryRoot(expr)->queryChild(0);
  2007. return NULL;
  2008. case no_mapto:
  2009. case no_if:
  2010. case no_case:
  2011. case no_fetch:
  2012. case no_choose:
  2013. case no_chooseds:
  2014. firstActivityIndex = 1;
  2015. break;
  2016. }
  2017. return queryRealChild(expr, firstActivityIndex + index);
  2018. }
  2019. unsigned getFlatFieldCount(IHqlExpression * expr)
  2020. {
  2021. switch (expr->getOperator())
  2022. {
  2023. case no_record:
  2024. {
  2025. unsigned count = 0;
  2026. ForEachChild(i, expr)
  2027. count += getFlatFieldCount(expr->queryChild(i));
  2028. return count;
  2029. }
  2030. case no_ifblock:
  2031. return getFlatFieldCount(expr->queryChild(1));
  2032. case no_field:
  2033. return 1;
  2034. case no_attr:
  2035. case no_attr_link:
  2036. case no_attr_expr:
  2037. return 0;
  2038. default:
  2039. UNIMPLEMENTED;
  2040. }
  2041. }
  2042. //This function gathers information about the number of fields etc. in a record.
  2043. //MORE: Should this calculate numFields, numExpandedFields, numDatasetFields all in a single function and
  2044. //then cache it as a property of a no_record? Only if it becomes a significant bottleneck.
  2045. void gatherRecordStats(HqlRecordStats & stats, IHqlExpression * expr)
  2046. {
  2047. switch (expr->getOperator())
  2048. {
  2049. case no_record:
  2050. {
  2051. ForEachChild(i, expr)
  2052. gatherRecordStats(stats, expr->queryChild(i));
  2053. break;
  2054. }
  2055. case no_ifblock:
  2056. return gatherRecordStats(stats, expr->queryChild(1));
  2057. case no_field:
  2058. {
  2059. ITypeInfo * type = expr->queryType();
  2060. switch (type->getTypeCode())
  2061. {
  2062. case type_table:
  2063. case type_groupedtable:
  2064. stats.fields++;
  2065. stats.unknownSizeFields++;
  2066. break;
  2067. case type_dictionary:
  2068. stats.fields++;
  2069. stats.unknownSizeFields++;
  2070. break;
  2071. case type_row:
  2072. gatherRecordStats(stats, expr->queryRecord());
  2073. break;
  2074. default:
  2075. stats.fields++;
  2076. //HPCC-17606 add: if (type->getSize() == UNKNOWN_LENGTH) stats.unknownSizeFields++;
  2077. break;
  2078. }
  2079. break;
  2080. }
  2081. case no_attr:
  2082. case no_attr_link:
  2083. case no_attr_expr:
  2084. break;
  2085. default:
  2086. UNIMPLEMENTED;
  2087. }
  2088. }
  2089. unsigned getVarSizeFieldCount(IHqlExpression * expr, bool expandRows)
  2090. {
  2091. //MORE: Is it worth caching the results of these functions as attributes?
  2092. switch (expr->getOperator())
  2093. {
  2094. case no_record:
  2095. {
  2096. unsigned count = 0;
  2097. ForEachChild(i, expr)
  2098. count += getVarSizeFieldCount(expr->queryChild(i), expandRows);
  2099. return count;
  2100. }
  2101. case no_ifblock:
  2102. return getVarSizeFieldCount(expr->queryChild(1), expandRows);
  2103. case no_field:
  2104. {
  2105. ITypeInfo * type = expr->queryType();
  2106. if (expandRows)
  2107. {
  2108. if (type->getTypeCode() == type_row)
  2109. return getVarSizeFieldCount(expr->queryRecord(), expandRows);
  2110. }
  2111. if (isArrayRowset(type))
  2112. return 0;
  2113. return isUnknownSize(type) ? 1 : 0;
  2114. }
  2115. case no_attr:
  2116. case no_attr_link:
  2117. case no_attr_expr:
  2118. return 0;
  2119. default:
  2120. //UNIMPLEMENTED;
  2121. return 0;
  2122. }
  2123. }
  2124. unsigned isEmptyRecord(IHqlExpression * record)
  2125. {
  2126. ForEachChild(i, record)
  2127. {
  2128. IHqlExpression * cur = record->queryChild(i);
  2129. switch (cur->getOperator())
  2130. {
  2131. case no_record:
  2132. if (!isEmptyRecord(cur))
  2133. return false;
  2134. break;
  2135. case no_ifblock:
  2136. if (!isEmptyRecord(cur->queryChild(1)))
  2137. return false;
  2138. break;
  2139. case no_field:
  2140. return false;
  2141. }
  2142. }
  2143. return true;
  2144. }
  2145. void getSimpleFields(HqlExprArray &out, IHqlExpression *record)
  2146. {
  2147. ForEachChild(i, record)
  2148. {
  2149. IHqlExpression * cur = record->queryChild(i);
  2150. switch (cur->getOperator())
  2151. {
  2152. case no_attr:
  2153. case no_attr_expr:
  2154. break;
  2155. case no_field:
  2156. switch (cur->queryType()->getTypeCode())
  2157. {
  2158. case type_record:
  2159. case type_row:
  2160. {
  2161. IHqlExpression *nested = cur->queryRecord();
  2162. if (nested)
  2163. getSimpleFields(out, nested);
  2164. break;
  2165. }
  2166. case type_table:
  2167. case type_groupedtable:
  2168. case type_alien:
  2169. case type_any:
  2170. case type_dictionary:
  2171. throwUnexpected();
  2172. default:
  2173. out.append(*LINK(cur));
  2174. break;
  2175. }
  2176. break;
  2177. case no_record:
  2178. getSimpleFields(out, cur);
  2179. break;
  2180. default:
  2181. throwUnexpected();
  2182. }
  2183. }
  2184. }
  2185. unsigned isSimpleRecord(IHqlExpression * record)
  2186. {
  2187. ForEachChild(i, record)
  2188. {
  2189. IHqlExpression * cur = record->queryChild(i);
  2190. switch (cur->getOperator())
  2191. {
  2192. case no_attr:
  2193. case no_attr_expr:
  2194. break;
  2195. case no_field:
  2196. switch (cur->queryType()->getTypeCode())
  2197. {
  2198. case type_record:
  2199. case type_row:
  2200. {
  2201. IHqlExpression *nested = cur->queryRecord();
  2202. if (nested && !isSimpleRecord(nested))
  2203. return false;
  2204. break;
  2205. }
  2206. case type_table:
  2207. case type_groupedtable:
  2208. case type_alien:
  2209. case type_any:
  2210. case type_dictionary:
  2211. return false;
  2212. }
  2213. break;
  2214. case no_record:
  2215. if (!isSimpleRecord(cur))
  2216. return false;
  2217. break;
  2218. default:
  2219. return false;
  2220. }
  2221. }
  2222. return record->numChildren()>0;
  2223. }
  2224. bool isTrivialSelectN(IHqlExpression * expr)
  2225. {
  2226. if (expr->getOperator() == no_index || expr->getOperator() == no_selectnth)
  2227. {
  2228. IHqlExpression * index = expr->queryChild(1);
  2229. if (matchesConstantValue(index, 1))
  2230. return hasSingleRow(expr->queryChild(0));
  2231. }
  2232. return false;
  2233. }
  2234. IHqlExpression * queryAttributeChild(IHqlExpression * expr, IAtom * name, unsigned idx)
  2235. {
  2236. IHqlExpression * match = expr->queryAttribute(name);
  2237. if (match)
  2238. return match->queryChild(idx);
  2239. return NULL;
  2240. }
  2241. int getResultSequenceValue(IHqlExpression * set)
  2242. {
  2243. switch (set->getOperator())
  2244. {
  2245. case no_setresult:
  2246. case no_ensureresult:
  2247. case no_extractresult:
  2248. case no_output:
  2249. return (int)getIntValue(queryAttributeChild(set, sequenceAtom, 0), 0);
  2250. }
  2251. return 0;
  2252. }
  2253. IHqlExpression * querySequence(IHqlExpression * expr)
  2254. {
  2255. IHqlExpression * seq = expr->queryAttribute(sequenceAtom);
  2256. if (seq)
  2257. return seq->queryChild(0);
  2258. if (expr->queryValue())
  2259. return expr;
  2260. return NULL;
  2261. }
  2262. IHqlExpression * queryResultName(IHqlExpression * expr)
  2263. {
  2264. IHqlExpression * name = expr->queryAttribute(namedAtom);
  2265. if (name)
  2266. return name->queryChild(0);
  2267. return NULL;
  2268. }
  2269. bool remainingChildrenMatch(IHqlExpression * left, IHqlExpression * right, unsigned first)
  2270. {
  2271. if (left->numChildren() != right->numChildren())
  2272. return false;
  2273. ForEachChildFrom(i, left, first)
  2274. {
  2275. if (left->queryChild(i) != right->queryChild(i))
  2276. return false;
  2277. }
  2278. return true;
  2279. }
  2280. //---------------------------------------------------------------------------
  2281. IHqlExpression * queryConvertChoosenNSort(IHqlExpression * expr, unsigned __int64 topNlimit)
  2282. {
  2283. OwnedHqlExpr first = foldHqlExpression(queryRealChild(expr, 2));
  2284. IHqlExpression * child = expr->queryChild(0);
  2285. if ((child->getOperator() != no_sort) || isGroupedActivity(child))
  2286. return NULL;
  2287. IHqlExpression * cosort = queryRealChild(child, 2);
  2288. if (cosort)
  2289. return NULL;
  2290. //grouped sort->choosen. Don't convert unless choosen preserves grouping
  2291. if (isGrouped(child) && !expr->hasAttribute(groupedAtom))
  2292. return NULL;
  2293. OwnedHqlExpr count = foldHqlExpression(expr->queryChild(1));
  2294. bool clone = false;
  2295. if (count->queryValue())
  2296. {
  2297. unsigned __int64 limit = count->queryValue()->getIntValue();
  2298. if (first)
  2299. {
  2300. if (!first->queryValue())
  2301. return NULL;
  2302. limit += (first->queryValue()->getIntValue() - 1);
  2303. count.setown(createConstant((__int64)limit));
  2304. clone = true;
  2305. }
  2306. if (limit > topNlimit)
  2307. return NULL;
  2308. }
  2309. else
  2310. {
  2311. if (!expr->hasAttribute(fewAtom) || first)
  2312. return NULL;
  2313. }
  2314. //choosen(sort(x,a,local),n) -> do the topn local, but need to reapply the global choosen
  2315. if (expr->hasAttribute(localAtom))
  2316. {
  2317. if (!child->hasAttribute(localAtom))
  2318. return NULL;
  2319. }
  2320. else
  2321. {
  2322. if (child->hasAttribute(localAtom))
  2323. clone = true;
  2324. }
  2325. HqlExprArray args;
  2326. unwindChildren(args, child);
  2327. args.add(*LINK(count), 2);
  2328. IHqlExpression * top = createDataset(no_topn, args);
  2329. if (!clone)
  2330. return top;
  2331. args.kill();
  2332. unwindChildren(args, expr);
  2333. args.replace(*top, 0);
  2334. return expr->clone(args);
  2335. }
  2336. //---------------------------------------------------------------------------
  2337. void DependenciesUsed::clear()
  2338. {
  2339. tablesRead.kill();
  2340. tablesWritten.kill();
  2341. resultsRead.kill();
  2342. resultsWritten.kill();
  2343. allRead = false;
  2344. allWritten = false;
  2345. }
  2346. bool DependenciesUsed::canSwapOrder(const DependenciesUsed & other) const
  2347. {
  2348. //Dependant on output from the previous
  2349. if (isDependantOn(other) || other.isDependantOn(*this))
  2350. return false;
  2351. return true;
  2352. }
  2353. bool DependenciesUsed::isDependantOn(const DependenciesUsed & other) const
  2354. {
  2355. //Dependant on output from the previous
  2356. if (allRead && (other.allWritten || other.tablesWritten.ordinality()))
  2357. return true;
  2358. if (other.allWritten && tablesRead.ordinality())
  2359. return true;
  2360. return isExplicitlyDependantOn(other);
  2361. }
  2362. bool DependenciesUsed::isExplicitlyDependantOn(const DependenciesUsed & other) const
  2363. {
  2364. ForEachItemIn(idx1, tablesRead)
  2365. {
  2366. if (other.tablesWritten.find(tablesRead.item(idx1)) != NotFound)
  2367. return true;
  2368. }
  2369. ForEachItemIn(idx2, resultsRead)
  2370. {
  2371. if (other.resultsWritten.find(resultsRead.item(idx2)) != NotFound)
  2372. return true;
  2373. }
  2374. return false;
  2375. }
  2376. void DependenciesUsed::addFilenameRead(IHqlExpression * expr)
  2377. {
  2378. OwnedHqlExpr normalized = getNormalizedFilename(expr);
  2379. if (tablesRead.find(*normalized) == NotFound)
  2380. {
  2381. appendUniqueExpr(tablesRead, LINK(normalized));
  2382. if (!normalized->queryValue())
  2383. allRead = true;
  2384. }
  2385. }
  2386. void DependenciesUsed::addFilenameWrite(IHqlExpression * expr)
  2387. {
  2388. OwnedHqlExpr normalized = getNormalizedFilename(expr);
  2389. if (appendUniqueExpr(tablesWritten, LINK(normalized)))
  2390. if (tablesRead.contains(*normalized))
  2391. noteInconsistency(normalized);
  2392. if (!normalized->queryValue())
  2393. allWritten = true;
  2394. }
  2395. void DependenciesUsed::addResultRead(IHqlExpression * wuid, IHqlExpression * seq, IHqlExpression * name, bool isGraphResult)
  2396. {
  2397. if (!isGraphResult)
  2398. if (!seq || !seq->queryValue())
  2399. return; //Can be called in parser when no sequence has been allocated
  2400. OwnedHqlExpr result = createExprAttribute(resultAtom, LINK(seq), LINK(name), LINK(wuid));
  2401. if (resultsWritten.find(*result) == NotFound)
  2402. appendUniqueExpr(resultsRead, LINK(result));
  2403. }
  2404. void DependenciesUsed::addResultWrite(IHqlExpression * seq, IHqlExpression * name, bool isGraphResult)
  2405. {
  2406. if (!isGraphResult)
  2407. if (!seq || !seq->queryValue())
  2408. return; //Can be called in parser when no sequence has been allocated
  2409. OwnedHqlExpr result = createExprAttribute(resultAtom, LINK(seq), LINK(name));
  2410. if (appendUniqueExpr(resultsWritten, LINK(result)))
  2411. if (resultsRead.contains(*result))
  2412. noteInconsistency(result);
  2413. }
  2414. void DependenciesUsed::addRefDependency(IHqlExpression * expr)
  2415. {
  2416. IHqlExpression * filename = queryTableFilename(expr);
  2417. if (filename)
  2418. addFilenameRead(filename);
  2419. }
  2420. IHqlExpression * DependenciesUsed::getNormalizedFilename(IHqlExpression * filename)
  2421. {
  2422. if (normalize)
  2423. return ::getNormalizedFilename(filename);
  2424. return LINK(filename);
  2425. }
  2426. bool DependenciesUsed::isSubsetOf(const DependenciesUsed & other) const
  2427. {
  2428. ForEachItemIn(idx1, tablesRead)
  2429. if (!other.tablesRead.contains(tablesRead.item(idx1)))
  2430. return false;
  2431. ForEachItemIn(idx2, resultsRead)
  2432. if (!other.resultsRead.contains(resultsRead.item(idx2)))
  2433. return false;
  2434. return true;
  2435. }
  2436. void DependenciesUsed::mergeIn(const DependenciesUsed & other)
  2437. {
  2438. appendArray(tablesRead, other.tablesRead);
  2439. appendArray(tablesWritten, other.tablesWritten);
  2440. appendArray(resultsRead, other.resultsRead);
  2441. appendArray(resultsWritten, other.resultsWritten);
  2442. if (other.allRead)
  2443. allRead = true;
  2444. if (other.allWritten)
  2445. allWritten = true;
  2446. }
  2447. void DependenciesUsed::extractDependencies(IHqlExpression * expr, unsigned flags)
  2448. {
  2449. switch (expr->getOperator())
  2450. {
  2451. case no_buildindex:
  2452. case no_output:
  2453. {
  2454. IHqlExpression * out = queryRealChild(expr, 1);
  2455. if (out)
  2456. {
  2457. if (flags & GatherFileWrite)
  2458. {
  2459. switch (out->getOperator())
  2460. {
  2461. case no_pipe:
  2462. allWritten = true;
  2463. break;
  2464. default:
  2465. addFilenameWrite(out);
  2466. break;
  2467. }
  2468. }
  2469. }
  2470. else
  2471. {
  2472. if (flags & GatherResultWrite)
  2473. addResultWrite(querySequence(expr), queryResultName(expr), false);
  2474. }
  2475. }
  2476. break;
  2477. case no_newkeyindex:
  2478. case no_keyindex:
  2479. if (flags & GatherFileRead)
  2480. addRefDependency(expr);
  2481. break;
  2482. case no_keydiff:
  2483. if (flags & GatherFileRead)
  2484. {
  2485. addRefDependency(expr->queryChild(0));
  2486. addRefDependency(expr->queryChild(1));
  2487. }
  2488. if (flags & GatherFileWrite)
  2489. addFilenameWrite(expr->queryChild(2));
  2490. break;
  2491. case no_keypatch:
  2492. if (flags & GatherFileRead)
  2493. {
  2494. addRefDependency(expr->queryChild(0));
  2495. addFilenameRead(expr->queryChild(1));
  2496. }
  2497. if (flags & GatherFileWrite)
  2498. addFilenameWrite(expr->queryChild(2));
  2499. break;
  2500. case no_table:
  2501. if (flags & GatherFileRead)
  2502. {
  2503. IHqlExpression * in = expr->queryChild(0);
  2504. IHqlExpression * mode = expr->queryChild(2);
  2505. if (mode->getOperator() == no_pipe)
  2506. allRead = true;
  2507. addFilenameRead(in);
  2508. }
  2509. break;
  2510. case no_workunit_dataset:
  2511. if (flags & GatherResultRead)
  2512. {
  2513. IHqlExpression * sequence = queryAttributeChild(expr, sequenceAtom, 0);
  2514. IHqlExpression * name = queryAttributeChild(expr, nameAtom, 0);
  2515. IHqlExpression * wuid = expr->queryAttribute(wuidAtom);
  2516. addResultRead(wuid, sequence, name, false);
  2517. }
  2518. break;
  2519. case no_getgraphresult:
  2520. if (flags & GatherGraphResultRead)
  2521. addResultRead(NULL, expr->queryChild(1), expr->queryChild(2), true);
  2522. break;
  2523. case no_setgraphresult:
  2524. if (flags & GatherGraphResultWrite)
  2525. addResultWrite(expr->queryChild(1), expr->queryChild(2), true);
  2526. break;
  2527. case no_getresult:
  2528. if (flags & GatherResultRead)
  2529. {
  2530. IHqlExpression * sequence = queryAttributeChild(expr, sequenceAtom, 0);
  2531. IHqlExpression * name = queryAttributeChild(expr, namedAtom, 0);
  2532. IHqlExpression * wuid = expr->queryAttribute(wuidAtom);
  2533. addResultRead(wuid, sequence, name, false);
  2534. }
  2535. break;
  2536. case no_ensureresult:
  2537. case no_setresult:
  2538. case no_extractresult:
  2539. if (flags & GatherResultWrite)
  2540. {
  2541. IHqlExpression * sequence = queryAttributeChild(expr, sequenceAtom, 0);
  2542. IHqlExpression * name = queryAttributeChild(expr, namedAtom, 0);
  2543. addResultWrite(sequence, name, false);
  2544. }
  2545. break;
  2546. case no_definesideeffect:
  2547. if (flags & GatherResultWrite)
  2548. {
  2549. addResultWrite(expr->queryAttribute(_uid_Atom), NULL, false);
  2550. }
  2551. break;
  2552. case no_callsideeffect:
  2553. if (flags & GatherResultRead)
  2554. {
  2555. addResultRead(NULL, expr->queryAttribute(_uid_Atom), NULL, false);
  2556. }
  2557. break;
  2558. }
  2559. }
  2560. void DependenciesUsed::noteInconsistency(IHqlExpression * expr)
  2561. {
  2562. if (!inconsistent)
  2563. inconsistent.set(expr);
  2564. }
  2565. void DependenciesUsed::removeInternalReads()
  2566. {
  2567. ForEachItemInRev(idx1, tablesRead)
  2568. {
  2569. IHqlExpression & cur = tablesRead.item(idx1);
  2570. if (tablesWritten.contains(cur))
  2571. tablesRead.remove(idx1);
  2572. }
  2573. }
  2574. void checkDependencyConsistency(IHqlExpression * expr)
  2575. {
  2576. DependenciesUsed depends(true);
  2577. gatherDependencies(expr, depends, GatherAll);
  2578. if (depends.inconsistent)
  2579. {
  2580. StringBuffer s;
  2581. if (depends.inconsistent->queryName() == resultAtom)
  2582. {
  2583. getStoredDescription(s, depends.inconsistent->queryChild(0), depends.inconsistent->queryChild(1), true);
  2584. throw MakeStringException(ERR_RECURSIVE_DEPENDENCY, "Result '%s' used before it is written", s.str());
  2585. }
  2586. else
  2587. {
  2588. depends.inconsistent->toString(s);
  2589. // DBGLOG("Filename %s used before it is written", s.str());
  2590. throw MakeStringException(ERR_RECURSIVE_DEPENDENCY, "Filename %s used before it is written", s.str());
  2591. }
  2592. }
  2593. }
  2594. void checkDependencyConsistency(const HqlExprArray & exprs)
  2595. {
  2596. DependenciesUsed depends(true);
  2597. DependencyGatherer gatherer(depends, GatherAll);
  2598. ForEachItemIn(i, exprs)
  2599. gatherer.gatherDependencies(&exprs.item(i));
  2600. if (depends.inconsistent)
  2601. {
  2602. StringBuffer s;
  2603. if (depends.inconsistent->queryName() == resultAtom)
  2604. {
  2605. getStoredDescription(s, depends.inconsistent->queryChild(0), depends.inconsistent->queryChild(1), true);
  2606. throw MakeStringException(ERR_RECURSIVE_DEPENDENCY, "Result '%s' used before it is written", s.str());
  2607. }
  2608. else
  2609. {
  2610. depends.inconsistent->toString(s);
  2611. // DBGLOG("Filename %s used before it is written", s.str());
  2612. throw MakeStringException(ERR_RECURSIVE_DEPENDENCY, "Filename %s used before it is written", s.str());
  2613. }
  2614. }
  2615. }
  2616. //---------------------------------------------------------------------------
  2617. static HqlTransformerInfo selectConsistencyCheckerInfo("SelectConsistencyChecker");
  2618. class SelectConsistencyChecker : public NewHqlTransformer
  2619. {
  2620. public:
  2621. SelectConsistencyChecker() : NewHqlTransformer(selectConsistencyCheckerInfo)
  2622. {
  2623. }
  2624. virtual void analyseExpr(IHqlExpression * expr)
  2625. {
  2626. if (alreadyVisited(expr))
  2627. return;
  2628. if (expr->getOperator() == no_select)
  2629. checkSelect(expr);
  2630. NewHqlTransformer::analyseExpr(expr);
  2631. }
  2632. virtual void analyseSelector(IHqlExpression * expr)
  2633. {
  2634. if (expr->getOperator() == no_select)
  2635. checkSelect(expr);
  2636. NewHqlTransformer::analyseSelector(expr);
  2637. }
  2638. protected:
  2639. void checkSelect(IHqlExpression * expr)
  2640. {
  2641. IHqlExpression * ds = expr->queryChild(0);
  2642. if (ds->getOperator() == no_activetable)
  2643. return;
  2644. IHqlExpression * field = expr->queryChild(1);
  2645. IHqlExpression * record = ds->queryRecord();
  2646. assertex(record);
  2647. IHqlSimpleScope * scope = record->querySimpleScope();
  2648. OwnedHqlExpr match = scope->lookupSymbol(field->queryId());
  2649. if (match != field)
  2650. {
  2651. EclIR::dbglogIR(2, field, match.get());
  2652. throw MakeStringException(ERR_RECURSIVE_DEPENDENCY, "Inconsistent select - field doesn't match parent record's field");
  2653. }
  2654. }
  2655. };
  2656. void checkSelectConsistency(IHqlExpression * expr)
  2657. {
  2658. SelectConsistencyChecker checker;
  2659. checker.analyse(expr, 0);
  2660. }
  2661. //---------------------------------------------------------------------------
  2662. static HqlTransformerInfo parameterDependencyCheckerInfo("ParameterDependencyChecker");
  2663. class ParameterDependencyChecker : public NewHqlTransformer
  2664. {
  2665. public:
  2666. ParameterDependencyChecker() : NewHqlTransformer(parameterDependencyCheckerInfo), foundParameter(false)
  2667. {
  2668. }
  2669. virtual void analyseExpr(IHqlExpression * expr)
  2670. {
  2671. if (expr->isFullyBound() || alreadyVisited(expr) || foundParameter)
  2672. return;
  2673. if (expr->getOperator() == no_param)
  2674. {
  2675. foundParameter = true;
  2676. return;
  2677. }
  2678. NewHqlTransformer::analyseExpr(expr);
  2679. }
  2680. bool isDependent(IHqlExpression * expr)
  2681. {
  2682. analyse(expr, 0);
  2683. return foundParameter;
  2684. }
  2685. protected:
  2686. bool foundParameter;
  2687. };
  2688. //Is 'expr' really dependent on a parameter - expr->isFullyBound() can give false negatives.
  2689. bool isDependentOnParameter(IHqlExpression * expr)
  2690. {
  2691. if (expr->isFullyBound())
  2692. return false;
  2693. ParameterDependencyChecker checker;
  2694. return checker.isDependent(expr);
  2695. }
  2696. bool isTimed(IHqlExpression * expr)
  2697. {
  2698. switch (expr->getOperator())
  2699. {
  2700. case no_externalcall:
  2701. {
  2702. IHqlExpression * funcdef = expr->queryExternalDefinition();
  2703. assertex(funcdef);
  2704. IHqlExpression * body = funcdef->queryChild(0);
  2705. if (body->hasAttribute(timeAtom))
  2706. return true;
  2707. break;
  2708. }
  2709. case no_call:
  2710. {
  2711. IHqlExpression * funcdef = expr->queryBody()->queryFunctionDefinition();
  2712. assertex(funcdef);
  2713. IHqlExpression * body = funcdef->queryChild(0);
  2714. if (body && body->hasAttribute(timeAtom))
  2715. return true;
  2716. break;
  2717. }
  2718. }
  2719. return false;
  2720. }
  2721. //---------------------------------------------------------------------------
  2722. void DependencyGatherer::doGatherDependencies(IHqlExpression * expr)
  2723. {
  2724. if (expr->queryTransformExtra())
  2725. return;
  2726. expr->setTransformExtraUnlinked(expr);
  2727. used.extractDependencies(expr, flags);
  2728. unsigned first = 0;
  2729. unsigned max = expr->numChildren();
  2730. switch (expr->getOperator())
  2731. {
  2732. case no_field: // by now there should be no default values as children of fields.
  2733. case no_attr:
  2734. case no_attr_link:
  2735. return;
  2736. case no_select:
  2737. if (!isNewSelector(expr))
  2738. return;
  2739. max = 1; // by now there should be no default values as children of fields.
  2740. break;
  2741. case no_keyindex:
  2742. first = 2;
  2743. break;
  2744. case no_newkeyindex:
  2745. first = 3;
  2746. break;
  2747. case no_executewhen:
  2748. if (expr->hasAttribute(beforeAtom))
  2749. {
  2750. for (unsigned i=max; i-- != 0; )
  2751. doGatherDependencies(expr->queryChild(i));
  2752. return;
  2753. }
  2754. break;
  2755. }
  2756. for (unsigned i = first; i < max; i++)
  2757. doGatherDependencies(expr->queryChild(i));
  2758. }
  2759. void DependencyGatherer::gatherDependencies(IHqlExpression * expr)
  2760. {
  2761. TransformMutexBlock lock;
  2762. doGatherDependencies(expr);
  2763. }
  2764. extern HQL_API void gatherDependencies(IHqlExpression * expr, DependenciesUsed & used, unsigned flags)
  2765. {
  2766. DependencyGatherer gatherer(used, flags);
  2767. gatherer.gatherDependencies(expr);
  2768. }
  2769. extern HQL_API bool introducesNewDependencies(IHqlExpression * oldExpr, IHqlExpression * newExpr)
  2770. {
  2771. DependenciesUsed oldDepends(true);
  2772. DependenciesUsed newDepends(true);
  2773. gatherDependencies(newExpr, newDepends, GatherAllRead);
  2774. gatherDependencies(oldExpr, oldDepends, GatherAllRead);
  2775. return !newDepends.isSubsetOf(oldDepends);
  2776. }
  2777. //---------------------------------------------------------------------------
  2778. RecordSelectIterator::RecordSelectIterator(IHqlExpression * record, IHqlExpression * selector)
  2779. {
  2780. rootRecord.set(record);
  2781. rootSelector.set(selector);
  2782. nestingDepth = 0;
  2783. ifblockDepth = 0;
  2784. }
  2785. bool RecordSelectIterator::doNext()
  2786. {
  2787. while (indices.ordinality())
  2788. {
  2789. for (;;)
  2790. {
  2791. unsigned next = indices.tos();
  2792. IHqlExpression & curRecord = records.tos();
  2793. unsigned max = curRecord.numChildren();
  2794. if (next >= max)
  2795. break;
  2796. indices.pop();
  2797. indices.append(next+1);
  2798. IHqlExpression * cur = curRecord.queryChild(next);
  2799. switch (cur->getOperator())
  2800. {
  2801. case no_record:
  2802. beginRecord(cur);
  2803. break;
  2804. case no_field:
  2805. switch (cur->queryType()->getTypeCode())
  2806. {
  2807. case type_row:
  2808. beginRecord(cur->queryRecord());
  2809. selector.setown(createSelectExpr(LINK(selector), LINK(cur)));
  2810. nestingDepth++;
  2811. break;
  2812. default:
  2813. curSelector.setown(createSelectExpr(LINK(selector), LINK(cur)));
  2814. return true;
  2815. }
  2816. break;
  2817. case no_ifblock:
  2818. beginRecord(cur->queryChild(1));
  2819. ifblockDepth++;
  2820. break;
  2821. case no_attr:
  2822. case no_attr_link:
  2823. case no_attr_expr:
  2824. break;
  2825. default:
  2826. UNIMPLEMENTED;
  2827. }
  2828. }
  2829. indices.pop();
  2830. records.pop();
  2831. selector.setown(&savedSelector.popGet());
  2832. if (records.ordinality())
  2833. {
  2834. switch (records.tos().queryChild(indices.tos()-1)->getOperator())
  2835. {
  2836. case no_ifblock:
  2837. ifblockDepth--;
  2838. break;
  2839. case no_field:
  2840. nestingDepth--;
  2841. break;
  2842. }
  2843. }
  2844. }
  2845. curSelector.clear();
  2846. return false;
  2847. }
  2848. void RecordSelectIterator::beginRecord(IHqlExpression * record)
  2849. {
  2850. savedSelector.append(*LINK(selector));
  2851. records.append(*record);
  2852. indices.append(0);
  2853. }
  2854. bool RecordSelectIterator::first()
  2855. {
  2856. savedSelector.kill();
  2857. records.kill();
  2858. indices.kill();
  2859. selector.set(rootSelector);
  2860. beginRecord(rootRecord);
  2861. ifblockDepth = 0;
  2862. nestingDepth = 0;
  2863. return doNext();
  2864. }
  2865. bool RecordSelectIterator::next()
  2866. {
  2867. return doNext();
  2868. }
  2869. bool RecordSelectIterator::isValid()
  2870. {
  2871. return (curSelector != NULL);
  2872. }
  2873. bool RecordSelectIterator::isInsideIfBlock()
  2874. {
  2875. return ifblockDepth > 0;
  2876. }
  2877. IHqlExpression * RecordSelectIterator::get()
  2878. {
  2879. return LINK(curSelector);
  2880. }
  2881. IHqlExpression * RecordSelectIterator::query()
  2882. {
  2883. return curSelector;
  2884. }
  2885. //---------------------------------------------------------------------------
  2886. unsigned countTotalFields(IHqlExpression * record, bool includeVirtual)
  2887. {
  2888. unsigned count = 0;
  2889. ForEachChild(i, record)
  2890. {
  2891. IHqlExpression * expr = record->queryChild(i);
  2892. switch (expr->getOperator())
  2893. {
  2894. case no_record:
  2895. count += countTotalFields(expr, includeVirtual);
  2896. break;
  2897. case no_ifblock:
  2898. count += countTotalFields(expr->queryChild(1), includeVirtual);
  2899. break;
  2900. case no_field:
  2901. switch (expr->queryType()->getTypeCode())
  2902. {
  2903. case type_record:
  2904. throwUnexpected();
  2905. case type_row:
  2906. count += countTotalFields(expr->queryRecord(), includeVirtual);
  2907. break;
  2908. default:
  2909. if (includeVirtual || !expr->hasAttribute(virtualAtom))
  2910. count++;
  2911. break;
  2912. }
  2913. break;
  2914. }
  2915. }
  2916. return count;
  2917. }
  2918. bool transformContainsSkip(IHqlExpression * transform)
  2919. {
  2920. return containsSkip(transform);
  2921. }
  2922. bool transformListContainsSkip(IHqlExpression * transforms)
  2923. {
  2924. ForEachChild(i, transforms)
  2925. {
  2926. if (transformContainsSkip(transforms->queryChild(i)))
  2927. return true;
  2928. }
  2929. return false;
  2930. }
  2931. IHqlExpression * queryNextRecordField(IHqlExpression * record, unsigned & idx)
  2932. {
  2933. for (;;)
  2934. {
  2935. IHqlExpression * cur = record->queryChild(idx++);
  2936. if (!cur || cur->getOperator() == no_field)
  2937. return cur;
  2938. }
  2939. }
  2940. IHqlExpression * ensureTransformType(IHqlExpression * transform, node_operator op)
  2941. {
  2942. if (transform->getOperator() == op)
  2943. return LINK(transform);
  2944. if (transform->getOperator() == no_call)
  2945. return LINK(transform); // This needs handling some other way!
  2946. HqlExprArray args;
  2947. unwindChildren(args, transform);
  2948. return createValue(op, transform->getType(), args);
  2949. }
  2950. //---------------------------------------------------------------------------
  2951. //NB: This needs to be kept in sync with the capabilities of the code generator.
  2952. extern HQL_API IHqlExpression * queryInvalidCsvRecordField(IHqlExpression * expr)
  2953. {
  2954. switch (expr->getOperator())
  2955. {
  2956. case no_ifblock:
  2957. return queryInvalidCsvRecordField(expr->queryChild(1));
  2958. case no_record:
  2959. {
  2960. ForEachChild(i, expr)
  2961. {
  2962. IHqlExpression * invalid = queryInvalidCsvRecordField(expr->queryChild(i));
  2963. if (invalid)
  2964. return invalid;
  2965. }
  2966. return NULL;
  2967. }
  2968. case no_field:
  2969. {
  2970. ITypeInfo * type = expr->queryType();
  2971. switch (type->getTypeCode())
  2972. {
  2973. case type_row:
  2974. return queryInvalidCsvRecordField(expr->queryRecord());
  2975. case type_table:
  2976. case type_groupedtable:
  2977. case type_set:
  2978. return expr;
  2979. default:
  2980. return NULL;
  2981. }
  2982. }
  2983. }
  2984. return NULL;
  2985. }
  2986. bool isValidCsvRecord(IHqlExpression * expr)
  2987. {
  2988. return queryInvalidCsvRecordField(expr) == NULL;
  2989. }
  2990. bool isValidXmlRecord(IHqlExpression * expr)
  2991. {
  2992. return true;
  2993. }
  2994. static void expandHintValue(StringBuffer & s, IHqlExpression * expr)
  2995. {
  2996. node_operator op = expr->getOperator();
  2997. node_operator childOp = no_none;
  2998. switch (op)
  2999. {
  3000. case no_constant:
  3001. expr->queryValue()->getStringValue(s);
  3002. break;
  3003. case no_comma:
  3004. expandHintValue(s, expr->queryChild(0));
  3005. expandHintValue(s.append(","), expr->queryChild(1));
  3006. break;
  3007. case no_range:
  3008. expandHintValue(s, expr->queryChild(0));
  3009. expandHintValue(s.append(".."), expr->queryChild(1));
  3010. break;
  3011. case no_rangefrom:
  3012. expandHintValue(s, expr->queryChild(0));
  3013. s.append("..");
  3014. break;
  3015. case no_rangeto:
  3016. expandHintValue(s.append(".."), expr->queryChild(0));
  3017. break;
  3018. case no_list:
  3019. {
  3020. s.append("[");
  3021. ForEachChild(i, expr)
  3022. {
  3023. if (i)
  3024. s.append(",");
  3025. expandHintValue(s, expr->queryChild(i));
  3026. }
  3027. s.append("]");
  3028. break;
  3029. }
  3030. case no_attr:
  3031. s.append(expr->queryName());
  3032. break;
  3033. default:
  3034. s.append("?");
  3035. break;
  3036. }
  3037. }
  3038. void getHintNameValue(IHqlExpression * attr, StringBuffer &name, StringBuffer &value)
  3039. {
  3040. name.set(str(attr->queryName()));
  3041. ForEachChild(i, attr)
  3042. {
  3043. if (i)
  3044. value.append(",");
  3045. expandHintValue(value, attr->queryChild(i));
  3046. }
  3047. if (value.length() == 0)
  3048. value.append("1");
  3049. }
  3050. bool getBoolValue(IHqlExpression * expr, bool dft)
  3051. {
  3052. if (expr)
  3053. {
  3054. if (expr->getOperator() == no_translated)
  3055. expr = expr->queryChild(0);
  3056. IValue * value = expr->queryValue();
  3057. if (value)
  3058. return value->getBoolValue();
  3059. }
  3060. return dft;
  3061. }
  3062. __int64 getIntValue(IHqlExpression * expr, __int64 dft)
  3063. {
  3064. if (expr)
  3065. {
  3066. if (expr->getOperator() == no_translated)
  3067. expr = expr->queryChild(0);
  3068. IValue * value = expr->queryValue();
  3069. if (value)
  3070. return value->getIntValue();
  3071. }
  3072. return dft;
  3073. }
  3074. StringBuffer & getStringValue(StringBuffer & out, IHqlExpression * expr, const char * dft, bool utf8)
  3075. {
  3076. if (expr)
  3077. {
  3078. if (expr->getOperator() == no_translated)
  3079. expr = expr->queryChild(0);
  3080. IValue * value = expr->queryValue();
  3081. if (value)
  3082. {
  3083. if (utf8)
  3084. value->getUTF8Value(out);
  3085. else
  3086. value->getStringValue(out);
  3087. return out;
  3088. }
  3089. }
  3090. if (dft)
  3091. out.append(dft);
  3092. return out;
  3093. }
  3094. StringBuffer & getStringValue(StringBuffer & out, IHqlExpression * expr, const char * dft)
  3095. {
  3096. return getStringValue(out, expr, dft, false);
  3097. }
  3098. StringBuffer & getUTF8Value(StringBuffer & out, IHqlExpression * expr, const char * dft)
  3099. {
  3100. return getStringValue(out, expr, dft, true);
  3101. }
  3102. bool matchesConstantValue(IHqlExpression * expr, __int64 test)
  3103. {
  3104. if (!expr) return false;
  3105. if (expr->getOperator() == no_translated)
  3106. expr = expr->queryChild(0);
  3107. IValue * value = expr->queryValue();
  3108. return value && value->queryType()->isInteger() && (value->getIntValue() == test);
  3109. }
  3110. bool matchesBoolean(IHqlExpression * expr, bool test)
  3111. {
  3112. if (!expr) return false;
  3113. if (expr->getOperator() == no_translated)
  3114. expr = expr->queryChild(0);
  3115. IValue * value = expr->queryValue();
  3116. return value && value->queryType()->getTypeCode() == type_boolean && (value->getBoolValue() == test);
  3117. }
  3118. bool matchesConstantString(IHqlExpression * expr, const char * text, bool ignoreCase)
  3119. {
  3120. if (!expr) return false;
  3121. if (expr->getOperator() == no_translated)
  3122. expr = expr->queryChild(0);
  3123. IValue * value = expr->queryValue();
  3124. if (!value || !isStringType(value->queryType()))
  3125. return false;
  3126. //Would be more efficient to compare directly, but would need to handle all the variants
  3127. StringBuffer temp;
  3128. value->getStringValue(temp);
  3129. if (ignoreCase)
  3130. return stricmp(temp.str(), text) == 0;
  3131. return strcmp(temp.str(), text) == 0;
  3132. }
  3133. bool isEmptyList(IHqlExpression * expr)
  3134. {
  3135. switch (expr->getOperator())
  3136. {
  3137. case no_null:
  3138. return true;
  3139. case no_list:
  3140. case no_datasetlist:
  3141. return (expr->numChildren() == 0);
  3142. default:
  3143. return false;
  3144. }
  3145. }
  3146. bool recordContainsNestedRow(IHqlExpression * record)
  3147. {
  3148. ForEachChild(i, record)
  3149. {
  3150. IHqlExpression * cur = record->queryChild(i);
  3151. switch (cur->getOperator())
  3152. {
  3153. case no_record:
  3154. if (recordContainsNestedRow(cur))
  3155. return true;
  3156. break;
  3157. case no_ifblock:
  3158. if (recordContainsNestedRow(cur->queryChild(1)))
  3159. return true;
  3160. break;
  3161. case no_field:
  3162. if (cur->queryType()->getTypeCode() == type_row)
  3163. return true;
  3164. break;
  3165. }
  3166. }
  3167. return false;
  3168. }
  3169. //Is this a select of the form a.b.c where only a is active, and b,c are datasets.
  3170. //If a is a row e.g., ds[1] and b is a record field then not true.
  3171. IHqlExpression * queryNextMultiLevelDataset(IHqlExpression * expr, bool followActiveSelectors)
  3172. {
  3173. while (expr->isDatarow())
  3174. {
  3175. switch (expr->getOperator())
  3176. {
  3177. case no_select:
  3178. case no_selectnth:
  3179. expr = expr->queryChild(0);
  3180. break;
  3181. default:
  3182. return NULL;
  3183. }
  3184. }
  3185. IHqlExpression * root = queryRoot(expr);
  3186. if (!root || (root->getOperator() != no_select))
  3187. return NULL;
  3188. if (!followActiveSelectors && !isNewSelector(root))
  3189. return NULL;
  3190. IHqlExpression * ds = root->queryChild(0);
  3191. for (;;)
  3192. {
  3193. if (ds->isDataset())
  3194. return ds;
  3195. if (ds->getOperator() != no_select)
  3196. return NULL;
  3197. ds = ds->queryChild(0);
  3198. }
  3199. }
  3200. bool isMultiLevelDatasetSelector(IHqlExpression * expr, bool followActiveSelectors)
  3201. {
  3202. return queryNextMultiLevelDataset(expr, followActiveSelectors) != NULL;
  3203. }
  3204. IHqlExpression * getInverse(IHqlExpression * op)
  3205. {
  3206. node_operator opKind = op->getOperator();
  3207. if (opKind == no_not)
  3208. {
  3209. IHqlExpression * arg0 = op->queryChild(0);
  3210. if (arg0->isBoolean())
  3211. return LINK(arg0);
  3212. }
  3213. if (opKind == no_constant)
  3214. return createConstant(!op->queryValue()->getBoolValue());
  3215. if (opKind == no_alias_scope)
  3216. {
  3217. HqlExprArray args;
  3218. args.append(*getInverse(op->queryChild(0)));
  3219. unwindChildren(args, op, 1);
  3220. return op->clone(args);
  3221. }
  3222. node_operator inv = getInverseOp(opKind);
  3223. if (inv)
  3224. {
  3225. IHqlExpression * value = createOpenValue(inv, op->getType());
  3226. ForEachChild(i, op)
  3227. value->addOperand(LINK(op->queryChild(i)));
  3228. return value->closeExpr();
  3229. }
  3230. switch (opKind)
  3231. {
  3232. case no_if:
  3233. return createBoolExpr(no_if, LINK(op->queryChild(0)), getInverse(op->queryChild(1)), getInverse(op->queryChild(2)));
  3234. }
  3235. Owned<ITypeInfo> boolType = makeBoolType();
  3236. return createValue(no_not, LINK(boolType), ensureExprType(op, boolType));
  3237. }
  3238. IHqlExpression * getNormalizedCondition(IHqlExpression * expr)
  3239. {
  3240. if (expr->getOperator() == no_not)
  3241. return getInverse(expr->queryChild(0)->queryBody());
  3242. return LINK(expr->queryBody());
  3243. }
  3244. bool areInverseExprs(IHqlExpression * left, IHqlExpression* right)
  3245. {
  3246. if (left->getOperator() == no_not)
  3247. return left->queryChild(0)->queryBody() == right->queryBody();
  3248. if (right->getOperator() == no_not)
  3249. return right->queryChild(0)->queryBody() == left->queryBody();
  3250. node_operator leftOp = left->getOperator();
  3251. node_operator rightOp = right->getOperator();
  3252. if (leftOp != rightOp)
  3253. {
  3254. if (getInverseOp(leftOp) != rightOp)
  3255. return false;
  3256. }
  3257. OwnedHqlExpr inverseLeft = getInverse(left->queryBody());
  3258. return inverseLeft->queryBody() == right->queryBody();
  3259. }
  3260. IHqlExpression * getNegative(IHqlExpression * expr)
  3261. {
  3262. IValue * value = expr->queryValue();
  3263. if (value && isNumericType(value->queryType()))
  3264. return createConstant(negateValue(value));
  3265. if (expr->getOperator() == no_negate)
  3266. return LINK(expr->queryChild(0));
  3267. return createValue(no_negate, expr->getType(), LINK(expr));
  3268. }
  3269. bool isCompoundSource(IHqlExpression * expr)
  3270. {
  3271. switch (expr->getOperator())
  3272. {
  3273. case no_compound_diskread:
  3274. case no_compound_disknormalize:
  3275. case no_compound_diskaggregate:
  3276. case no_compound_diskcount:
  3277. case no_compound_diskgroupaggregate:
  3278. case no_compound_indexread:
  3279. case no_compound_indexnormalize:
  3280. case no_compound_indexaggregate:
  3281. case no_compound_indexcount:
  3282. case no_compound_indexgroupaggregate:
  3283. case no_compound_childread:
  3284. case no_compound_childnormalize:
  3285. case no_compound_childaggregate:
  3286. case no_compound_childcount:
  3287. case no_compound_childgroupaggregate:
  3288. case no_compound_inline:
  3289. return true;
  3290. }
  3291. return false;
  3292. }
  3293. static void convertRecordToAssigns(HqlExprArray & assigns, IHqlExpression * record, IHqlExpression * targetSelector, bool canOmit)
  3294. {
  3295. ForEachChild(idx, record)
  3296. {
  3297. IHqlExpression * cur = record->queryChild(idx);
  3298. switch (cur->getOperator())
  3299. {
  3300. case no_record:
  3301. convertRecordToAssigns(assigns, cur, targetSelector, canOmit);
  3302. break;
  3303. case no_ifblock:
  3304. convertRecordToAssigns(assigns, cur->queryChild(1), targetSelector, canOmit);
  3305. break;
  3306. case no_field:
  3307. {
  3308. IHqlExpression * fieldRecord = cur->queryRecord();
  3309. IHqlExpression * value = queryRealChild(cur, 0);
  3310. OwnedHqlExpr newTargetSelector = createSelectExpr(LINK(targetSelector), LINK(cur));
  3311. if (fieldRecord && !cur->isDataset() && !value)
  3312. {
  3313. //convertRecordToAssigns(assigns, cur->queryRecord(), newTargetSelector, canOmit);
  3314. IHqlExpression * transform = convertRecordToTransform(fieldRecord, canOmit);
  3315. IHqlExpression * newValue = createRow(no_createrow, transform);
  3316. assigns.append(*createAssign(LINK(newTargetSelector), newValue));
  3317. }
  3318. else
  3319. {
  3320. if (!value && !canOmit)
  3321. throwError1(HQLERR_FieldHasNoDefaultValue, str(cur->queryId()));
  3322. if (value)
  3323. assigns.append(*createAssign(LINK(newTargetSelector), LINK(value)));
  3324. }
  3325. break;
  3326. }
  3327. }
  3328. }
  3329. }
  3330. IHqlExpression * convertRecordToTransform(IHqlExpression * record, bool canOmit)
  3331. {
  3332. HqlExprArray assigns;
  3333. OwnedHqlExpr self = getSelf(record);
  3334. convertRecordToAssigns(assigns, record, self, canOmit);
  3335. return createValue(no_transform, makeTransformType(record->getType()), assigns);
  3336. }
  3337. IHqlExpression * createTransformForField(IHqlExpression * field, IHqlExpression * value)
  3338. {
  3339. OwnedHqlExpr record = createRecord(field);
  3340. OwnedHqlExpr self = getSelf(record);
  3341. OwnedHqlExpr target = createSelectExpr(LINK(self), LINK(field));
  3342. OwnedHqlExpr assign = createAssign(LINK(target), LINK(value));
  3343. return createValue(no_transform, makeTransformType(record->getType()), assign.getClear());
  3344. }
  3345. IHqlExpression * convertScalarToRow(IHqlExpression * value, ITypeInfo * fieldType)
  3346. {
  3347. if (!fieldType)
  3348. fieldType = value->queryType();
  3349. OwnedHqlExpr field = createField(unnamedId, LINK(fieldType), NULL, NULL);
  3350. OwnedHqlExpr record = createRecord(field);
  3351. OwnedHqlExpr dataset;
  3352. OwnedHqlExpr attribute;
  3353. if (splitResultValue(dataset, attribute, value))
  3354. {
  3355. OwnedHqlExpr transform = createTransformForField(field, attribute);
  3356. OwnedHqlExpr ds = createDataset(no_newusertable, LINK(dataset), createComma(LINK(record), LINK(transform)));
  3357. return createRow(no_selectnth, LINK(ds), getSizetConstant(1));
  3358. }
  3359. OwnedHqlExpr transform = createTransformForField(field, value);
  3360. return createRow(no_createrow, transform.getClear());
  3361. }
  3362. inline bool isScheduleAction(IHqlExpression * expr)
  3363. {
  3364. switch (expr->getOperator())
  3365. {
  3366. case no_when:
  3367. case no_priority:
  3368. return true;
  3369. }
  3370. return false;
  3371. }
  3372. bool workflowContainsSchedule(IHqlExpression * colonExpr)
  3373. {
  3374. HqlExprArray actions;
  3375. colonExpr->queryChild(1)->unwindList(actions, no_comma);
  3376. ForEachItemIn(i, actions)
  3377. if (isScheduleAction(&actions.item(i)))
  3378. return true;
  3379. return false;
  3380. }
  3381. bool workflowContainsNonSchedule(IHqlExpression * colonExpr)
  3382. {
  3383. HqlExprArray actions;
  3384. colonExpr->queryChild(1)->unwindList(actions, no_comma);
  3385. ForEachItemIn(i, actions)
  3386. if (!isScheduleAction(&actions.item(i)))
  3387. return true;
  3388. return false;
  3389. }
  3390. bool isUngroup(IHqlExpression * expr)
  3391. {
  3392. return (expr->getOperator() == no_group) && !queryRealChild(expr, 1);
  3393. }
  3394. void unwindFilterConditions(HqlExprArray & conds, IHqlExpression * expr)
  3395. {
  3396. unsigned max = expr->numChildren();
  3397. for (unsigned idx=1; idx < max; idx++)
  3398. {
  3399. IHqlExpression * cur = queryRealChild(expr, idx);
  3400. if (cur)
  3401. cur->unwindList(conds, no_and);
  3402. }
  3403. }
  3404. unsigned getBestLengthEstimate(IHqlExpression * expr)
  3405. {
  3406. ITypeInfo * exprType = expr->queryType();
  3407. unsigned len = exprType->getStringLen();
  3408. if (len != UNKNOWN_LENGTH)
  3409. return len;
  3410. switch (expr->getOperator())
  3411. {
  3412. case no_cast:
  3413. case no_implicitcast:
  3414. if ((isStringType(exprType) || isUnicodeType(exprType)))
  3415. {
  3416. IHqlExpression * uncast = expr->queryChild(0);
  3417. ITypeInfo * uncastType = uncast->queryType();
  3418. if ((uncastType->getSize() != UNKNOWN_LENGTH) && (isStringType(uncastType) || isUnicodeType(uncastType)))
  3419. return uncastType->getStringLen();
  3420. }
  3421. break;
  3422. }
  3423. return len;
  3424. }
  3425. //---------------------------------------------------------------------------
  3426. SubStringHelper::SubStringHelper(IHqlExpression * expr)
  3427. {
  3428. init(expr->queryChild(0), expr->queryChild(1));
  3429. }
  3430. SubStringHelper::SubStringHelper(IHqlExpression * _src, IHqlExpression * range)
  3431. {
  3432. init(_src, range);
  3433. }
  3434. void SubStringHelper::init(IHqlExpression * _src, IHqlExpression * range)
  3435. {
  3436. special = false;
  3437. infiniteString = false;
  3438. from = NULL;
  3439. to = NULL;
  3440. src = _src;
  3441. srcType = src->queryType();
  3442. unsigned strSize = getBestLengthEstimate(src);
  3443. switch (range->getOperator())
  3444. {
  3445. case no_range:
  3446. from = range->queryChild(0);
  3447. to = range->queryChild(1);
  3448. break;
  3449. case no_rangeto:
  3450. to = range->queryChild(0);
  3451. break;
  3452. case no_rangefrom:
  3453. case no_rangecommon:
  3454. from = range->queryChild(0);
  3455. break;
  3456. default:
  3457. from = range;
  3458. to = range;
  3459. break;
  3460. }
  3461. if (from)
  3462. {
  3463. IValue * startValue = from->queryValue();
  3464. if (startValue)
  3465. {
  3466. fixedStart = (unsigned)startValue->getIntValue();
  3467. if ((int)fixedStart <= 0)
  3468. fixedStart = 1;
  3469. }
  3470. else
  3471. fixedStart = UNKNOWN_LENGTH;
  3472. }
  3473. else
  3474. fixedStart = 1;
  3475. if (to)
  3476. {
  3477. IValue * endValue = to->queryValue();
  3478. if (endValue)
  3479. {
  3480. fixedEnd = (unsigned)endValue->getIntValue();
  3481. if ((int)fixedEnd <= 0)
  3482. fixedEnd = 1;
  3483. if (knownStart() && fixedEnd < fixedStart)
  3484. fixedEnd = fixedStart-1;
  3485. }
  3486. else
  3487. fixedEnd = UNKNOWN_LENGTH;
  3488. }
  3489. else
  3490. fixedEnd = strSize;
  3491. bool isStringOrData = false;
  3492. switch (srcType->getTypeCode())
  3493. {
  3494. case type_string:
  3495. case type_data:
  3496. case type_unicode:
  3497. isStringOrData = true;
  3498. break;
  3499. }
  3500. bool isUnicode = srcType->getTypeCode() == type_unicode;
  3501. if (isStringOrData)
  3502. {
  3503. if (srcType->getSize() == UNKNOWN_LENGTH)
  3504. {
  3505. if ((src->getOperator() == no_cast) || (src->getOperator() == no_implicitcast))
  3506. {
  3507. ITypeInfo * childType = src->queryChild(0)->queryType();
  3508. type_t childTC = childType->getTypeCode();
  3509. type_t srcTC = srcType->getTypeCode();
  3510. switch (childType->getTypeCode())
  3511. {
  3512. case type_string:
  3513. case type_data:
  3514. if ((srcTC == type_data) || (childTC == type_data) || (srcType->queryCharset() == childType->queryCharset()))
  3515. {
  3516. src = src->queryChild(0);
  3517. srcType = childType;
  3518. }
  3519. break;
  3520. case type_unicode:
  3521. if(isUnicode && (srcType->queryLocale() == childType->queryLocale()))
  3522. {
  3523. src = src->queryChild(0);
  3524. srcType = childType;
  3525. }
  3526. break;
  3527. }
  3528. }
  3529. }
  3530. if (srcType->getSize() != UNKNOWN_LENGTH)
  3531. if (knownStart() && knownEnd())
  3532. special = true;
  3533. }
  3534. if (isStringOrData && srcType->getSize() == INFINITE_LENGTH)
  3535. infiniteString = true;
  3536. }
  3537. void unwindFields(HqlExprArray & fields, IHqlExpression * record)
  3538. {
  3539. ForEachChild(i, record)
  3540. {
  3541. IHqlExpression * cur = record->queryChild(i);
  3542. switch (cur->getOperator())
  3543. {
  3544. case no_record:
  3545. unwindFields(fields, cur);
  3546. break;
  3547. case no_ifblock:
  3548. unwindFields(fields, cur->queryChild(1));
  3549. break;
  3550. case no_field:
  3551. fields.append(*LINK(cur));
  3552. break;
  3553. }
  3554. }
  3555. }
  3556. void unwindFields(HqlExprCopyArray & fields, IHqlExpression * record)
  3557. {
  3558. ForEachChild(i, record)
  3559. {
  3560. IHqlExpression * cur = record->queryChild(i);
  3561. switch (cur->getOperator())
  3562. {
  3563. case no_record:
  3564. unwindFields(fields, cur);
  3565. break;
  3566. case no_ifblock:
  3567. unwindFields(fields, cur->queryChild(1));
  3568. break;
  3569. case no_field:
  3570. fields.append(*LINK(cur));
  3571. break;
  3572. }
  3573. }
  3574. }
  3575. unsigned numAttributes(const HqlExprArray & args)
  3576. {
  3577. unsigned cnt = 0;
  3578. ForEachItemIn(i, args)
  3579. if (args.item(i).isAttribute())
  3580. cnt++;
  3581. return cnt;
  3582. }
  3583. unsigned numAttributes(const IHqlExpression * expr)
  3584. {
  3585. unsigned cnt = 0;
  3586. ForEachChild(i, expr)
  3587. if (expr->queryChild(i)->isAttribute())
  3588. cnt++;
  3589. return cnt;
  3590. }
  3591. IHqlExpression * createGetResultFromSetResult(IHqlExpression * setResult, ITypeInfo * type)
  3592. {
  3593. IHqlExpression * seqAttr = setResult->queryAttribute(sequenceAtom);
  3594. IHqlExpression * aliasAttr = setResult->queryAttribute(namedAtom);
  3595. Linked<ITypeInfo> valueType = type;
  3596. if (!valueType)
  3597. {
  3598. IHqlExpression * value;
  3599. if (setResult->getOperator() == no_extractresult)
  3600. value = setResult->queryChild(1);
  3601. else
  3602. value = setResult->queryChild(0);
  3603. valueType.setown(value->getType());
  3604. }
  3605. switch (valueType->getTypeCode())
  3606. {
  3607. case type_table:
  3608. return createDataset(no_getresult, LINK(queryOriginalRecord(valueType)), createComma(LINK(seqAttr), LINK(aliasAttr)));
  3609. case type_groupedtable:
  3610. return createDataset(no_getresult, LINK(queryOriginalRecord(valueType)), createComma(LINK(seqAttr), createAttribute(groupedAtom), LINK(aliasAttr)));
  3611. case type_dictionary:
  3612. return createDictionary(no_workunit_dataset, LINK(queryOriginalRecord(valueType)), createComma(LINK(seqAttr), LINK(aliasAttr)));
  3613. case type_row:
  3614. case type_record:
  3615. return createRow(no_getresult, LINK(queryOriginalRecord(valueType)), createComma(LINK(seqAttr), LINK(aliasAttr)));
  3616. }
  3617. return createValue(no_getresult, valueType.getLink(), LINK(seqAttr), LINK(aliasAttr));
  3618. }
  3619. //---------------------------------------------------------------------------------------------------------------------
  3620. IHqlExpression * convertScalarToGraphResult(IHqlExpression * value, ITypeInfo * fieldType, IHqlExpression * represents, unsigned seq)
  3621. {
  3622. OwnedHqlExpr row = convertScalarToRow(value, fieldType);
  3623. OwnedHqlExpr ds = createDatasetFromRow(LINK(row));
  3624. HqlExprArray args;
  3625. args.append(*LINK(ds));
  3626. args.append(*LINK(represents));
  3627. args.append(*getSizetConstant(seq));
  3628. args.append(*createAttribute(rowAtom));
  3629. return createValue(no_setgraphresult, makeVoidType(), args);
  3630. }
  3631. IHqlExpression * createScalarFromGraphResult(ITypeInfo * scalarType, ITypeInfo * fieldType, IHqlExpression * represents, unsigned seq)
  3632. {
  3633. OwnedHqlExpr counterField = createField(unnamedId, LINK(fieldType), NULL, NULL);
  3634. OwnedHqlExpr counterRecord = createRecord(counterField);
  3635. HqlExprArray args;
  3636. args.append(*LINK(counterRecord));
  3637. args.append(*LINK(represents));
  3638. args.append(*getSizetConstant(seq));
  3639. args.append(*createAttribute(rowAtom));
  3640. OwnedHqlExpr counterResult = createRow(no_getgraphresult, args);
  3641. OwnedHqlExpr select = createNewSelectExpr(LINK(counterResult), LINK(counterField));
  3642. return ensureExprType(select, scalarType);
  3643. }
  3644. IAtom * queryCsvEncoding(IHqlExpression * mode)
  3645. {
  3646. if (mode)
  3647. {
  3648. if (mode->queryAttribute(asciiAtom))
  3649. return asciiAtom;
  3650. if (mode->queryAttribute(ebcdicAtom))
  3651. return ebcdicAtom;
  3652. if (mode->queryAttribute(unicodeAtom))
  3653. return unicodeAtom;
  3654. }
  3655. return NULL;
  3656. }
  3657. IAtom * queryCsvTableEncoding(IHqlExpression * tableExpr)
  3658. {
  3659. if (!tableExpr)
  3660. return NULL;
  3661. IHqlExpression * mode = tableExpr->queryChild(2);
  3662. assertex(mode->getOperator() == no_csv);
  3663. return queryCsvEncoding(mode);
  3664. }
  3665. IHqlExpression * createTrimExpr(IHqlExpression * value, IHqlExpression * flags)
  3666. {
  3667. LinkedHqlExpr expr = value;
  3668. ITypeInfo * exprType = expr->queryType()->queryPromotedType();
  3669. if (!isSimpleStringType(exprType) && !isUnicodeType(exprType))
  3670. {
  3671. unsigned strLen = isStringType(exprType) ? exprType->getStringLen() : UNKNOWN_LENGTH;
  3672. Owned<ITypeInfo> type = makeStringType(strLen, NULL, NULL);
  3673. expr.setown(ensureExprType(expr, type));
  3674. }
  3675. ITypeInfo * srcType = expr->queryType();
  3676. ITypeInfo * tgtType;
  3677. if (srcType->getTypeCode() == type_utf8)
  3678. tgtType = makeUtf8Type(UNKNOWN_LENGTH, srcType->queryLocale());
  3679. else if (isUnicodeType(srcType))
  3680. tgtType = makeUnicodeType(UNKNOWN_LENGTH, srcType->queryLocale());
  3681. else
  3682. tgtType = makeStringType(UNKNOWN_LENGTH, getCharset(asciiAtom), getCollation(asciiAtom));
  3683. HqlExprArray args;
  3684. args.append(*LINK(expr));
  3685. if (flags)
  3686. flags->unwindList(args, no_comma);
  3687. return createValue(no_trim, tgtType, args);
  3688. }
  3689. bool isRightTrim(IHqlExpression * expr)
  3690. {
  3691. if (expr->getOperator() != no_trim)
  3692. return false;
  3693. if (expr->hasAttribute(leftAtom) || expr->hasAttribute(allAtom))
  3694. return false;
  3695. return true;
  3696. }
  3697. bool isOpRedundantForCompare(IHqlExpression * expr)
  3698. {
  3699. if (isRightTrim(expr))
  3700. {
  3701. ITypeInfo * baseType = expr->queryChild(0)->queryType();
  3702. if (baseType->getTypeCode() == type_data)
  3703. return false;
  3704. return true;
  3705. }
  3706. return false;
  3707. }
  3708. bool isLengthPreservingCast(IHqlExpression * expr)
  3709. {
  3710. if (!isCast(expr))
  3711. return false;
  3712. ITypeInfo * type = expr->queryType();
  3713. ITypeInfo * baseType = expr->queryChild(0)->queryType();
  3714. if ((isStringType(type) || isUnicodeType(type)) &&
  3715. (isStringType(baseType) || isUnicodeType(baseType)))
  3716. {
  3717. if (type->getStringLen() == baseType->getStringLen())
  3718. return true;
  3719. }
  3720. return false;
  3721. }
  3722. static void createDefaultTransformAssigns(HqlExprArray & args, IHqlExpression * self, IHqlExpression * right, IHqlExpression * record)
  3723. {
  3724. ForEachChild(i, record)
  3725. {
  3726. IHqlExpression * cur = record->queryChild(i);
  3727. switch (cur->getOperator())
  3728. {
  3729. case no_record:
  3730. createDefaultTransformAssigns(args, self, right, cur);
  3731. break;
  3732. case no_ifblock:
  3733. createDefaultTransformAssigns(args, self, right, cur->queryChild(1));
  3734. break;
  3735. case no_field:
  3736. {
  3737. IHqlExpression * target = createSelectExpr(LINK(self), LINK(cur));
  3738. IHqlExpression * value;
  3739. if (right)
  3740. value = createSelectExpr(LINK(right), LINK(cur));
  3741. else
  3742. value = createNullExpr(cur);
  3743. args.append(*createAssign(target, value));
  3744. break;
  3745. }
  3746. }
  3747. }
  3748. }
  3749. IHqlExpression * createTransformFromRow(IHqlExpression * expr)
  3750. {
  3751. IHqlExpression * record = expr->queryRecord();
  3752. OwnedHqlExpr self = createSelector(no_self, record, NULL);
  3753. HqlExprArray args;
  3754. createDefaultTransformAssigns(args, self, expr, record);
  3755. return createValue(no_transform, makeTransformType(record->getType()), args);
  3756. }
  3757. IHqlExpression * createNullTransform(IHqlExpression * record)
  3758. {
  3759. OwnedHqlExpr self = createSelector(no_self, record, NULL);
  3760. HqlExprArray args;
  3761. createDefaultTransformAssigns(args, self, NULL, record);
  3762. return createValue(no_transform, makeTransformType(record->getType()), args);
  3763. }
  3764. static bool foundDifference()
  3765. {
  3766. return false;
  3767. }
  3768. bool debugFindFirstDifference(IHqlExpression * left, IHqlExpression * right)
  3769. {
  3770. if (left == right)
  3771. return true;
  3772. if (!left || !right)
  3773. return foundDifference();
  3774. if (left->queryBody() == right->queryBody())
  3775. {
  3776. if ((left->getOperator() == no_call) && (right->getOperator() == no_call))
  3777. {
  3778. IHqlExpression * leftDefinition = left->queryDefinition();
  3779. IHqlExpression * rightDefinition = right->queryDefinition();
  3780. if ((left != leftDefinition) || (right != rightDefinition))
  3781. {
  3782. if (debugFindFirstDifference(left->queryDefinition(), right->queryDefinition()))
  3783. return false;
  3784. }
  3785. return foundDifference(); // break point here.
  3786. }
  3787. IHqlExpression * leftBody = left->queryBody(true);
  3788. IHqlExpression * rightBody = right->queryBody(true);
  3789. annotate_kind leftAK = left->getAnnotationKind();
  3790. annotate_kind rightAK = right->getAnnotationKind();
  3791. if (leftBody != rightBody)
  3792. {
  3793. if ((left == leftBody) || (right == rightBody))
  3794. return foundDifference(); // one side has an annotation, the other doesn't
  3795. return debugFindFirstDifference(leftBody, rightBody);
  3796. }
  3797. if (leftAK != rightAK)
  3798. return foundDifference(); // different annotation
  3799. return foundDifference(); // some difference in the annotation details
  3800. }
  3801. if (left->getOperator() != right->getOperator())
  3802. return foundDifference();
  3803. if (left->queryName() != right->queryName())
  3804. return foundDifference();
  3805. ForEachChild(i, left)
  3806. {
  3807. if (!debugFindFirstDifference(left->queryChild(i), right->queryChild(i)))
  3808. return false;
  3809. }
  3810. if (left->getOperator() != no_record)
  3811. {
  3812. IHqlExpression * leftRecord = queryOriginalRecord(left);
  3813. IHqlExpression * rightRecord = queryOriginalRecord(right);
  3814. if (leftRecord || rightRecord)
  3815. {
  3816. if (!debugFindFirstDifference(leftRecord, rightRecord))
  3817. return false;
  3818. }
  3819. }
  3820. if (left->queryType() != right->queryType())
  3821. {
  3822. IHqlExpression * lTypeExpr = queryExpression(left->queryType());
  3823. IHqlExpression * rTypeExpr = queryExpression(right->queryType());
  3824. if (((left != lTypeExpr) || (right != rTypeExpr)) &&
  3825. (lTypeExpr && rTypeExpr && lTypeExpr != rTypeExpr))
  3826. return debugFindFirstDifference(lTypeExpr, rTypeExpr);
  3827. return foundDifference();
  3828. }
  3829. return foundDifference();//something else
  3830. }
  3831. void debugTrackDifference(IHqlExpression * expr)
  3832. {
  3833. static IHqlExpression * prev;
  3834. if (prev && prev != expr)
  3835. debugFindFirstDifference(prev, expr);
  3836. prev = expr;
  3837. }
  3838. //------------------------------------------------------------------------------------------------
  3839. static IHqlExpression * expandConditions(IHqlExpression * expr, DependenciesUsed & dependencies, HqlExprArray & conds, HqlExprArray & values)
  3840. {
  3841. if (expr->getOperator() != no_if)
  3842. return expr;
  3843. IHqlExpression * cond = expr->queryChild(0);
  3844. //don't combine if conditions it it means that extra dependencies will be needed to test the if condition
  3845. //since it may cause unnecessary code to be executed.
  3846. if (conds.ordinality() == 0)
  3847. gatherDependencies(cond, dependencies, GatherAllResultRead);
  3848. else
  3849. {
  3850. DependenciesUsed condDependencies(true);
  3851. gatherDependencies(cond, condDependencies, GatherAllResultRead);
  3852. if (!condDependencies.isSubsetOf(dependencies))
  3853. return expr;
  3854. }
  3855. conds.append(*LINK(cond));
  3856. values.append(*LINK(expr->queryChild(1)));
  3857. return expandConditions(expr->queryChild(2), dependencies, conds, values);
  3858. }
  3859. IHqlExpression * combineIfsToMap(IHqlExpression * expr)
  3860. {
  3861. if (expr->isAction())
  3862. return NULL;
  3863. HqlExprArray conds, values;
  3864. DependenciesUsed dependencies(true);
  3865. IHqlExpression * falseExpr = expandConditions(expr, dependencies, conds, values);
  3866. if (conds.ordinality() <= 1)
  3867. return NULL;
  3868. HqlExprArray args;
  3869. ForEachItemIn(i, conds)
  3870. {
  3871. IHqlExpression & curValue = values.item(i);
  3872. args.append(*createValue(no_mapto, curValue.getType(), LINK(&conds.item(i)), LINK(&curValue)));
  3873. }
  3874. args.append(*LINK(falseExpr));
  3875. return createWrapper(no_map, expr->queryType(), args);
  3876. }
  3877. bool castPreservesValueAndOrder(IHqlExpression * expr)
  3878. {
  3879. assertex(isCast(expr));
  3880. IHqlExpression * uncast = expr->queryChild(0);
  3881. ITypeInfo * castType = expr->queryType();
  3882. ITypeInfo * uncastType = uncast->queryType();
  3883. if (castLosesInformation(castType, uncastType))
  3884. return false;
  3885. if (!preservesOrder(castType, uncastType))
  3886. return false;
  3887. return true;
  3888. }
  3889. //------------------------------------------------------------------------------------------------
  3890. class RecordMetaCreator
  3891. {
  3892. public:
  3893. RecordMetaCreator(IMaxSizeCallback * _callback) { callback = _callback; }
  3894. IDefRecordElement * createRecord(IHqlExpression * record, IHqlExpression * self);
  3895. protected:
  3896. IDefRecordElement * createField(IHqlExpression * cur, IHqlExpression * self);
  3897. IDefRecordElement * createIfBlock(IHqlExpression * cur, IHqlExpression * self);
  3898. bool createRecord(IDefRecordBuilder * builder, IHqlExpression * record, IHqlExpression * self);
  3899. protected:
  3900. HqlExprArray selects;
  3901. IDefRecordElementArray created;
  3902. IMaxSizeCallback * callback;
  3903. };
  3904. IDefRecordElement * RecordMetaCreator::createField(IHqlExpression * cur, IHqlExpression * self)
  3905. {
  3906. IHqlExpression * fieldRecord = cur->queryRecord();
  3907. Owned<IDefRecordElement> childDefRecord;
  3908. ITypeInfo * type = cur->queryType();
  3909. Linked<ITypeInfo> defType = type;
  3910. switch (type->getTypeCode())
  3911. {
  3912. case type_row:
  3913. //Backward compatibility!
  3914. defType.setown(makeRecordType());
  3915. childDefRecord.setown(createRecord(fieldRecord, self));
  3916. break;
  3917. case type_table:
  3918. defType.setown(makeTableType(makeRowType(makeRecordType())));
  3919. childDefRecord.setown(::createMetaRecord(fieldRecord, callback));
  3920. break;
  3921. case type_groupedtable:
  3922. {
  3923. ITypeInfo * tableType = makeTableType(makeRowType(makeRecordType()));
  3924. defType.setown(makeGroupedTableType(tableType));
  3925. childDefRecord.setown(::createMetaRecord(fieldRecord, callback));
  3926. break;
  3927. }
  3928. case type_alien:
  3929. case type_any:
  3930. case type_bitfield:
  3931. //MORE: Not Allowed....
  3932. return NULL;
  3933. }
  3934. size32_t maxSize = 0;
  3935. Owned<IDefRecordElement> elem = createDEfield(cur->queryName(), defType, childDefRecord, maxSize);
  3936. if (cur->hasAttribute(blobAtom))
  3937. {
  3938. Owned<ITypeInfo> blobType = makeBlobType();
  3939. return createDEfield(cur->queryName(), blobType, elem, 0);
  3940. }
  3941. return elem.getClear();
  3942. }
  3943. IDefRecordElement * RecordMetaCreator::createIfBlock(IHqlExpression * cur, IHqlExpression * self)
  3944. {
  3945. IHqlExpression * cond = cur->queryChild(0);
  3946. IHqlExpression * select;
  3947. LinkedHqlExpr value;
  3948. switch (cond->getOperator())
  3949. {
  3950. case no_select:
  3951. //ifblock(self.booleanField)
  3952. select = cond;
  3953. value.setown(createConstant(true));
  3954. break;
  3955. case no_eq:
  3956. select = cond->queryChild(0);
  3957. value.set(cond->queryChild(1));
  3958. if (select->getOperator() != no_select)
  3959. return NULL;
  3960. if (value->getOperator() != no_constant)
  3961. return NULL;
  3962. break;
  3963. default:
  3964. return NULL;
  3965. }
  3966. unsigned match = selects.find(*select);
  3967. if (match == NotFound)
  3968. return NULL;
  3969. IDefRecordElement & condField = created.item(match);
  3970. Owned<IDefRecordElement> record = createRecord(cur->queryChild(1), self);
  3971. if (!record)
  3972. return NULL;
  3973. return createDEifblock(&condField, value->queryValue(), record);
  3974. }
  3975. bool RecordMetaCreator::createRecord(IDefRecordBuilder * builder, IHqlExpression * record, IHqlExpression * self)
  3976. {
  3977. ForEachChild(i, record)
  3978. {
  3979. IHqlExpression * cur = record->queryChild(i);
  3980. switch (cur->getOperator())
  3981. {
  3982. case no_record:
  3983. if (!createRecord(builder, cur, self))
  3984. return false;
  3985. break;
  3986. case no_field:
  3987. {
  3988. OwnedHqlExpr selector = createSelectExpr(LINK(self), LINK(cur));
  3989. IDefRecordElement * next = createField(cur, selector);
  3990. if (!next)
  3991. return false;
  3992. builder->addChildOwn(next);
  3993. selects.append(*LINK(selector));
  3994. created.append(*LINK(next));
  3995. break;
  3996. }
  3997. case no_ifblock:
  3998. {
  3999. IDefRecordElement * next = createIfBlock(cur, self);
  4000. if (!next)
  4001. return false;
  4002. builder->addChildOwn(next);
  4003. break;
  4004. }
  4005. default:
  4006. break;
  4007. }
  4008. }
  4009. return true;
  4010. }
  4011. IDefRecordElement * RecordMetaCreator::createRecord(IHqlExpression * record, IHqlExpression * self)
  4012. {
  4013. size32_t maxSize = callback ? callback->getMaxSize(record) : 4096;
  4014. Owned<IDefRecordBuilder> builder = createDErecord(maxSize);
  4015. if (!createRecord(builder, record, self))
  4016. return NULL;
  4017. return builder->close();
  4018. }
  4019. IDefRecordElement * createMetaRecord(IHqlExpression * record, IMaxSizeCallback * callback)
  4020. {
  4021. RecordMetaCreator creator(callback);
  4022. return creator.createRecord(record, querySelfReference());
  4023. }
  4024. static bool doContainsExpression(IHqlExpression * expr, IHqlExpression * search)
  4025. {
  4026. for (;;)
  4027. {
  4028. if (expr->queryTransformExtra())
  4029. return false;
  4030. if (expr == search)
  4031. return true;
  4032. expr->setTransformExtraUnlinked(expr);
  4033. IHqlExpression * body = expr->queryBody(true);
  4034. if (body == expr)
  4035. break;
  4036. expr = body;
  4037. }
  4038. ForEachChild(i, expr)
  4039. {
  4040. if (doContainsExpression(expr->queryChild(i), search))
  4041. return true;
  4042. }
  4043. return false;
  4044. }
  4045. bool containsExpression(IHqlExpression * expr, IHqlExpression * search)
  4046. {
  4047. TransformMutexBlock lock;
  4048. return doContainsExpression(expr, search);
  4049. }
  4050. static bool doContainsOperator(IHqlExpression * expr, node_operator search)
  4051. {
  4052. if (expr->queryTransformExtra())
  4053. return false;
  4054. if (expr->getOperator() == search)
  4055. return true;
  4056. expr->setTransformExtraUnlinked(expr);
  4057. ForEachChild(i, expr)
  4058. {
  4059. if (doContainsOperator(expr->queryChild(i), search))
  4060. return true;
  4061. }
  4062. return false;
  4063. }
  4064. bool containsOperator(IHqlExpression * expr, node_operator search)
  4065. {
  4066. TransformMutexBlock lock;
  4067. return doContainsOperator(expr, search);
  4068. }
  4069. static HqlTransformerInfo annotationRemoverInfo("AnnotationRemover");
  4070. class AnnotationRemover : public NewHqlTransformer
  4071. {
  4072. public:
  4073. AnnotationRemover(IHqlExpression * _searchExpr)
  4074. : NewHqlTransformer(annotationRemoverInfo), searchExpr(_searchExpr)
  4075. {
  4076. }
  4077. virtual IHqlExpression * createTransformed(IHqlExpression * expr)
  4078. {
  4079. if (expr->queryBody() == searchExpr)
  4080. return LINK(searchExpr);
  4081. return NewHqlTransformer::createTransformed(expr);
  4082. }
  4083. protected:
  4084. IHqlExpression * searchExpr;
  4085. };
  4086. IHqlExpression * removeAnnotations(IHqlExpression * expr, IHqlExpression * search)
  4087. {
  4088. AnnotationRemover remover(search);
  4089. return remover.transformRoot(expr);
  4090. }
  4091. bool containsIfBlock(IHqlExpression * record)
  4092. {
  4093. ForEachChild(i, record)
  4094. {
  4095. IHqlExpression * cur = record->queryChild(i);
  4096. switch (cur->getOperator())
  4097. {
  4098. case no_record:
  4099. if (containsIfBlock(cur))
  4100. return true;
  4101. break;
  4102. case no_field:
  4103. if (cur->isDatarow() && containsIfBlock(cur->queryRecord()))
  4104. return true;
  4105. break;
  4106. case no_ifblock:
  4107. return true;
  4108. }
  4109. }
  4110. return false;
  4111. }
  4112. bool canCreateRtlTypeInfo(IHqlExpression * record)
  4113. {
  4114. ForEachChild(i, record)
  4115. {
  4116. IHqlExpression * cur = record->queryChild(i);
  4117. switch (cur->getOperator())
  4118. {
  4119. case no_record:
  4120. if (!canCreateRtlTypeInfo(cur))
  4121. return false;
  4122. break;
  4123. case no_field:
  4124. switch (cur->queryType()->getTypeCode())
  4125. {
  4126. case type_row:
  4127. if (!canCreateRtlTypeInfo(cur->queryRecord()))
  4128. return false;
  4129. break;
  4130. case type_table:
  4131. case type_groupedtable:
  4132. if (cur->hasAttribute(countAtom) || cur->hasAttribute(sizeofAtom))
  4133. return false;
  4134. break;
  4135. case type_alien:
  4136. return false;
  4137. }
  4138. break;
  4139. case no_ifblock:
  4140. return false;
  4141. }
  4142. }
  4143. return true;
  4144. }
  4145. IHqlExpression * getFailCode(IHqlExpression * failExpr)
  4146. {
  4147. IHqlExpression * arg0 = failExpr->queryChild(0);
  4148. if (arg0 && arg0->queryType()->isInteger())
  4149. return LINK(arg0);
  4150. return createConstant(0);
  4151. }
  4152. IHqlExpression * getFailMessage(IHqlExpression * failExpr, bool nullIfOmitted)
  4153. {
  4154. IHqlExpression * arg0 = failExpr->queryChild(0);
  4155. if (arg0)
  4156. {
  4157. if (!arg0->queryType()->isInteger())
  4158. return LINK(arg0);
  4159. IHqlExpression * arg1 = failExpr->queryChild(1);
  4160. if (arg1)
  4161. return LINK(arg1);
  4162. }
  4163. if (nullIfOmitted)
  4164. return NULL;
  4165. return createBlankString();
  4166. }
  4167. int compareAtoms(IInterface * const * pleft, IInterface * const * pright)
  4168. {
  4169. IAtom * left = static_cast<IAtom *>(*pleft);
  4170. IAtom * right = static_cast<IAtom *>(*pright);
  4171. return stricmp(str(left), str(right));
  4172. }
  4173. int compareScopesByName(IHqlScope * left, IHqlScope * right)
  4174. {
  4175. const char * leftName = str(left->queryName());
  4176. const char * rightName = str(right->queryName());
  4177. if (leftName && rightName)
  4178. return stricmp(leftName, rightName);
  4179. if (leftName)
  4180. return +1;
  4181. if (rightName)
  4182. return -1;
  4183. return 0;
  4184. }
  4185. int compareSymbolsByName(IHqlExpression * left, IHqlExpression * right)
  4186. {
  4187. return stricmp(str(left->queryName()), str(right->queryName()));
  4188. }
  4189. int compareSymbolsByName(IInterface * const * pleft, IInterface * const * pright)
  4190. {
  4191. IHqlExpression * left = static_cast<IHqlExpression *>(*pleft);
  4192. IHqlExpression * right = static_cast<IHqlExpression *>(*pright);
  4193. return stricmp(str(left->queryName()), str(right->queryName()));
  4194. }
  4195. int compareScopesByName(IInterface * const * pleft, IInterface * const * pright)
  4196. {
  4197. IHqlScope * left = static_cast<IHqlScope *>(*pleft);
  4198. IHqlScope * right = static_cast<IHqlScope *>(*pright);
  4199. return compareScopesByName(left, right);
  4200. }
  4201. class ModuleExpander
  4202. {
  4203. public:
  4204. ModuleExpander(HqlLookupContext & _ctx, bool _expandCallsWhenBound, node_operator _outputOp)
  4205. : ctx(_ctx), expandCallsWhenBound(_expandCallsWhenBound), outputOp(_outputOp) {}
  4206. IHqlExpression * createExpanded(IHqlExpression * scopeExpr, IHqlExpression * ifaceExpr, const char * prefix, IIdAtom *matchId);
  4207. protected:
  4208. HqlLookupContext ctx;
  4209. bool expandCallsWhenBound;
  4210. node_operator outputOp;
  4211. };
  4212. IHqlExpression * ModuleExpander::createExpanded(IHqlExpression * scopeExpr, IHqlExpression * ifaceExpr, const char * prefix, IIdAtom *matchId)
  4213. {
  4214. IHqlScope * scope = scopeExpr->queryScope();
  4215. HqlExprArray symbols;
  4216. ensureSymbolsDefined(ifaceExpr, ctx);
  4217. ifaceExpr->queryScope()->getSymbols(symbols);
  4218. symbols.sort(compareSymbolsByName); // should really be in definition order, but that isn't currently preserved
  4219. HqlExprArray outputs;
  4220. StringBuffer lowername;
  4221. ForEachItemIn(i, symbols)
  4222. {
  4223. IHqlExpression & cur = symbols.item(i);
  4224. IIdAtom * name = cur.queryId();
  4225. OwnedHqlExpr resolved = scope->lookupSymbol(name, LSFpublic, ctx);
  4226. LinkedHqlExpr value = resolved;
  4227. if (value && value->isFunction())
  4228. {
  4229. bool allArgumentsHaveDefaults = false;
  4230. if (value->isFunctionDefinition())
  4231. {
  4232. //Allow functions that supply default values for each of the parameters to be expanded
  4233. IHqlExpression * formals = value->queryChild(1);
  4234. IHqlExpression * defaults = value->queryChild(2);
  4235. unsigned numFormals = formals->numChildren();
  4236. if (numFormals == 0)
  4237. allArgumentsHaveDefaults = true;
  4238. else if (defaults && (defaults->numChildren() == numFormals))
  4239. {
  4240. allArgumentsHaveDefaults = true;
  4241. ForEachChild(i, defaults)
  4242. {
  4243. IHqlExpression * param = defaults->queryChild(i);
  4244. if (param->getOperator() == no_omitted)
  4245. allArgumentsHaveDefaults = false;
  4246. }
  4247. }
  4248. }
  4249. if (allArgumentsHaveDefaults)
  4250. {
  4251. HqlExprArray args;
  4252. value.setown(createBoundFunction(NULL, value, args, NULL, expandCallsWhenBound));
  4253. }
  4254. else
  4255. value.clear();
  4256. }
  4257. if (value && isExported(resolved))
  4258. {
  4259. lowername.clear().append(prefix).append(lower(name)).toLowerCase();
  4260. node_operator op = no_none;
  4261. if (outputOp == no_output)
  4262. {
  4263. if (value->isDictionary())
  4264. {
  4265. value.setown(createDataset(no_datasetfromdictionary, value.getClear()));
  4266. value.setown(createDataset(no_selectfields, value.getClear(), createValue(no_null)));
  4267. op = no_output;
  4268. }
  4269. else if (value->isDataset())
  4270. {
  4271. value.setown(createDataset(no_selectfields, LINK(value), createValue(no_null)));
  4272. op = no_output;
  4273. }
  4274. else if (value->isDatarow())
  4275. op = no_output;
  4276. else if (value->isList() || value->queryType()->isScalar())
  4277. op = no_outputscalar;
  4278. }
  4279. else
  4280. {
  4281. assertex(outputOp == no_evaluate_stmt);
  4282. if (value->isList() || value->queryType()->isScalar())
  4283. op = no_evaluate_stmt;
  4284. }
  4285. switch (value->getOperator())
  4286. {
  4287. case no_typedef:
  4288. case no_enum:
  4289. op = no_none;
  4290. break;
  4291. }
  4292. if (value->isScope())
  4293. {
  4294. lowername.append(".");
  4295. OwnedHqlExpr child = createExpanded(value, value, lowername.str(), matchId);
  4296. if (child->getOperator() != no_null)
  4297. outputs.append(*child.getClear());
  4298. }
  4299. else if (!matchId || lower(name)==lower(matchId))
  4300. {
  4301. if (op != no_none)
  4302. {
  4303. outputs.append(*createValue(op, makeVoidType(), LINK(value), createAttribute(namedAtom, createConstant(lowername))));
  4304. }
  4305. else if (value->isAction())
  4306. outputs.append(*LINK(value));
  4307. }
  4308. }
  4309. }
  4310. return createActionList(outputs);
  4311. }
  4312. IHqlExpression * createEvaluateOutputModule(HqlLookupContext & ctx, IHqlExpression * scopeExpr, IHqlExpression * ifaceExpr, bool expandCallsWhenBound, node_operator outputOp, IIdAtom *id)
  4313. {
  4314. ModuleExpander expander(ctx, expandCallsWhenBound, outputOp);
  4315. return expander.createExpanded(scopeExpr, ifaceExpr, NULL, id);
  4316. }
  4317. extern HQL_API IHqlExpression * createStoredModule(IHqlExpression * scopeExpr)
  4318. {
  4319. IHqlScope * scope = scopeExpr->queryScope();
  4320. HqlExprArray symbols;
  4321. scope->getSymbols(symbols);
  4322. symbols.sort(compareSymbolsByName); // should really be in definition order, but that isn't currently preserved
  4323. Owned<IHqlScope> newScope = createVirtualScope();
  4324. IHqlExpression * newScopeExpr = queryExpression(newScope);
  4325. newScopeExpr->addOperand(LINK(scopeExpr));
  4326. HqlExprArray noParameters;
  4327. IIdAtom * moduleName = NULL;
  4328. ForEachItemIn(i, symbols)
  4329. {
  4330. IHqlExpression & cur = symbols.item(i);
  4331. if (isExported(&cur) && !cur.isFunction())
  4332. {
  4333. LinkedHqlExpr value = &cur;
  4334. if (value->isDataset() || value->isDatarow() || value->isList() || value->queryType()->isScalar())
  4335. {
  4336. if (value->getOperator() == no_purevirtual)
  4337. value.setown(createNullExpr(value));
  4338. IIdAtom * name = symbols.item(i).queryId();
  4339. OwnedHqlExpr failure = createValue(no_stored, makeVoidType(), createConstant(str(lower(name))));
  4340. HqlExprArray meta;
  4341. value.setown(attachWorkflowOwn(meta, value.getClear(), failure, NULL));
  4342. newScope->defineSymbol(name, moduleName, value.getClear(),
  4343. true, false, cur.getSymbolFlags());
  4344. }
  4345. }
  4346. }
  4347. return queryExpression(newScope.getClear())->closeExpr();
  4348. }
  4349. extern HQL_API IHqlExpression * convertScalarAggregateToDataset(IHqlExpression * expr)
  4350. {
  4351. IHqlExpression * dataset = expr->queryChild(0);
  4352. IHqlExpression * arg = queryRealChild(expr, 1);
  4353. node_operator newop;
  4354. switch (expr->getOperator())
  4355. {
  4356. case no_ave: newop = no_avegroup; break;
  4357. case no_count: newop = no_countgroup; break;
  4358. case no_min: newop = no_mingroup; break;
  4359. case no_max: newop = no_maxgroup; break;
  4360. case no_sum: newop = no_sumgroup; break;
  4361. case no_exists:newop = no_existsgroup; break;
  4362. case no_variance: newop = no_vargroup; break;
  4363. case no_covariance: newop = no_covargroup; break;
  4364. case no_correlation:newop = no_corrgroup; break;
  4365. default:
  4366. return NULL;
  4367. }
  4368. OwnedHqlExpr field;
  4369. if ((newop == no_mingroup || newop == no_maxgroup) && (arg->getOperator() == no_select))
  4370. field.set(arg->queryChild(1)); // inherit maxlength etc...
  4371. else
  4372. field.setown(createField(valueId, expr->getType(), NULL));
  4373. IHqlExpression * aggregateRecord = createRecord(field);
  4374. HqlExprArray valueArgs;
  4375. ForEachChildFrom(i1, expr, 1)
  4376. {
  4377. IHqlExpression * cur = expr->queryChild(i1);
  4378. //keyed is currently required on the aggregate operator
  4379. if (!cur->isAttribute() || (cur->queryName() == keyedAtom))
  4380. valueArgs.append(*LINK(cur));
  4381. }
  4382. IHqlExpression * newValue = createValue(newop, expr->getType(), valueArgs);
  4383. IHqlExpression * assign = createAssign(createSelectExpr(getSelf(aggregateRecord), LINK(field)), newValue);
  4384. IHqlExpression * transform = createValue(no_newtransform, makeTransformType(aggregateRecord->getType()), assign);
  4385. //remove grouping if dataset happens to be grouped...
  4386. dataset->Link();
  4387. if (dataset->queryType()->getTypeCode() == type_groupedtable)
  4388. dataset = createDataset(no_group, dataset, NULL);
  4389. HqlExprArray args;
  4390. args.append(*dataset);
  4391. args.append(*aggregateRecord);
  4392. args.append(*transform);
  4393. ForEachChild(i2, expr)
  4394. {
  4395. IHqlExpression * cur = expr->queryChild(i2);
  4396. if (cur->isAttribute())
  4397. args.append(*LINK(cur));
  4398. }
  4399. IHqlExpression * project = createDataset(no_newaggregate, args);
  4400. return createRow(no_selectnth, project, createConstantOne());
  4401. }
  4402. //---------------------------------------------------------------------------
  4403. void HqlExprHashTable::onAdd(void *et)
  4404. {
  4405. ((IHqlExpression*)et)->Link();
  4406. }
  4407. void HqlExprHashTable::onRemove(void *et)
  4408. {
  4409. ((IHqlExpression*)et)->Release();
  4410. }
  4411. unsigned HqlExprHashTable::getHashFromElement(const void *et) const
  4412. {
  4413. return ((IHqlExpression*)et)->getHash();
  4414. }
  4415. unsigned HqlExprHashTable::getHashFromFindParam(const void *fp) const
  4416. {
  4417. return ((IHqlExpression*)fp)->getHash();
  4418. }
  4419. const void * HqlExprHashTable::getFindParam(const void *et) const
  4420. {
  4421. return et;
  4422. }
  4423. bool HqlExprHashTable::matchesFindParam(const void *et, const void *key, unsigned fphash) const
  4424. {
  4425. return et == key;
  4426. }
  4427. //---------------------------------------------------------------------------
  4428. bool BitfieldPacker::checkSpaceAvailable(unsigned & thisBitOffset, unsigned & thisBits, ITypeInfo * type)
  4429. {
  4430. bool fitted = true;
  4431. thisBits = type->getBitSize();
  4432. ITypeInfo * storeType = type->queryChildType();
  4433. if ((thisBits > bitsRemaining) || !activeType || (storeType != activeType))
  4434. {
  4435. activeType = storeType;
  4436. unsigned unitSize = storeType->getSize();
  4437. bitsRemaining = unitSize * 8;
  4438. nextBitOffset = 0;
  4439. fitted = false;
  4440. }
  4441. thisBitOffset = nextBitOffset;
  4442. nextBitOffset += thisBits;
  4443. bitsRemaining -= thisBits;
  4444. return fitted;
  4445. }
  4446. void reorderAttributesToEnd(HqlExprArray & target, const HqlExprArray & source)
  4447. {
  4448. ForEachItemIn(i1, source)
  4449. {
  4450. IHqlExpression & cur = source.item(i1);
  4451. if (!cur.isAttribute())
  4452. target.append(OLINK(cur));
  4453. }
  4454. ForEachItemIn(i2, source)
  4455. {
  4456. IHqlExpression & cur = source.item(i2);
  4457. if (cur.isAttribute())
  4458. target.append(OLINK(cur));
  4459. }
  4460. }
  4461. bool hasActiveTopDataset(IHqlExpression * expr)
  4462. {
  4463. switch (getChildDatasetType(expr))
  4464. {
  4465. case childdataset_dataset:
  4466. case childdataset_datasetleft:
  4467. case childdataset_top_left_right:
  4468. return true;
  4469. }
  4470. return false;
  4471. }
  4472. //-------------------------------------------------------------------------------------------------------
  4473. void getStoredDescription(StringBuffer & text, IHqlExpression * sequence, IHqlExpression * name, bool includeInternalName)
  4474. {
  4475. if (sequence)
  4476. {
  4477. switch (sequence->queryValue()->getIntValue())
  4478. {
  4479. case ResultSequencePersist:
  4480. text.append("PERSIST(");
  4481. name->toString(text);
  4482. text.append(")");
  4483. break;
  4484. case ResultSequenceStored:
  4485. text.append("STORED(");
  4486. name->toString(text);
  4487. text.append(")");
  4488. break;
  4489. case ResultSequenceInternal:
  4490. text.append("Internal");
  4491. if (includeInternalName)
  4492. name->toString(text.append("(")).append(")");
  4493. break;
  4494. default:
  4495. if (name)
  4496. name->toString(text);
  4497. else
  4498. text.append("Result #").append(sequence->queryValue()->getIntValue()+1);
  4499. break;
  4500. }
  4501. }
  4502. }
  4503. IHqlExpression * appendOwnedOperandsF(IHqlExpression * expr, ...)
  4504. {
  4505. HqlExprArray children;
  4506. unwindChildren(children, expr);
  4507. va_list args;
  4508. va_start(args, expr);
  4509. for (;;)
  4510. {
  4511. IHqlExpression *parm = va_arg(args, IHqlExpression *);
  4512. if (!parm)
  4513. break;
  4514. children.append(*parm);
  4515. }
  4516. va_end(args);
  4517. return expr->clone(children);
  4518. }
  4519. extern HQL_API void inheritAttribute(HqlExprArray & attrs, IHqlExpression * donor, IAtom * name)
  4520. {
  4521. IHqlExpression * match = donor->queryAttribute(name);
  4522. if (match)
  4523. attrs.append(*LINK(match));
  4524. }
  4525. IHqlExpression * inheritAttribute(IHqlExpression * expr, IHqlExpression * donor, IAtom * name)
  4526. {
  4527. return appendOwnedOperand(expr, LINK(donor->queryAttribute(name)));
  4528. }
  4529. IHqlExpression * appendAttribute(IHqlExpression * expr, IAtom * attr)
  4530. {
  4531. return appendOwnedOperand(expr, createAttribute(attr));
  4532. }
  4533. IHqlExpression * appendOwnedOperand(IHqlExpression * expr, IHqlExpression * ownedOperand)
  4534. {
  4535. if (!ownedOperand)
  4536. return LINK(expr);
  4537. HqlExprArray args;
  4538. unwindChildren(args, expr);
  4539. args.append(*ownedOperand);
  4540. return expr->clone(args);
  4541. }
  4542. IHqlExpression * removeOperand(IHqlExpression * expr, IHqlExpression * operand)
  4543. {
  4544. HqlExprArray args;
  4545. unwindChildren(args, expr);
  4546. args.zap(*operand);
  4547. return expr->clone(args);
  4548. }
  4549. IHqlExpression * removeChildOp(IHqlExpression * expr, node_operator op)
  4550. {
  4551. HqlExprArray args;
  4552. unwindChildren(args, expr);
  4553. ForEachItemInRev(i, args)
  4554. if (args.item(i).getOperator() == op)
  4555. args.remove(i);
  4556. return expr->clone(args);
  4557. }
  4558. IHqlExpression * removeAttribute(IHqlExpression * expr, IAtom * attr)
  4559. {
  4560. HqlExprArray args;
  4561. unwindChildren(args, expr);
  4562. if (removeAttribute(args, attr))
  4563. return expr->clone(args);
  4564. return LINK(expr);
  4565. }
  4566. IHqlExpression * replaceOwnedAttribute(IHqlExpression * expr, IHqlExpression * ownedOperand)
  4567. {
  4568. HqlExprArray args;
  4569. unwindChildren(args, expr);
  4570. removeAttribute(args, ownedOperand->queryName());
  4571. args.append(*ownedOperand);
  4572. return expr->clone(args);
  4573. }
  4574. IHqlExpression * appendLocalAttribute(IHqlExpression * expr)
  4575. {
  4576. return appendOwnedOperand(expr, createLocalAttribute());
  4577. }
  4578. IHqlExpression * removeLocalAttribute(IHqlExpression * expr)
  4579. {
  4580. return removeAttribute(expr, localAtom);
  4581. }
  4582. bool hasOperand(IHqlExpression * expr, IHqlExpression * child)
  4583. {
  4584. expr = expr->queryBody();
  4585. ForEachChild(i, expr)
  4586. {
  4587. if (expr->queryChild(i) == child)
  4588. return true;
  4589. }
  4590. return false;
  4591. }
  4592. //-------------------------------------------------------------------------------------------------------
  4593. class HQL_API SplitDatasetAttributeTransformer : public NewHqlTransformer
  4594. {
  4595. public:
  4596. SplitDatasetAttributeTransformer();
  4597. virtual void analyseExpr(IHqlExpression * expr);
  4598. virtual IHqlExpression * createTransformed(IHqlExpression * expr);
  4599. bool split(SharedHqlExpr & dataset, SharedHqlExpr & attribute, IHqlExpression * expr);
  4600. protected:
  4601. void doAnalyseSelect(IHqlExpression * expr);
  4602. IHqlExpression * doTransformSelect(IHqlExpression * expr);
  4603. protected:
  4604. OwnedHqlExpr selSeq;
  4605. OwnedHqlExpr rowsId;
  4606. HqlExprCopyArray datasets;
  4607. HqlExprArray newDatasets;
  4608. HqlExprArray selectors;
  4609. };
  4610. static HqlTransformerInfo hqlSplitDatasetAttributeInfo("SplitDatasetAttributeTransformer");
  4611. SplitDatasetAttributeTransformer::SplitDatasetAttributeTransformer(): NewHqlTransformer(hqlSplitDatasetAttributeInfo)
  4612. {
  4613. }
  4614. void SplitDatasetAttributeTransformer::analyseExpr(IHqlExpression * expr)
  4615. {
  4616. if (alreadyVisited(expr))
  4617. return;
  4618. switch (expr->getOperator())
  4619. {
  4620. case no_select:
  4621. doAnalyseSelect(expr);
  4622. return;
  4623. case NO_AGGREGATE:
  4624. case no_createset:
  4625. case no_colon:
  4626. case no_globalscope:
  4627. case no_nothor:
  4628. //Ugly, should really be normalized to no_select(no_aggregate[1], x)
  4629. return;
  4630. case no_if:
  4631. case no_mapto:
  4632. analyseExpr(expr->queryChild(0));
  4633. return;
  4634. case no_add:
  4635. case no_sub:
  4636. case no_mul:
  4637. case no_div:
  4638. case no_cast:
  4639. case no_implicitcast:
  4640. case no_concat:
  4641. case no_eq: case no_ne: case no_gt: case no_ge: case no_lt: case no_le:
  4642. case no_case:
  4643. case no_map:
  4644. case no_externalcall:
  4645. case no_call:
  4646. break;
  4647. // default:
  4648. // return;
  4649. }
  4650. ITypeInfo * type = expr->queryType();
  4651. if (type && type->getTypeCode() == type_void)
  4652. return;
  4653. NewHqlTransformer::analyseExpr(expr);
  4654. }
  4655. void SplitDatasetAttributeTransformer::doAnalyseSelect(IHqlExpression * expr)
  4656. {
  4657. IHqlExpression * ds = expr->queryChild(0);
  4658. if (expr->hasAttribute(newAtom))
  4659. {
  4660. if (!datasets.contains(*ds))
  4661. {
  4662. IHqlExpression * lhs = LINK(ds);
  4663. if (lhs->isDataset()) lhs = createRow(no_activerow, lhs);
  4664. datasets.append(*ds);
  4665. newDatasets.append(*createDatasetFromRow(lhs));
  4666. }
  4667. return;
  4668. }
  4669. //ds is a no_select, so will be handled correctly.
  4670. NewHqlTransformer::analyseExpr(expr);
  4671. }
  4672. IHqlExpression * SplitDatasetAttributeTransformer::createTransformed(IHqlExpression * expr)
  4673. {
  4674. switch (expr->getOperator())
  4675. {
  4676. case no_select:
  4677. if (expr->hasAttribute(newAtom))
  4678. return doTransformSelect(expr);
  4679. break;
  4680. case no_colon:
  4681. case no_globalscope:
  4682. case no_nothor:
  4683. return LINK(expr);
  4684. }
  4685. return NewHqlTransformer::createTransformed(expr);
  4686. }
  4687. IHqlExpression * SplitDatasetAttributeTransformer::doTransformSelect(IHqlExpression * expr)
  4688. {
  4689. IHqlExpression * ds = expr->queryChild(0);
  4690. IHqlExpression * field = expr->queryChild(1);
  4691. unsigned match = datasets.find(*ds);
  4692. if (match == NotFound)
  4693. return NewHqlTransformer::createTransformed(expr);
  4694. return createSelectExpr(transform(&selectors.item(match)), LINK(field)); // note, remove new attributes
  4695. }
  4696. bool SplitDatasetAttributeTransformer::split(SharedHqlExpr & dataset, SharedHqlExpr & attribute, IHqlExpression * expr)
  4697. {
  4698. analyseExpr(expr);
  4699. //First remove trivial datasets...
  4700. {
  4701. unsigned num = datasets.ordinality();
  4702. for (unsigned i=0; i< num;)
  4703. {
  4704. IHqlExpression * cur = &datasets.item(i);
  4705. while ((cur->getOperator() == no_selectnth) || (cur->getOperator() == no_preservemeta))
  4706. cur = cur->queryChild(0);
  4707. bool remove = false;
  4708. switch (cur->getOperator())
  4709. {
  4710. case no_getgraphresult:
  4711. remove = !expr->hasAttribute(_distributed_Atom);
  4712. break;
  4713. case no_workunit_dataset:
  4714. case no_getgraphloopresult:
  4715. case no_left:
  4716. case no_right:
  4717. case no_colon:
  4718. case no_globalscope:
  4719. case no_nothor:
  4720. remove = true;
  4721. break;
  4722. }
  4723. if (remove)
  4724. {
  4725. datasets.remove(i);
  4726. newDatasets.remove(i);
  4727. num--;
  4728. }
  4729. else
  4730. i++;
  4731. }
  4732. }
  4733. const unsigned maxDatasets = 1;
  4734. datasets.trunc(maxDatasets);
  4735. newDatasets.trunc(maxDatasets);
  4736. switch (datasets.ordinality())
  4737. {
  4738. case 0:
  4739. return false;
  4740. case 1:
  4741. selectors.append(*LINK(&newDatasets.item(0)));
  4742. break;
  4743. case 2:
  4744. selSeq.setown(createSelectorSequence());
  4745. selectors.append(*createSelector(no_left, &datasets.item(0), selSeq));
  4746. selectors.append(*createSelector(no_right, &datasets.item(1), selSeq));
  4747. break;
  4748. default:
  4749. {
  4750. selSeq.setown(createSelectorSequence());
  4751. rowsId.setown(createUniqueRowsId());
  4752. ForEachItemIn(i, newDatasets)
  4753. {
  4754. IHqlExpression & cur = newDatasets.item(i);
  4755. OwnedHqlExpr rows = createDataset(no_rows, LINK(&cur), LINK(rowsId));
  4756. selectors.append(*createRow(no_selectnth, LINK(rows), createComma(getSizetConstant(i+1), createAttribute(noBoundCheckAtom))));
  4757. }
  4758. break;
  4759. }
  4760. }
  4761. OwnedHqlExpr value = transform(expr);
  4762. switch (datasets.ordinality())
  4763. {
  4764. case 1:
  4765. dataset.set(&newDatasets.item(0));
  4766. attribute.set(value);
  4767. break;
  4768. case 2:
  4769. {
  4770. OwnedHqlExpr field = createField(unnamedId, value->getType(), NULL);
  4771. OwnedHqlExpr transform = createTransformForField(field, value);
  4772. OwnedHqlExpr combine = createDatasetF(no_combine, LINK(&newDatasets.item(0)), LINK(&newDatasets.item(1)), LINK(transform), LINK(selSeq), NULL);
  4773. OwnedHqlExpr first = createRowF(no_selectnth, LINK(combine), getSizetConstant(1), createAttribute(noBoundCheckAtom), NULL);
  4774. dataset.setown(createDatasetFromRow(first.getClear()));
  4775. attribute.setown(createSelectExpr(LINK(dataset->queryNormalizedSelector()), LINK(field)));
  4776. break;
  4777. }
  4778. default:
  4779. return false;
  4780. }
  4781. return true;
  4782. }
  4783. static bool splitDatasetAttribute(SharedHqlExpr & dataset, SharedHqlExpr & attribute, IHqlExpression * expr)
  4784. {
  4785. #if 0
  4786. //The following code works. However I think it has the side-effect of modifying expressions so that they are no longer
  4787. //csed with other expressions (similar to including too many items in the case statement below). So currently disabled.
  4788. SplitDatasetAttributeTransformer transformer;
  4789. return transformer.split(dataset, attribute, queryNonAliased(expr));
  4790. #else
  4791. IHqlExpression * left = expr->queryChild(0);
  4792. node_operator op = expr->getOperator();
  4793. switch (op)
  4794. {
  4795. case no_evaluate:
  4796. case no_field:
  4797. throwUnexpectedOp(op);
  4798. case no_constant:
  4799. return false;
  4800. case no_select:
  4801. break;
  4802. //Play it safe, by only containing a subset of the expressions here
  4803. //The list of expressions to include here seems to be a bit of a black art. For instance including and/or/not makes many queries worse.
  4804. case no_add:
  4805. case no_sub:
  4806. case no_mul:
  4807. case no_div:
  4808. case no_cast:
  4809. case no_implicitcast:
  4810. case no_concat:
  4811. case no_eq: case no_ne: case no_gt: case no_ge: case no_lt: case no_le:
  4812. case no_if:
  4813. case no_mapto:
  4814. case no_case:
  4815. case no_map:
  4816. case no_externalcall:
  4817. case no_call:
  4818. // case no_not:
  4819. // case no_and:
  4820. // case no_or:
  4821. // case no_substring:
  4822. // case no_charlen:
  4823. {
  4824. HqlExprArray args;
  4825. bool mapped = false;
  4826. ForEachChild(i, expr)
  4827. {
  4828. IHqlExpression * cur = expr->queryChild(i);
  4829. OwnedHqlExpr ds, attr;
  4830. if (splitDatasetAttribute(ds, attr, cur) && (!dataset || ds.get() == dataset.get()))
  4831. {
  4832. args.append(*attr.getClear());
  4833. dataset.set(ds);
  4834. mapped = true;
  4835. }
  4836. else
  4837. args.append(*LINK(cur));
  4838. }
  4839. if (!mapped)
  4840. return false;
  4841. attribute.setown(expr->clone(args));
  4842. return true;
  4843. }
  4844. default:
  4845. return false;
  4846. }
  4847. #ifdef _SR6_
  4848. if (isInlineTrivialDataset(left))
  4849. {
  4850. attribute.set(expr);
  4851. return true;
  4852. }
  4853. #endif
  4854. node_operator leftOp = left->getOperator();
  4855. if ((leftOp !=no_select) || expr->hasAttribute(newAtom))
  4856. {
  4857. //Ensure selections from dictionaries do not have a separate activity for the row lookup.
  4858. if (leftOp == no_selectmap)
  4859. return false;
  4860. //If this is a selection from an inscope dataset then this must not be assumed to be an input dataset.
  4861. if (expr->isDataset() && !expr->hasAttribute(newAtom))
  4862. return false;
  4863. IHqlExpression * lhs = LINK(left);
  4864. IHqlExpression * field = expr->queryChild(1);
  4865. if (lhs->isDataset()) lhs = createRow(no_activerow, lhs);
  4866. dataset.setown(createDatasetFromRow(lhs));
  4867. attribute.setown(createSelectExpr(LINK(dataset), LINK(field))); // remove new attributes
  4868. return true;
  4869. }
  4870. if (!splitDatasetAttribute(dataset, attribute, left))
  4871. return false;
  4872. HqlExprArray args;
  4873. args.append(*attribute.getClear());
  4874. unwindChildren(args, expr, 1);
  4875. attribute.setown(expr->clone(args));
  4876. return true;
  4877. #endif
  4878. }
  4879. bool splitResultValue(SharedHqlExpr & dataset, SharedHqlExpr & attribute, IHqlExpression * value)
  4880. {
  4881. if (value->isDataset())
  4882. return false;
  4883. if (splitDatasetAttribute(dataset, attribute, value))
  4884. return true;
  4885. if (value->isDatarow())
  4886. {
  4887. dataset.setown(createDatasetFromRow(LINK(value)));
  4888. attribute.setown(ensureActiveRow(dataset));
  4889. return true;
  4890. }
  4891. return false;
  4892. }
  4893. IHqlExpression * createSetResult(HqlExprArray & args)
  4894. {
  4895. HqlExprAttr dataset, attribute;
  4896. IHqlExpression * value = &args.item(0);
  4897. assertex(value->getOperator() != no_param);
  4898. if (splitResultValue(dataset, attribute, value))
  4899. {
  4900. args.replace(*dataset.getClear(), 0);
  4901. args.add(*attribute.getClear(), 1);
  4902. return createValue(no_extractresult, makeVoidType(), args);
  4903. }
  4904. if (value->isDataset() || value->isDictionary())
  4905. return createValue(no_output, makeVoidType(), args);
  4906. return createValue(no_setresult, makeVoidType(), args);
  4907. }
  4908. IHqlExpression * convertSetResultToExtract(IHqlExpression * setResult)
  4909. {
  4910. HqlExprAttr dataset, attribute;
  4911. if (splitResultValue(dataset, attribute, setResult->queryChild(0)))
  4912. {
  4913. HqlExprArray args;
  4914. args.append(*dataset.getClear());
  4915. args.append(*attribute.getClear());
  4916. unwindChildren(args, setResult, 1);
  4917. return createValue(no_extractresult, makeVoidType(), args);
  4918. }
  4919. return NULL;
  4920. }
  4921. IHqlExpression * removeDatasetWrapper(IHqlExpression * ds)
  4922. {
  4923. node_operator dsOp = ds->getOperator();
  4924. switch (dsOp)
  4925. {
  4926. case no_datasetfromrow:
  4927. return LINK(ds->queryChild(0));
  4928. case no_inlinetable:
  4929. {
  4930. IHqlExpression * values = ds->queryChild(0);
  4931. assertex(values->numChildren() == 1);
  4932. return createRow(no_createrow, LINK(values->queryChild(0)));
  4933. }
  4934. }
  4935. if (hasSingleRow(ds))
  4936. return createRow(no_selectnth, LINK(ds), createConstantOne());
  4937. throwUnexpectedOp(dsOp);
  4938. }
  4939. //-------------------------------------------------------------------------------------------------------
  4940. void getVirtualFields(HqlExprArray & virtuals, IHqlExpression * record)
  4941. {
  4942. ForEachChild(i, record)
  4943. {
  4944. IHqlExpression * cur = record->queryChild(i);
  4945. switch (cur->getOperator())
  4946. {
  4947. case no_field:
  4948. if (cur->hasAttribute(virtualAtom))
  4949. virtuals.append(*LINK(cur));
  4950. break;
  4951. case no_ifblock:
  4952. getVirtualFields(virtuals, cur->queryChild(1));
  4953. break;
  4954. case no_record:
  4955. getVirtualFields(virtuals, cur);
  4956. break;
  4957. }
  4958. }
  4959. }
  4960. bool containsVirtualFields(IHqlExpression * record)
  4961. {
  4962. ForEachChild(i, record)
  4963. {
  4964. IHqlExpression * cur = record->queryChild(i);
  4965. switch (cur->getOperator())
  4966. {
  4967. case no_field:
  4968. if (cur->hasAttribute(virtualAtom))
  4969. return true;
  4970. //does not walk into nested records
  4971. break;
  4972. case no_ifblock:
  4973. if (containsVirtualFields(cur->queryChild(1)))
  4974. return true;
  4975. break;
  4976. case no_record:
  4977. if (containsVirtualFields(cur))
  4978. return true;
  4979. break;
  4980. }
  4981. }
  4982. return false;
  4983. }
  4984. IHqlExpression * removeVirtualFields(IHqlExpression * record)
  4985. {
  4986. HqlExprArray args;
  4987. args.ensure(record->numChildren());
  4988. ForEachChild(i, record)
  4989. {
  4990. IHqlExpression * cur = record->queryChild(i);
  4991. switch (cur->getOperator())
  4992. {
  4993. case no_field:
  4994. if (!cur->hasAttribute(virtualAtom))
  4995. args.append(*LINK(cur));
  4996. //does not walk into nested records
  4997. break;
  4998. case no_ifblock:
  4999. {
  5000. HqlExprArray ifargs;
  5001. ifargs.append(*LINK(cur->queryChild(0)));
  5002. ifargs.append(*removeVirtualFields(cur->queryChild(1)));
  5003. args.append(*cur->clone(ifargs));
  5004. break;
  5005. }
  5006. case no_record:
  5007. args.append(*removeVirtualFields(cur));
  5008. break;
  5009. default:
  5010. args.append(*LINK(cur));
  5011. break;
  5012. }
  5013. }
  5014. return record->clone(args);
  5015. }
  5016. static HqlTransformerInfo fieldPropertyRemoverInfo("FieldAttributeRemover");
  5017. class FieldAttributeRemover : public NewHqlTransformer
  5018. {
  5019. public:
  5020. FieldAttributeRemover(IAtom * _name) : NewHqlTransformer(fieldPropertyRemoverInfo), name(_name) {}
  5021. virtual IHqlExpression * createTransformed(IHqlExpression * expr)
  5022. {
  5023. switch (expr->getOperator())
  5024. {
  5025. //By default fields within the following are not transformed...
  5026. case no_record:
  5027. case no_ifblock:
  5028. case no_select: // Ensure fields used by ifblocks get transformed
  5029. return completeTransform(expr);
  5030. case no_field:
  5031. {
  5032. OwnedHqlExpr transformed = transformField(expr);
  5033. while (transformed->hasAttribute(name))
  5034. transformed.setown(removeAttribute(transformed, name));
  5035. return transformed.getClear();
  5036. }
  5037. default:
  5038. return NewHqlTransformer::createTransformed(expr);
  5039. }
  5040. }
  5041. private:
  5042. IAtom * name;
  5043. };
  5044. IHqlExpression * removeAttributeFromFields(IHqlExpression * expr, IAtom * name)
  5045. {
  5046. FieldAttributeRemover remover(name);
  5047. return remover.transformRoot(expr);
  5048. }
  5049. #if 0
  5050. void VirtualReplacer::createProjectAssignments(HqlExprArray & assigns, IHqlExpression * expr, IHqlExpression * tgtSelector, IHqlExpression * srcSelector, IHqlExpression * dataset)
  5051. {
  5052. switch (expr->getOperator())
  5053. {
  5054. case no_record:
  5055. {
  5056. ForEachChild(i, expr)
  5057. createProjectAssignments(assigns, expr->queryChild(i), tgtSelector, srcSelector, dataset);
  5058. break;
  5059. }
  5060. case no_ifblock:
  5061. createProjectAssignments(assigns, expr->queryChild(1), tgtSelector, srcSelector, dataset);
  5062. break;
  5063. case no_field:
  5064. {
  5065. OwnedHqlExpr target = createSelectExpr(LINK(tgtSelector), LINK(expr));
  5066. IHqlExpression * newValue;
  5067. if (expr->hasAttribute(virtualAtom))
  5068. newValue = getVirtualReplacement(expr, expr->queryAttribute(virtualAtom)->queryChild(0), dataset);
  5069. else
  5070. newValue = createSelectExpr(LINK(srcSelector), LINK(expr));
  5071. assigns.append(*createAssign(target.getClear(), newValue));
  5072. break;
  5073. }
  5074. }
  5075. }
  5076. #endif
  5077. void unwindTransform(HqlExprCopyArray & exprs, IHqlExpression * transform)
  5078. {
  5079. ForEachChild(i, transform)
  5080. {
  5081. IHqlExpression * cur = transform->queryChild(i);
  5082. switch (cur->getOperator())
  5083. {
  5084. case no_assignall:
  5085. unwindTransform(exprs, cur);
  5086. break;
  5087. default:
  5088. exprs.append(*cur);
  5089. break;
  5090. }
  5091. }
  5092. }
  5093. bool isConstantTransform(IHqlExpression * transform)
  5094. {
  5095. ForEachChild(i, transform)
  5096. {
  5097. IHqlExpression * cur = transform->queryChild(i);
  5098. switch (cur->getOperator())
  5099. {
  5100. case no_assignall:
  5101. if (!isConstantTransform(cur))
  5102. return false;
  5103. break;
  5104. case no_assign:
  5105. {
  5106. IHqlExpression * rhs = cur->queryChild(1);
  5107. if (!rhs->isConstant())
  5108. {
  5109. switch (rhs->getOperator())
  5110. {
  5111. case no_null:
  5112. case no_all:
  5113. break;
  5114. default:
  5115. return false;
  5116. }
  5117. }
  5118. break;
  5119. }
  5120. case no_attr:
  5121. case no_attr_expr:
  5122. break;
  5123. default:
  5124. return false;
  5125. }
  5126. }
  5127. return true;
  5128. }
  5129. //would be sensible to extend this to some simple expressions
  5130. static bool isSimpleValue(IHqlExpression * expr)
  5131. {
  5132. for (;;)
  5133. {
  5134. if (expr->isConstant())
  5135. return true;
  5136. node_operator op = expr->getOperator();
  5137. switch (op)
  5138. {
  5139. case no_null:
  5140. case no_all:
  5141. return true;
  5142. case no_select:
  5143. return !isNewSelector(expr);
  5144. case no_cast:
  5145. case no_implicitcast:
  5146. break;
  5147. default:
  5148. //Do not include access to stored variables
  5149. return false;
  5150. }
  5151. expr = expr->queryChild(0);
  5152. }
  5153. }
  5154. IHqlExpression * queryUncastExpr(IHqlExpression * expr)
  5155. {
  5156. for (;;)
  5157. {
  5158. if (!isCast(expr))
  5159. return expr;
  5160. expr = expr->queryChild(0);
  5161. }
  5162. }
  5163. static bool isSimpleTransformToMergeWith(IHqlExpression * expr, int & varSizeCount)
  5164. {
  5165. ForEachChild(i, expr)
  5166. {
  5167. IHqlExpression * cur = expr->queryChild(i);
  5168. switch (cur->getOperator())
  5169. {
  5170. case no_assignall:
  5171. {
  5172. if (!isSimpleTransformToMergeWith(cur, varSizeCount))
  5173. return false;
  5174. break;
  5175. }
  5176. case no_assign:
  5177. {
  5178. IHqlExpression * rhs = cur->queryChild(1);
  5179. if (!isSimpleValue(rhs))
  5180. return false;
  5181. //Want to take note of whether it reduces the number of variable size fields, if it makes many variable sized into fixed size then it won't be good to remove
  5182. ITypeInfo * srcType = queryUncastExpr(rhs)->queryType();
  5183. ITypeInfo * tgtType = cur->queryChild(0)->queryType();
  5184. if (tgtType->getSize() == UNKNOWN_LENGTH)
  5185. varSizeCount--;
  5186. if (srcType->getSize() == UNKNOWN_LENGTH)
  5187. varSizeCount++;
  5188. break;
  5189. }
  5190. case no_attr:
  5191. case no_attr_link:
  5192. case no_attr_expr:
  5193. break;
  5194. default:
  5195. return false;
  5196. }
  5197. }
  5198. return true;
  5199. }
  5200. bool isSimpleTransformToMergeWith(IHqlExpression * expr)
  5201. {
  5202. int varSizeCount = 0;
  5203. return isSimpleTransformToMergeWith(expr, varSizeCount) && varSizeCount < 3;
  5204. }
  5205. bool isSimpleTransform(IHqlExpression * expr)
  5206. {
  5207. int varSizeCount = 0;
  5208. return isSimpleTransformToMergeWith(expr, varSizeCount);
  5209. }
  5210. bool isConstantDataset(IHqlExpression * expr)
  5211. {
  5212. assertex(expr->getOperator() == no_inlinetable);
  5213. IHqlExpression * values = expr->queryChild(0);
  5214. ForEachChild(i, values)
  5215. {
  5216. if (!isConstantTransform(values->queryChild(i)))
  5217. return false;
  5218. }
  5219. return true;
  5220. }
  5221. bool isConstantDictionary(IHqlExpression * expr)
  5222. {
  5223. if (expr->getOperator() == no_null)
  5224. return true;
  5225. if (expr->getOperator() != no_createdictionary)
  5226. return false;
  5227. IHqlExpression * dataset = expr->queryChild(0);
  5228. if (dataset->getOperator() == no_inlinetable)
  5229. return isConstantDataset(dataset);
  5230. return false;
  5231. }
  5232. bool isProjectableCall(IHqlExpression *expr)
  5233. {
  5234. if (expr->getOperator() != no_call)
  5235. return false;
  5236. IHqlExpression * funcdef = expr->queryBody()->queryFunctionDefinition();
  5237. assertex(funcdef);
  5238. IHqlExpression * body = funcdef->queryChild(0);
  5239. assertex(body);
  5240. if ((funcdef->getOperator() == no_funcdef) && (body->getOperator() == no_outofline))
  5241. {
  5242. IHqlExpression * bodycode = body->queryChild(0);
  5243. if (bodycode->getOperator() == no_embedbody && bodycode->hasAttribute(projectedAtom))
  5244. return true;
  5245. }
  5246. return false;
  5247. }
  5248. inline bool iseol(char c) { return c == '\r' || c == '\n'; }
  5249. static unsigned skipSpace(unsigned start, unsigned len, const char * buffer)
  5250. {
  5251. while (start < len && isspace((byte)buffer[start]))
  5252. start++;
  5253. return start;
  5254. }
  5255. static unsigned trimSpace(unsigned len, const char * buffer)
  5256. {
  5257. while (len && isspace((byte)buffer[len-1]))
  5258. len--;
  5259. return len;
  5260. }
  5261. // Supported syntax:
  5262. // #option pure
  5263. // #option library 'value'
  5264. // #option ('pure', true)
  5265. // #option ('library', 'value')
  5266. //
  5267. // - cur must point to the first non-space character of '#option'
  5268. static bool matchOption(unsigned cur, unsigned max, const char * buffer, unsigned lenMatch, const char * match, bool requireValue, unsigned & valueStart, unsigned & valueEnd)
  5269. {
  5270. bool openBracket = false;
  5271. bool commaBetweenPair = false;
  5272. valueStart = 0;
  5273. valueEnd = 0;
  5274. if (cur + lenMatch > max)
  5275. return false;
  5276. if ('(' == buffer[cur])
  5277. {
  5278. openBracket = true;
  5279. cur = skipSpace(cur+1, max, buffer);
  5280. // Option inside brackets must have the option name wrapped in single quotes
  5281. if ((cur+lenMatch+3 < max) && ('\'' == buffer[cur]) )
  5282. {
  5283. ++cur;
  5284. if (memicmp(buffer+cur, match, lenMatch) != 0)
  5285. return false;
  5286. cur += lenMatch;
  5287. if ('\'' != buffer[cur])
  5288. return false;
  5289. cur = skipSpace(cur+1, max, buffer);
  5290. if ((cur < max) && (',' == buffer[cur]))
  5291. {
  5292. ++cur;
  5293. commaBetweenPair = true;
  5294. }
  5295. else if (requireValue)
  5296. return false;
  5297. }
  5298. else // Not possible to match option name in quotes
  5299. return false;
  5300. }
  5301. else
  5302. {
  5303. if (memicmp(buffer+cur, match, lenMatch) != 0)
  5304. return false;
  5305. cur += lenMatch;
  5306. if ((cur < max) && isalnum(buffer[cur]))
  5307. return false;
  5308. }
  5309. cur = skipSpace(cur, max, buffer);
  5310. if (cur < max)
  5311. {
  5312. if ('\'' == buffer[cur])
  5313. {
  5314. ++cur;
  5315. valueStart = cur;
  5316. while ((cur < max) && ('\'' != buffer[cur]))
  5317. ++cur;
  5318. if (cur >= max) return false;
  5319. valueEnd = cur;
  5320. cur = skipSpace(cur+1, max, buffer);
  5321. if (openBracket && (')' != buffer[cur]))
  5322. return false;
  5323. }
  5324. else
  5325. {
  5326. valueStart = cur;
  5327. if (openBracket)
  5328. {
  5329. while ((cur < max) && (')' != buffer[cur]))
  5330. ++cur;
  5331. if (cur >= max) return false;
  5332. valueEnd = trimSpace(cur,buffer);
  5333. }
  5334. else
  5335. valueEnd = trimSpace(max, buffer);
  5336. }
  5337. }
  5338. // Note: empty quoted strings rejected here too
  5339. if ((requireValue || commaBetweenPair) && (valueEnd==valueStart))
  5340. return false;
  5341. return true;
  5342. }
  5343. IHqlExpression * extractCppBodyAttrs(unsigned lenBuffer, const char * buffer)
  5344. {
  5345. OwnedHqlExpr attrs;
  5346. unsigned prev = '\n';
  5347. for (unsigned i=0; i < lenBuffer; i++)
  5348. {
  5349. unsigned next = buffer[i];
  5350. bool ignore = false;
  5351. switch (next)
  5352. {
  5353. case '*':
  5354. if ('/' == prev) // Ignore directives in multi-line comments
  5355. {
  5356. i+=2;
  5357. while (i < lenBuffer && ('*' != buffer[i-1] || '/' != buffer[i]))
  5358. ++i;
  5359. }
  5360. next = ' '; // treat as whitespace
  5361. break;
  5362. case '/':
  5363. if ('/' == prev) // Ignore directives in single line comments
  5364. {
  5365. ++i;
  5366. while (i < lenBuffer && !iseol(buffer[i]))
  5367. ++i;
  5368. }
  5369. next = '\n';
  5370. break;
  5371. case ' ': case '\t':
  5372. ignore = true; // allow whitespace in front of #option
  5373. break;
  5374. case '#':
  5375. if (prev == '\n')
  5376. {
  5377. if ((i + 1 + 6 < lenBuffer) && memicmp(buffer+i+1, "option", 6) == 0)
  5378. {
  5379. unsigned valueStart, valueEnd;
  5380. unsigned start = skipSpace(i+1+6, lenBuffer, buffer);
  5381. unsigned end = start;
  5382. while (end < lenBuffer && !iseol((byte)buffer[end]))
  5383. end++;
  5384. i = end;
  5385. if(matchOption(start, end, buffer, 4, "pure", false, valueStart, valueEnd))
  5386. attrs.setown(createComma(attrs.getClear(), createAttribute(pureAtom)));
  5387. else if (matchOption(start, end, buffer, 8, "volatile", false, valueStart, valueEnd))
  5388. attrs.setown(createComma(attrs.getClear(), createAttribute(volatileAtom)));
  5389. else if (matchOption(start, end, buffer, 4, "costly", false, valueStart, valueEnd))
  5390. attrs.setown(createComma(attrs.getClear(), createAttribute(costlyAtom)));
  5391. else if (matchOption(start, end, buffer, 4, "once", false, valueStart, valueEnd))
  5392. attrs.setown(createComma(attrs.getClear(), createAttribute(onceAtom)));
  5393. else if (matchOption(start, end, buffer, 6, "action", false, valueStart, valueEnd))
  5394. attrs.setown(createComma(attrs.getClear(), createAttribute(actionAtom)));
  5395. else if (matchOption(start, end, buffer, 6, "source", true, valueStart, valueEnd))
  5396. {
  5397. Owned<IValue> restOfLine = createUtf8Value(valueEnd-valueStart, buffer+valueStart, makeUtf8Type(UNKNOWN_LENGTH, NULL));
  5398. OwnedHqlExpr arg = createConstant(restOfLine.getClear());
  5399. attrs.setown(createComma(attrs.getClear(), createAttribute(sourceAtom, arg.getClear())));
  5400. }
  5401. else if (matchOption(start, end, buffer, 7, "library", true, valueStart, valueEnd))
  5402. {
  5403. Owned<IValue> restOfLine = createUtf8Value(valueEnd-valueStart, buffer+valueStart, makeUtf8Type(UNKNOWN_LENGTH, NULL));
  5404. OwnedHqlExpr arg = createConstant(restOfLine.getClear());
  5405. attrs.setown(createComma(attrs.getClear(), createAttribute(libraryAtom, arg.getClear())));
  5406. }
  5407. else if (matchOption(start, end, buffer, 4, "link", true, valueStart, valueEnd))
  5408. {
  5409. Owned<IValue> restOfLine = createUtf8Value(valueEnd-valueStart, buffer+valueStart, makeUtf8Type(UNKNOWN_LENGTH, NULL));
  5410. OwnedHqlExpr arg = createConstant(restOfLine.getClear());
  5411. attrs.setown(createComma(attrs.getClear(), createAttribute(linkAtom, arg.getClear())));
  5412. }
  5413. }
  5414. }
  5415. }
  5416. if (!ignore)
  5417. prev = next;
  5418. }
  5419. return attrs.getClear();
  5420. }
  5421. unsigned cleanupEmbeddedCpp(unsigned len, char * buffer)
  5422. {
  5423. unsigned delta = 0;
  5424. unsigned prev = '\n';
  5425. for (unsigned i=0; i < len; i++)
  5426. {
  5427. char next = buffer[i];
  5428. unsigned skip = 0;
  5429. switch (next)
  5430. {
  5431. case '\r':
  5432. skip = 1;
  5433. prev = next;
  5434. break;
  5435. case ' ': case '\t':
  5436. break;
  5437. case '#':
  5438. if (prev == '\n')
  5439. {
  5440. if ((i + 1 + 6 < len) && memicmp(buffer+i+1, "option", 6) == 0)
  5441. {
  5442. //skip to newline after #option
  5443. unsigned end = i + 1 + 6;
  5444. while (end < len && !iseol(buffer[end]))
  5445. end++;
  5446. skip = end - i;
  5447. }
  5448. }
  5449. //fallthrough
  5450. default:
  5451. prev = next;
  5452. break;
  5453. }
  5454. if (skip != 0)
  5455. {
  5456. delta += skip;
  5457. i += (skip - 1);
  5458. }
  5459. else if (delta)
  5460. buffer[i-delta] = next;
  5461. }
  5462. return len-delta;
  5463. }
  5464. bool isNullList(IHqlExpression * expr)
  5465. {
  5466. switch (expr->getOperator())
  5467. {
  5468. case no_null:
  5469. return true;
  5470. case no_list:
  5471. case no_datasetlist:
  5472. case no_sortlist:
  5473. return expr->numChildren() == 0;
  5474. }
  5475. return false;
  5476. }
  5477. //--------------------------------------------------------------------------------------
  5478. class TempTableTransformer
  5479. {
  5480. public:
  5481. TempTableTransformer(IErrorReceiver & _errorProcessor, ECLlocation & _location, bool _strictTypeChecking = false)
  5482. : errorProcessor(_errorProcessor), defaultLocation(_location), strictTypeChecking(_strictTypeChecking)
  5483. {}
  5484. IHqlExpression * createTempTableTransform(IHqlExpression * curRow, IHqlExpression * record);
  5485. protected:
  5486. void createTempTableAssign(HqlExprArray & assigns, IHqlExpression * self, IHqlExpression * curRow, IHqlExpression * expr, unsigned & col, IHqlExpression * selector, HqlMapTransformer & mapper, bool included);
  5487. IHqlExpression * createTempTableTransform(IHqlExpression * self, IHqlExpression * curRow, IHqlExpression * expr, unsigned & col, IHqlExpression * selector, HqlMapTransformer & mapper, bool included);
  5488. void reportWarning(WarnErrorCategory category, IHqlExpression * location, int code,const char *format, ...) __attribute__((format(printf, 5, 6)));
  5489. void reportError(IHqlExpression * location, int code,const char *format, ...) __attribute__((format(printf, 4, 5)));
  5490. protected:
  5491. IErrorReceiver & errorProcessor;
  5492. ECLlocation & defaultLocation;
  5493. bool strictTypeChecking;
  5494. };
  5495. IHqlExpression * TempTableTransformer::createTempTableTransform(IHqlExpression * self, IHqlExpression * curRow, IHqlExpression * expr, unsigned & col, IHqlExpression * selector, HqlMapTransformer & mapper, bool included)
  5496. {
  5497. HqlExprArray assigns;
  5498. createTempTableAssign(assigns, self, curRow, expr, col, selector, mapper, included);
  5499. return createValue(no_transform, makeTransformType(createRecordType(expr)), assigns);
  5500. }
  5501. IHqlExpression * TempTableTransformer::createTempTableTransform(IHqlExpression * curRow, IHqlExpression * record)
  5502. {
  5503. OwnedHqlExpr self = getSelf(record);
  5504. HqlMapTransformer mapping;
  5505. unsigned col = 0;
  5506. IHqlExpression * rowPayloadAttr = curRow->queryAttribute(_payload_Atom);
  5507. IHqlExpression * recordPayloadAttr = record->queryAttribute(_payload_Atom);
  5508. if (rowPayloadAttr)
  5509. {
  5510. unsigned rowPayload = (unsigned) getIntValue(rowPayloadAttr->queryChild(0));
  5511. col++;
  5512. if (recordPayloadAttr)
  5513. {
  5514. unsigned recordPayload = (unsigned) getIntValue(recordPayloadAttr->queryChild(0));
  5515. if (rowPayload != recordPayload)
  5516. ERRORAT(curRow->queryAttribute(_location_Atom), HQLERR_PayloadMismatch);
  5517. }
  5518. else
  5519. ERRORAT(curRow->queryAttribute(_location_Atom), HQLERR_PayloadMismatch);
  5520. }
  5521. else if (recordPayloadAttr)
  5522. ERRORAT(curRow->queryAttribute(_location_Atom), HQLERR_PayloadMismatch);
  5523. OwnedHqlExpr ret = createTempTableTransform(self, curRow, record, col, self, mapping, true);
  5524. if (queryRealChild(curRow, col))
  5525. {
  5526. StringBuffer s;
  5527. getExprECL(curRow->queryChild(col), s);
  5528. ERRORAT1(curRow->queryAttribute(_location_Atom), HQLERR_TooManyInitializers, s.str());
  5529. }
  5530. return ret.getClear();
  5531. }
  5532. //NB: Skating on thin ice - can't call transform() inside here because the mapper has the transform mutex.
  5533. //So don't make it a member function...
  5534. void TempTableTransformer::createTempTableAssign(HqlExprArray & assigns, IHqlExpression * self, IHqlExpression * curRow, IHqlExpression * expr, unsigned & col, IHqlExpression * selector, HqlMapTransformer & mapper, bool included)
  5535. {
  5536. switch (expr->getOperator())
  5537. {
  5538. case no_field:
  5539. {
  5540. OwnedHqlExpr target = createSelectExpr(LINK(selector), LINK(expr));
  5541. OwnedHqlExpr castValue;
  5542. IHqlExpression * record = expr->queryRecord();
  5543. if (record)
  5544. {
  5545. if (included)
  5546. {
  5547. LinkedHqlExpr src = queryRealChild(curRow, col);
  5548. if (expr->isDataset() || expr->isDictionary())
  5549. {
  5550. if (src)
  5551. col++;
  5552. else
  5553. {
  5554. src.set(expr->queryChild(0));
  5555. if (!src || src->isAttribute())
  5556. src.set(queryAttributeChild(expr, defaultAtom, 0));
  5557. if (!src)
  5558. {
  5559. ERRORAT1(curRow->queryAttribute(_location_Atom), HQLERR_NoDefaultProvided, str(expr->queryName()));
  5560. return;
  5561. }
  5562. }
  5563. src.setown(replaceSelfRefSelector(src, self));
  5564. if (src->getOperator() == no_list)
  5565. {
  5566. HqlExprArray children;
  5567. children.append(*LINK(src));
  5568. children.append(*LINK(record));
  5569. OwnedHqlExpr tempTable = createValue(no_temptable, children);
  5570. // castValue.setown(transform(tempTable));
  5571. castValue.set(tempTable);
  5572. }
  5573. else if (src->getOperator() == no_recordlist)
  5574. {
  5575. HqlExprArray transforms;
  5576. ForEachChild(idx, src)
  5577. transforms.append(*createTempTableTransform(src->queryChild(idx), record));
  5578. HqlExprArray children;
  5579. children.append(*createValue(no_transformlist, transforms));
  5580. children.append(*LINK(record));
  5581. castValue.setown(createDataset(no_inlinetable, children));
  5582. }
  5583. else if (src->isDataset())
  5584. {
  5585. if (!recordTypesMatch(src, target))
  5586. {
  5587. ERRORAT1(curRow->queryAttribute(_location_Atom), HQLERR_IncompatibleTypesForField, str(expr->queryName()));
  5588. return;
  5589. }
  5590. if (isGrouped(src))
  5591. castValue.setown(createDataset(no_group, LINK(src)));
  5592. else
  5593. castValue.set(src);
  5594. }
  5595. else
  5596. {
  5597. ERRORAT1(curRow->queryAttribute(_location_Atom), HQLERR_IncompatibleTypesForField, str(expr->queryName()));
  5598. return;
  5599. }
  5600. }
  5601. else
  5602. {
  5603. if (src && src->isDatarow())
  5604. {
  5605. if (!recordTypesMatch(src, target))
  5606. {
  5607. ERRORAT1(curRow->queryAttribute(_location_Atom), HQLERR_IncompatibleTypesForField, str(expr->queryName()));
  5608. return;
  5609. }
  5610. castValue.set(src);
  5611. col++;
  5612. }
  5613. else
  5614. {
  5615. //structured initialisers for nested records...
  5616. OwnedHqlExpr transform;
  5617. if (src && src->getOperator() == no_rowvalue)
  5618. {
  5619. col++;
  5620. transform.setown(createTempTableTransform(src, record));
  5621. }
  5622. else
  5623. {
  5624. OwnedHqlExpr localSelf = getSelf(record);
  5625. HqlMapTransformer localMapping;
  5626. transform.setown(createTempTableTransform(self, curRow, record, col, localSelf, localMapping, true));
  5627. }
  5628. castValue.setown(createRow(no_createrow, LINK(transform)));
  5629. }
  5630. }
  5631. if (target->isDictionary() && !castValue->isDictionary())
  5632. castValue.setown(createDictionary(no_createdictionary, castValue.getClear()));
  5633. }
  5634. else
  5635. {
  5636. if (expr->isDictionary())
  5637. castValue.setown(createDictionary(no_null, LINK(record)));
  5638. else if (expr->isDataset())
  5639. castValue.setown(createDataset(no_null, LINK(record)));
  5640. else
  5641. castValue.setown(createRow(no_null, LINK(record)));
  5642. }
  5643. }
  5644. else
  5645. {
  5646. ITypeInfo * type = expr->queryType()->queryPromotedType();
  5647. if (included)
  5648. {
  5649. LinkedHqlExpr src = queryRealChild(curRow, col++);
  5650. if (!src)
  5651. {
  5652. IHqlExpression * defaultValue = expr->queryChild(0);
  5653. if (!defaultValue || defaultValue->isAttribute())
  5654. defaultValue = queryAttributeChild(expr, defaultAtom, 0);
  5655. src.setown(replaceSelfRefSelector(defaultValue, self));
  5656. if (src)
  5657. src.setown(mapper.transformRoot(src));
  5658. }
  5659. if (!src || src->isAttribute())
  5660. {
  5661. if (expr->hasAttribute(virtualAtom))
  5662. ERRORAT1(curRow->queryAttribute(_location_Atom), HQLERR_VirtualFieldInTempTable, str(expr->queryName()));
  5663. else
  5664. ERRORAT1(curRow->queryAttribute(_location_Atom), HQLERR_NoDefaultProvided, str(expr->queryName()));
  5665. return;
  5666. }
  5667. if (src->getOperator() == no_recordlist)
  5668. {
  5669. ERRORAT1(curRow->queryAttribute(_location_Atom), HQLERR_IncompatiableInitailiser, str(expr->queryName()));
  5670. return;
  5671. }
  5672. else if (type->isScalar() != src->queryType()->isScalar())
  5673. {
  5674. ERRORAT1(curRow->queryAttribute(_location_Atom), HQLERR_IncompatibleTypesForField, str(expr->queryName()));
  5675. return;
  5676. }
  5677. else if (strictTypeChecking && !type->assignableFrom(src->queryType()))
  5678. {
  5679. ERRORAT1(curRow->queryAttribute(_location_Atom), HQLERR_IncompatibleTypesForField, str(expr->queryName()));
  5680. }
  5681. castValue.setown(ensureExprType(src, type));
  5682. }
  5683. else
  5684. castValue.setown(createNullExpr(expr));
  5685. }
  5686. assigns.append(*createAssign(LINK(target), LINK(castValue)));
  5687. mapper.setMapping(target, castValue);
  5688. break;
  5689. }
  5690. case no_ifblock:
  5691. {
  5692. OwnedHqlExpr cond = replaceSelfRefSelector(expr->queryChild(0), selector);
  5693. OwnedHqlExpr mapped = mapper.transformRoot(cond);
  5694. mapped.setown(foldHqlExpression(errorProcessor, mapped, NULL, HFOfoldimpure|HFOforcefold));
  5695. IValue * mappedValue = mapped->queryValue();
  5696. if (included)
  5697. {
  5698. if (!mappedValue)
  5699. reportWarning(CategoryUnexpected, NULL, HQLWRN_CouldNotConstantFoldIf, HQLWRN_CouldNotConstantFoldIf_Text);
  5700. else if (!mappedValue->getBoolValue())
  5701. included = false;
  5702. }
  5703. createTempTableAssign(assigns, self, curRow, expr->queryChild(1), col, selector, mapper, included);
  5704. break;
  5705. }
  5706. case no_record:
  5707. {
  5708. ForEachChild(idx, expr)
  5709. createTempTableAssign(assigns, self, curRow, expr->queryChild(idx), col, selector, mapper, included);
  5710. break;
  5711. }
  5712. case no_attr:
  5713. case no_attr_expr:
  5714. case no_attr_link:
  5715. break;
  5716. }
  5717. }
  5718. void TempTableTransformer::reportError(IHqlExpression * location, int code,const char *format, ...)
  5719. {
  5720. ECLlocation * where = &defaultLocation;
  5721. ECLlocation thisLocation;
  5722. if (location)
  5723. {
  5724. thisLocation.extractLocationAttr(location);
  5725. where = &thisLocation;
  5726. }
  5727. StringBuffer errorMsg;
  5728. va_list args;
  5729. va_start(args, format);
  5730. errorMsg.valist_appendf(format, args);
  5731. va_end(args);
  5732. Owned<IError> err = createError(code, errorMsg.str(), str(where->sourcePath), where->lineno, where->column, where->position);
  5733. errorProcessor.report(err);
  5734. }
  5735. void TempTableTransformer::reportWarning(WarnErrorCategory category, IHqlExpression * location, int code,const char *format, ...)
  5736. {
  5737. ECLlocation * where = &defaultLocation;
  5738. ECLlocation thisLocation;
  5739. if (location)
  5740. {
  5741. thisLocation.extractLocationAttr(location);
  5742. where = &thisLocation;
  5743. }
  5744. StringBuffer errorMsg;
  5745. va_list args;
  5746. va_start(args, format);
  5747. errorMsg.valist_appendf(format, args);
  5748. va_end(args);
  5749. errorProcessor.reportWarning(category, code, errorMsg.str(), str(where->sourcePath), where->lineno, where->column, where->position);
  5750. }
  5751. IHqlExpression *getDictionaryKeyRecord(IHqlExpression *record)
  5752. {
  5753. IHqlExpression * payload = record->queryAttribute(_payload_Atom);
  5754. unsigned payloadSize = payload ? (unsigned)getIntValue(payload->queryChild(0)) : 0;
  5755. unsigned max = record->numChildren() - payloadSize;
  5756. IHqlExpression *newrec = createRecord();
  5757. for (unsigned idx = 0; idx < max; idx++)
  5758. {
  5759. IHqlExpression *child = record->queryChild(idx);
  5760. if (!child->isAttribute() || child->queryName()!=_payload_Atom) // Strip off the payload attribute
  5761. newrec->addOperand(LINK(child));
  5762. }
  5763. return newrec->closeExpr();
  5764. }
  5765. IHqlExpression *recursiveStretchFields(IHqlExpression *record)
  5766. {
  5767. IHqlExpression *newrec = createRecord();
  5768. ForEachChild (idx, record)
  5769. {
  5770. IHqlExpression *child = record->queryChild(idx);
  5771. if (child->getOperator()==no_field)
  5772. {
  5773. ITypeInfo *fieldType = child->queryType();
  5774. switch (fieldType->getTypeCode())
  5775. {
  5776. case type_row:
  5777. {
  5778. OwnedHqlExpr childType = recursiveStretchFields(child->queryRecord());
  5779. newrec->addOperand(createField(child->queryId(), makeRowType(childType->getType()), NULL, NULL));
  5780. break;
  5781. }
  5782. default:
  5783. {
  5784. Owned<ITypeInfo> stretched = getMaxLengthType(fieldType);
  5785. newrec->addOperand(createField(child->queryId(), stretched.getClear(), NULL, NULL));
  5786. break;
  5787. }
  5788. }
  5789. }
  5790. else
  5791. newrec->addOperand(LINK(child));
  5792. }
  5793. return newrec->closeExpr();
  5794. }
  5795. IHqlExpression *getDictionarySearchRecord(IHqlExpression *record)
  5796. {
  5797. OwnedHqlExpr keyrec = getDictionaryKeyRecord(record);
  5798. return recursiveStretchFields(keyrec);
  5799. }
  5800. static IHqlExpression *createTransformFromRowValue(IErrorReceiver & errorProcessor, ECLlocation & location, IHqlExpression *dict, IHqlExpression * rowValue)
  5801. {
  5802. OwnedHqlExpr record = getDictionarySearchRecord(dict->queryRecord());
  5803. TempTableTransformer transformer(errorProcessor, location, true);
  5804. return transformer.createTempTableTransform(rowValue, record);
  5805. }
  5806. IHqlExpression *createRowForDictExpr(IErrorReceiver & errorProcessor, ECLlocation & location, IHqlExpression *expr, IHqlExpression *dict)
  5807. {
  5808. OwnedHqlExpr rowValue = createValue(no_rowvalue, makeNullType(), LINK(expr));
  5809. OwnedHqlExpr newTransform = createTransformFromRowValue(errorProcessor, location, dict, rowValue);
  5810. return createRow(no_createrow, newTransform.getClear());
  5811. }
  5812. IHqlExpression * createSelectMapRow(IErrorReceiver & errorProcessor, ECLlocation & location, IHqlExpression * dict, IHqlExpression *values)
  5813. {
  5814. //Always process the expression and create a row since this also validates the search expression
  5815. OwnedHqlExpr newTransform = createTransformFromRowValue(errorProcessor, location, dict, values);
  5816. //If only a single expression is being looked up then create no_selectmap(dict, expr) instead of no_selectmap(dict, row) to avoid unnecessary aliases.
  5817. if (getFlatFieldCount(newTransform->queryRecord()) == 1)
  5818. return createRow(no_selectmap, LINK(dict), LINK(values->queryChild(0)));
  5819. return createRow(no_selectmap, LINK(dict), createRow(no_createrow, newTransform.getClear()));
  5820. }
  5821. IHqlExpression *createINDictExpr(IErrorReceiver & errorProcessor, ECLlocation & location, IHqlExpression *expr, IHqlExpression *dict)
  5822. {
  5823. //Always process the expression and create a row since this also validates the search expression
  5824. OwnedHqlExpr row = createRowForDictExpr(errorProcessor, location, expr, dict);
  5825. //If only a single expression is being looked up then create no_indict(expr,dict) instead of no_indict(row,dict) to avoid unnecessary row aliases.
  5826. if (getFlatFieldCount(row->queryRecord()) == 1)
  5827. return createBoolExpr(no_indict, LINK(expr), LINK(dict));
  5828. return createBoolExpr(no_indict, LINK(row), LINK(dict));
  5829. }
  5830. IHqlExpression *createINDictRow(IErrorReceiver & errorProcessor, ECLlocation & location, IHqlExpression *row, IHqlExpression *dict)
  5831. {
  5832. OwnedHqlExpr record = getDictionarySearchRecord(dict->queryRecord());
  5833. Owned<ITypeInfo> rowType = makeRowType(record->getType());
  5834. OwnedHqlExpr castRow = ensureExprType(row, rowType);
  5835. return createBoolExpr(no_indict, castRow.getClear(), LINK(dict));
  5836. }
  5837. IHqlExpression * convertTempRowToCreateRow(IErrorReceiver & errorProcessor, ECLlocation & location, IHqlExpression * expr)
  5838. {
  5839. IHqlExpression * oldValues = expr->queryChild(0);
  5840. IHqlExpression * record = expr->queryChild(1);
  5841. OwnedHqlExpr values = normalizeListCasts(oldValues); // ??? not used
  5842. TempTableTransformer transformer(errorProcessor, location);
  5843. OwnedHqlExpr newTransform = transformer.createTempTableTransform(oldValues, record);
  5844. HqlExprArray children;
  5845. children.append(*LINK(newTransform));
  5846. OwnedHqlExpr ret = createRow(no_createrow, children);
  5847. return expr->cloneAllAnnotations(ret);
  5848. }
  5849. static IHqlExpression * convertTempTableToInline(IErrorReceiver & errorProcessor, ECLlocation & location, IHqlExpression * expr)
  5850. {
  5851. IHqlExpression * oldValues = expr->queryChild(0);
  5852. IHqlExpression * record = expr->queryChild(1);
  5853. OwnedHqlExpr values = normalizeListCasts(oldValues);
  5854. node_operator valueOp = values->getOperator();
  5855. if ((valueOp == no_list) && (values->numChildren() == 0))
  5856. return createDataset(no_null, LINK(record));
  5857. if ((valueOp != no_recordlist) && (valueOp != no_list))
  5858. return LINK(expr);
  5859. TempTableTransformer transformer(errorProcessor, location);
  5860. HqlExprArray transforms;
  5861. ForEachChild(idx, values)
  5862. {
  5863. LinkedHqlExpr cur = values->queryChild(idx);
  5864. if (valueOp == no_list)
  5865. cur.setown(createValue(no_rowvalue, makeNullType(), LINK(cur)));
  5866. if (cur->getOperator() == no_record)
  5867. {
  5868. HqlExprArray row;
  5869. ForEachChild(idx, cur)
  5870. {
  5871. IHqlExpression * field = cur->queryChild(idx);
  5872. if (field->getOperator() == no_field)
  5873. {
  5874. IHqlExpression * value = queryRealChild(field, 0);
  5875. if (value)
  5876. row.append(*LINK(value));
  5877. else
  5878. {
  5879. VStringBuffer msg(HQLERR_FieldHasNoDefaultValue_Text, str(field->queryName()));
  5880. errorProcessor.reportError(HQLERR_FieldHasNoDefaultValue, msg.str(), str(location.sourcePath), location.lineno, location.column, location.position);
  5881. }
  5882. }
  5883. }
  5884. cur.setown(createValue(no_rowvalue, makeNullType(), row));
  5885. }
  5886. transforms.append(*transformer.createTempTableTransform(cur, record));
  5887. }
  5888. HqlExprArray children;
  5889. children.append(*createValue(no_transformlist, makeNullType(), transforms));
  5890. children.append(*LINK(record));
  5891. unwindChildren(children, expr, 2);
  5892. OwnedHqlExpr ret = createDataset(no_inlinetable, children);
  5893. return expr->cloneAllAnnotations(ret);
  5894. }
  5895. IHqlExpression * convertTempTableToInlineTable(IErrorReceiver & errors, ECLlocation & location, IHqlExpression * expr)
  5896. {
  5897. return convertTempTableToInline(errors, location, expr);
  5898. }
  5899. void setPayloadAttribute(HqlExprArray &args)
  5900. {
  5901. // Locate a payload attribute in an initializer value list. If found, move it to front and give it a position
  5902. int payloadPos = -1;
  5903. ForEachItemIn(idx, args)
  5904. {
  5905. IHqlExpression *cur = &args.item(idx);
  5906. if (cur->isAttribute())
  5907. {
  5908. assertex(payloadPos==-1);
  5909. assertex(cur->queryName()==_payload_Atom);
  5910. payloadPos = idx;
  5911. }
  5912. }
  5913. if (payloadPos != -1)
  5914. {
  5915. args.remove(payloadPos);
  5916. args.add(*createAttribute(_payload_Atom, createConstant((__int64) args.length()-payloadPos)), 0);
  5917. }
  5918. }
  5919. bool areTypesComparable(ITypeInfo * leftType, ITypeInfo * rightType)
  5920. {
  5921. if (leftType == rightType)
  5922. return true;
  5923. if (!leftType || !rightType)
  5924. return false;
  5925. type_t ltc = leftType->getTypeCode();
  5926. type_t rtc = rightType->getTypeCode();
  5927. if (ltc != rtc)
  5928. return false;
  5929. switch (ltc)
  5930. {
  5931. case type_unicode:
  5932. case type_varunicode:
  5933. case type_utf8:
  5934. return haveCommonLocale(leftType, rightType);
  5935. case type_data:
  5936. case type_decimal:
  5937. return true;
  5938. case type_qstring:
  5939. case type_varstring:
  5940. case type_string:
  5941. return (leftType->queryCharset() == rightType->queryCharset()) &&
  5942. (leftType->queryCollation() == rightType->queryCollation());
  5943. case type_set:
  5944. case type_array:
  5945. return areTypesComparable(leftType->queryChildType(), rightType->queryChildType());
  5946. case type_row:
  5947. case type_dictionary:
  5948. case type_table:
  5949. case type_groupedtable:
  5950. return recordTypesMatch(leftType, rightType);
  5951. }
  5952. return false;
  5953. }
  5954. bool arraysMatch(const HqlExprArray & left, const HqlExprArray & right)
  5955. {
  5956. unsigned numLeft = left.ordinality();
  5957. unsigned numRight = right.ordinality();
  5958. if (numLeft != numRight)
  5959. return false;
  5960. for (unsigned i=0; i < numLeft; i++)
  5961. {
  5962. if (&left.item(i) != &right.item(i))
  5963. return false;
  5964. }
  5965. return true;
  5966. }
  5967. bool isBlankString(IHqlExpression * expr)
  5968. {
  5969. if (expr->getOperator() != no_constant)
  5970. return false;
  5971. IValue * value = expr->queryValue();
  5972. if (value->getTypeCode() != type_string)
  5973. return false;
  5974. unsigned size = value->getSize();
  5975. return rtlCompareStrBlank(size, (const char *)value->queryValue()) == 0;
  5976. }
  5977. bool isNullString(IHqlExpression * expr)
  5978. {
  5979. ITypeInfo * exprType = expr->queryType();
  5980. switch (exprType->getTypeCode())
  5981. {
  5982. case type_data:
  5983. case type_string:
  5984. case type_qstring:
  5985. return exprType->getSize() == 0;
  5986. }
  5987. return false;
  5988. }
  5989. const char * queryChildNodeTraceText(StringBuffer & s, IHqlExpression * expr)
  5990. {
  5991. s.clear().append(getOpString(expr->getOperator()));
  5992. if (expr->queryName())
  5993. s.append("[").append(expr->queryName()).append("]");
  5994. // s.appendf(" {%lx}", (unsigned)expr);
  5995. return s.str();
  5996. }
  5997. extern HQL_API bool areConstant(const HqlExprArray & args)
  5998. {
  5999. ForEachItemIn(i, args)
  6000. {
  6001. if (!args.item(i).isConstant())
  6002. return false;
  6003. }
  6004. return true;
  6005. }
  6006. bool getFoldedConstantText(StringBuffer& ret, IHqlExpression * expr)
  6007. {
  6008. OwnedHqlExpr folded = foldExprIfConstant(expr);
  6009. IValue * value = folded->queryValue();
  6010. if (!value)
  6011. return false;
  6012. value->getStringValue(ret);
  6013. return true;
  6014. }
  6015. //===========================================================================
  6016. void appendArray(HqlExprCopyArray & tgt, const HqlExprCopyArray & src)
  6017. {
  6018. ForEachItemIn(idx, src)
  6019. tgt.append(src.item(idx));
  6020. }
  6021. void appendArray(HqlExprCopyArray & tgt, const HqlExprArray & src)
  6022. {
  6023. ForEachItemIn(idx, src)
  6024. tgt.append(src.item(idx));
  6025. }
  6026. void replaceArray(HqlExprArray & tgt, const HqlExprArray & src)
  6027. {
  6028. tgt.kill();
  6029. appendArray(tgt, src);
  6030. }
  6031. //--------------------------------------------------------------
  6032. static void gatherSortOrder(HqlExprArray & sorts, IHqlExpression * ds, IHqlExpression * record, unsigned maxfield = NotFound)
  6033. {
  6034. unsigned max = record->numChildren();
  6035. if (max > maxfield) max = maxfield;
  6036. for (unsigned idx=0; idx < max; idx++)
  6037. {
  6038. IHqlExpression * cur = record->queryChild(idx);
  6039. switch (cur->getOperator())
  6040. {
  6041. case no_record:
  6042. gatherSortOrder(sorts, ds, cur);
  6043. break;
  6044. case no_ifblock:
  6045. gatherSortOrder(sorts, ds, cur->queryChild(1));
  6046. break;
  6047. case no_field:
  6048. sorts.append(*createSelectExpr(LINK(ds), LINK(cur)));
  6049. break;
  6050. }
  6051. }
  6052. }
  6053. void gatherIndexBuildSortOrder(HqlExprArray & sorts, IHqlExpression * expr, bool sortIndexPayload)
  6054. {
  6055. // If any field types collate differently before and after translation to their hozed
  6056. // format, then we need to do the translation here, otherwise this
  6057. // sort may not be in the correct order. (ebcdic->ascii? integers are ok; unicode isn't!)
  6058. // First build the sort order we need....
  6059. LinkedHqlExpr dataset = expr->queryChild(0);
  6060. IHqlExpression * normalizedDs = dataset->queryNormalizedSelector();
  6061. IHqlExpression * buildRecord = dataset->queryRecord();
  6062. unsigned payloadCount = numPayloadFields(expr);
  6063. //Option to not sort by fields that aren't part of the sorted key.
  6064. unsigned indexFirstPayload = firstPayloadField(buildRecord, payloadCount);
  6065. unsigned max;
  6066. bool sortPayload = sortIndexPayload ? !expr->hasAttribute(sort_KeyedAtom) : expr->hasAttribute(sort_AllAtom);
  6067. if (sortPayload)
  6068. {
  6069. max = buildRecord->numChildren();
  6070. //If the last field is an implicit fpos, then they will all have the same value, so no point sorting.
  6071. if (queryLastField(buildRecord)->hasAttribute(_implicitFpos_Atom))
  6072. max--;
  6073. }
  6074. else
  6075. max = indexFirstPayload;
  6076. gatherSortOrder(sorts, normalizedDs, buildRecord, max);
  6077. ForEachItemIn(i0, sorts)
  6078. {
  6079. IHqlExpression & cur = sorts.item(i0);
  6080. if (cur.isDataset())
  6081. {
  6082. sorts.replace(*createValue(no_typetransfer, makeDataType(UNKNOWN_LENGTH), LINK(&cur)), i0);
  6083. }
  6084. else if ((i0 < indexFirstPayload) && isUnicodeType(cur.queryType()))
  6085. {
  6086. sorts.replace(*createValue(no_typetransfer, makeDataType(cur.queryType()->getSize()), LINK(&cur)), i0);
  6087. }
  6088. }
  6089. }
  6090. //------------------------- Library processing -------------------------------------
  6091. int compareLibraryParameterOrder(IHqlExpression * left, IHqlExpression * right)
  6092. {
  6093. //datasets come first - even if not streamed
  6094. if (left->isDataset())
  6095. {
  6096. if (!right->isDataset())
  6097. return -1;
  6098. }
  6099. else
  6100. {
  6101. if (right->isDataset())
  6102. return +1;
  6103. }
  6104. //Then fixed size fields - to minimize the code generated to access them
  6105. if (left->queryType()->getSize() == UNKNOWN_LENGTH)
  6106. {
  6107. if (right->queryType()->getSize() != UNKNOWN_LENGTH)
  6108. return +1;
  6109. }
  6110. else
  6111. {
  6112. if (right->queryType()->getSize() == UNKNOWN_LENGTH)
  6113. return -1;
  6114. }
  6115. //then by name
  6116. return stricmp(str(left->queryName()), str(right->queryName()));
  6117. }
  6118. static int compareLibraryParameterOrder(IInterface * const * pleft, IInterface * const * pright)
  6119. {
  6120. IHqlExpression * left = static_cast<IHqlExpression *>(*pleft);
  6121. IHqlExpression * right = static_cast<IHqlExpression *>(*pright);
  6122. return compareLibraryParameterOrder(left, right);
  6123. }
  6124. LibraryInputMapper::LibraryInputMapper(IHqlExpression * _libraryInterface)
  6125. : libraryInterface(_libraryInterface)
  6126. {
  6127. assertex(libraryInterface->getOperator() == no_funcdef);
  6128. scopeExpr.set(libraryInterface->queryChild(0));
  6129. streamingAllowed = !scopeExpr->hasAttribute(_noStreaming_Atom); // ?? is this in the correct place, probably, just nasty
  6130. expandParameters();
  6131. }
  6132. void LibraryInputMapper::expandParameters()
  6133. {
  6134. IHqlExpression * formals = libraryInterface->queryChild(1);
  6135. unsigned nextParameter = formals->numChildren()+1;
  6136. ForEachChild(i, formals)
  6137. expandParameter(formals->queryChild(i), nextParameter);
  6138. realParameters.sort(compareLibraryParameterOrder);
  6139. //Count number of datasets (always at the front), so can use to adjust library counts when streaming
  6140. numDatasets = 0;
  6141. while ((numDatasets < realParameters.ordinality()) && realParameters.item(numDatasets).isDataset())
  6142. numDatasets++;
  6143. }
  6144. void LibraryInputMapper::expandParameter(IHqlExpression * expr, unsigned & nextParameter)
  6145. {
  6146. if (expr->isScope())
  6147. {
  6148. IHqlScope * scope = expr->queryScope();
  6149. HqlExprArray symbols;
  6150. scope->getSymbols(symbols);
  6151. ForEachItemIn(i, symbols)
  6152. {
  6153. IHqlExpression & cur = symbols.item(i);
  6154. IIdAtom * nestedName = createMangledName(expr, &cur);
  6155. //default values are handled elsewhere - lost from the mapped values here.
  6156. HqlExprArray attrs;
  6157. OwnedHqlExpr renamed = createParameter(nestedName, nextParameter++, cur.getType(), attrs);
  6158. expandParameter(renamed, nextParameter);
  6159. }
  6160. }
  6161. else
  6162. realParameters.append(*LINK(expr));
  6163. }
  6164. unsigned LibraryInputMapper::findParameter(IIdAtom * searchId)
  6165. {
  6166. IAtom * searchName = lower(searchId);
  6167. ForEachItemIn(i, realParameters)
  6168. {
  6169. if (realParameters.item(i).queryName() == searchName)
  6170. return i;
  6171. }
  6172. return NotFound;
  6173. }
  6174. IHqlExpression * LibraryInputMapper::resolveParameter(IIdAtom * search)
  6175. {
  6176. unsigned match = findParameter(search);
  6177. assertex(match != NotFound);
  6178. return &realParameters.item(match);
  6179. }
  6180. void LibraryInputMapper::mapRealToLogical(HqlExprArray & inputExprs, HqlExprArray & logicalParams, IHqlExpression * libraryId, bool canStream, bool distributed)
  6181. {
  6182. //Create a list of expressions representing each of the inputs...
  6183. ForEachItemIn(i1, realParameters)
  6184. {
  6185. IHqlExpression * cur = &realParameters.item(i1);
  6186. IHqlExpression * result = NULL;
  6187. unsigned inputIndex = i1;
  6188. if (canStream && streamingAllowed)
  6189. {
  6190. if (cur->isDataset())
  6191. {
  6192. HqlExprArray args;
  6193. args.append(*LINK(cur->queryRecord()));
  6194. args.append(*LINK(libraryId));
  6195. args.append(*getSizetConstant(inputIndex));
  6196. args.append(*createAttribute(_streaming_Atom));
  6197. if (isGrouped(cur))
  6198. args.append(*createAttribute(groupedAtom));
  6199. if (distributed)
  6200. args.append(*createAttribute(_distributed_Atom));
  6201. result = createDataset(no_getgraphresult, args);
  6202. }
  6203. else
  6204. inputIndex -= numDatasets;
  6205. }
  6206. if (!result)
  6207. {
  6208. IHqlExpression * seq = getSizetConstant(inputIndex);
  6209. if (cur->isDataset())
  6210. {
  6211. IHqlExpression * groupAttr = isGrouped(cur) ? createAttribute(groupedAtom) : NULL;
  6212. result = createDataset(no_libraryinput, LINK(cur->queryRecord()), createComma(seq, groupAttr));
  6213. }
  6214. else if (cur->isDatarow())
  6215. result = createDataset(no_libraryinput, LINK(cur->queryRecord()), seq); // should this be a row?
  6216. else
  6217. result = createValue(no_libraryinput, cur->getType(), seq);
  6218. }
  6219. inputExprs.append(*createSymbol(cur->queryId(), result, ob_private));
  6220. }
  6221. IHqlExpression * formals = libraryInterface->queryChild(1);
  6222. ForEachChild(i, formals)
  6223. logicalParams.append(*mapRealToLogical(inputExprs, formals->queryChild(i), libraryId));
  6224. }
  6225. IHqlExpression * LibraryInputMapper::mapRealToLogical(const HqlExprArray & inputExprs, IHqlExpression * expr, IHqlExpression * libraryId)
  6226. {
  6227. if (expr->isScope())
  6228. {
  6229. IHqlScope * scope = expr->queryScope();
  6230. HqlExprArray symbols;
  6231. scope->getSymbols(symbols);
  6232. Owned<IHqlScope> newScope = createVirtualScope();
  6233. ForEachItemIn(i, symbols)
  6234. {
  6235. IHqlExpression & cur = symbols.item(i);
  6236. IHqlExpression * param = resolveParameter(createMangledName(expr, &cur));
  6237. OwnedHqlExpr mapped = mapRealToLogical(inputExprs, param, libraryId);
  6238. OwnedHqlExpr named = createSymbol(cur.queryId(), LINK(mapped), ob_private);
  6239. newScope->defineSymbol(named.getClear());
  6240. }
  6241. return queryExpression(closeScope(newScope.getClear()));
  6242. }
  6243. else
  6244. {
  6245. unsigned inputIndex = realParameters.find(*expr);
  6246. return LINK(&inputExprs.item(inputIndex));
  6247. }
  6248. }
  6249. void LibraryInputMapper::mapLogicalToReal(HqlExprArray & mapped, HqlExprArray & params)
  6250. {
  6251. IHqlExpression * placeholder = queryActiveTableSelector();
  6252. ForEachItemIn(i1, realParameters)
  6253. mapped.append(*LINK(placeholder));
  6254. IHqlExpression * formals = libraryInterface->queryChild(1);
  6255. ForEachChild(i, formals)
  6256. mapLogicalToReal(mapped, formals->queryChild(i), &params.item(i));
  6257. }
  6258. void LibraryInputMapper::mapLogicalToReal(HqlExprArray & mapped, IHqlExpression * expr, IHqlExpression * value)
  6259. {
  6260. if (expr->isScope())
  6261. {
  6262. IHqlScope * scope = expr->queryScope();
  6263. IHqlScope * valueScope = value->queryScope();
  6264. HqlExprArray symbols;
  6265. scope->getSymbols(symbols);
  6266. HqlDummyLookupContext lookupCtx(NULL);
  6267. ForEachItemIn(i, symbols)
  6268. {
  6269. IHqlExpression & cur = symbols.item(i);
  6270. IHqlExpression * param = resolveParameter(createMangledName(expr, &cur));
  6271. OwnedHqlExpr childValue = valueScope->lookupSymbol(cur.queryId(), LSFpublic, lookupCtx);
  6272. mapLogicalToReal(mapped, param, childValue);
  6273. }
  6274. }
  6275. else
  6276. {
  6277. //Replace the real parameter at the appropriate position
  6278. unsigned match = realParameters.find(*expr);
  6279. assertex(match != NotFound);
  6280. mapped.replace(*LINK(value), match);
  6281. }
  6282. }
  6283. static byte key[32] = {
  6284. 0xf7, 0xe8, 0x79, 0x40, 0x44, 0x16, 0x66, 0x18, 0x52, 0xb8, 0x18, 0x6e, 0x77, 0xd1, 0x68, 0xd3,
  6285. 0x87, 0x47, 0x01, 0xe6, 0x66, 0x62, 0x2f, 0xbe, 0xc1, 0xd5, 0x9f, 0x4a, 0x53, 0x27, 0xae, 0xa1,
  6286. };
  6287. extern HQL_API void encryptEclAttribute(IStringVal & out, size32_t len, const void * in)
  6288. {
  6289. MemoryBuffer encrypted;
  6290. aesEncrypt(key, sizeof(key), in, len, encrypted);
  6291. StringBuffer base64;
  6292. JBASE64_Encode(encrypted.toByteArray(), encrypted.length(), base64, false);
  6293. StringBuffer text;
  6294. text.append("ENC").append('R').append('Y').append("PTE").append("D(").newline();
  6295. const char * base64Text = base64.str();
  6296. unsigned max = base64.length();
  6297. const unsigned chunk = 60;
  6298. unsigned i;
  6299. for (i = 0; i + chunk < max; i += chunk)
  6300. {
  6301. text.append('\t').append("'").append(chunk, base64Text+i).append("',").newline();
  6302. }
  6303. text.append('\t').append("'").append(max-i, base64Text+i).append("'").newline().append(");").newline();
  6304. out.set(text.str());
  6305. }
  6306. void decryptEclAttribute(MemoryBuffer & out, const char * in)
  6307. {
  6308. StringBuffer decoded;
  6309. JBASE64_Decode(in, decoded);
  6310. aesDecrypt(key, sizeof(key), decoded.str(), decoded.length(), out);
  6311. }
  6312. //---------------------------------------------------------------------------
  6313. class HQL_API GraphIdCollector : public NewHqlTransformer
  6314. {
  6315. public:
  6316. GraphIdCollector(HqlExprCopyArray & _graphs, bool _externalIds);
  6317. virtual void analyseExpr(IHqlExpression * expr);
  6318. protected:
  6319. HqlExprCopyArray & graphs;
  6320. bool externalIds;
  6321. };
  6322. static HqlTransformerInfo hqlGraphIdCollectorInfo("GraphIdCollector");
  6323. GraphIdCollector::GraphIdCollector(HqlExprCopyArray & _graphs, bool _externalIds)
  6324. : NewHqlTransformer(hqlGraphIdCollectorInfo), graphs(_graphs), externalIds(_externalIds)
  6325. {
  6326. }
  6327. void GraphIdCollector::analyseExpr(IHqlExpression * expr)
  6328. {
  6329. if (alreadyVisited(expr))
  6330. return;
  6331. switch (expr->getOperator())
  6332. {
  6333. case no_loopcounter:
  6334. if (!externalIds)
  6335. graphs.append(*expr->queryChild(0));
  6336. return;
  6337. case no_getgraphresult:
  6338. if (externalIds)
  6339. {
  6340. IHqlExpression * id = queryAttributeChild(expr, externalAtom, 0);
  6341. if (id)
  6342. graphs.append(*id);
  6343. }
  6344. else
  6345. graphs.append(*expr->queryChild(1));
  6346. return;
  6347. }
  6348. NewHqlTransformer::analyseExpr(expr);
  6349. }
  6350. void gatherGraphReferences(HqlExprCopyArray & graphs, IHqlExpression * value, bool externalIds)
  6351. {
  6352. GraphIdCollector collector(graphs, externalIds);
  6353. collector.analyse(value, 0);
  6354. }
  6355. //---------------------------------------------------------------------------
  6356. static ErrorSeverity getWarningAction(unsigned errorCode, const HqlExprArray & overrides, unsigned first, ErrorSeverity defaultSeverity)
  6357. {
  6358. //warnings are assumed to be infrequent, so don't worry about efficiency here.
  6359. const unsigned max = overrides.ordinality();
  6360. for (unsigned i=first; i < max; i++)
  6361. {
  6362. IHqlExpression & cur = overrides.item(i);
  6363. if (matchesConstantValue(cur.queryChild(0), errorCode))
  6364. return getCheckSeverity(cur.queryChild(1)->queryName());
  6365. }
  6366. return defaultSeverity;
  6367. }
  6368. //---------------------------------------------------------------------------
  6369. ErrorSeverityMapper::ErrorSeverityMapper(IErrorReceiver & _errorProcessor) : IndirectErrorReceiver(_errorProcessor)
  6370. {
  6371. firstActiveMapping = 0;
  6372. activeSymbol = NULL;
  6373. for (unsigned category = 0; category < CategoryMax; category++)
  6374. categoryAction[category] = SeverityUnknown;
  6375. }
  6376. bool ErrorSeverityMapper::addCommandLineMapping(const char * mapping)
  6377. {
  6378. if (!mapping)
  6379. return true;
  6380. unsigned len = strlen(mapping);
  6381. if (len == 0)
  6382. return true;
  6383. const char * equals = strchr(mapping, '=');
  6384. const char * value;
  6385. if (equals)
  6386. {
  6387. value = equals+1;
  6388. len = equals-mapping;
  6389. }
  6390. else if (mapping[len-1] == '+')
  6391. {
  6392. len--;
  6393. value = "error";
  6394. }
  6395. else if (mapping[len-1] == '-')
  6396. {
  6397. value = "ignore";
  6398. len--;
  6399. }
  6400. else
  6401. value = "error";
  6402. StringAttr category(mapping, len);
  6403. return addMapping(category, value);
  6404. }
  6405. bool ErrorSeverityMapper::addMapping(const char * category, const char * value)
  6406. {
  6407. if (!category || !*category)
  6408. {
  6409. ERRLOG("Error: No warning category supplied");
  6410. return false;
  6411. }
  6412. //Ignore mappings with no action
  6413. if (!value || !*value)
  6414. return true;
  6415. IAtom * action = createAtom(value);
  6416. ErrorSeverity severity = getSeverity(action);
  6417. if (severity == SeverityUnknown)
  6418. {
  6419. ERRLOG("Error: Invalid warning severity '%s'", value);
  6420. return false;
  6421. }
  6422. if (isdigit(*category))
  6423. {
  6424. unsigned errorCode = atoi(category);
  6425. addOnWarning(errorCode, action);
  6426. return true;
  6427. }
  6428. WarnErrorCategory cat = getCategory(category);
  6429. if (cat != CategoryUnknown)
  6430. {
  6431. categoryAction[cat] = severity;
  6432. return true;
  6433. }
  6434. ERRLOG("Error: Mapping doesn't specify a valid warning code or category '%s'", category);
  6435. return false;
  6436. }
  6437. void ErrorSeverityMapper::addOnWarning(unsigned code, IAtom * action)
  6438. {
  6439. severityMappings.append(*createAttribute(onWarningAtom, getSizetConstant(code), createAttribute(action)));
  6440. }
  6441. void ErrorSeverityMapper::addOnWarning(IHqlExpression * setMetaExpr)
  6442. {
  6443. IHqlExpression * code = setMetaExpr->queryChild(1);
  6444. IHqlExpression * action = setMetaExpr->queryChild(2);
  6445. if (isStringType(code->queryType()))
  6446. {
  6447. StringBuffer text;
  6448. getStringValue(text, code, NULL);
  6449. WarnErrorCategory cat = getCategory(text);
  6450. ErrorSeverity severity = getSeverity(action->queryName());
  6451. if (cat == CategoryUnknown)
  6452. throwError1(HQLERR_InvalidErrorCategory, text.str());
  6453. categoryAction[cat] = severity;
  6454. }
  6455. else
  6456. {
  6457. severityMappings.append(*createAttribute(onWarningAtom, LINK(code), LINK(action)));
  6458. }
  6459. }
  6460. unsigned ErrorSeverityMapper::processMetaAnnotation(IHqlExpression * expr)
  6461. {
  6462. unsigned prevMax = severityMappings.ordinality();
  6463. gatherMetaAttributes(severityMappings, onWarningAtom, expr);
  6464. return prevMax;
  6465. }
  6466. void ErrorSeverityMapper::restoreLocalOnWarnings(unsigned prevMax)
  6467. {
  6468. severityMappings.trunc(prevMax);
  6469. }
  6470. void ErrorSeverityMapper::pushSymbol(ErrorSeverityMapperState & saved, IHqlExpression * _symbol)
  6471. {
  6472. saveState(saved);
  6473. setSymbol(_symbol);
  6474. }
  6475. void ErrorSeverityMapper::saveState(ErrorSeverityMapperState & saved) const
  6476. {
  6477. saved.firstActiveMapping = firstActiveMapping;
  6478. saved.maxMappings = severityMappings.ordinality();
  6479. saved.symbol = activeSymbol;
  6480. }
  6481. void ErrorSeverityMapper::setSymbol(IHqlExpression * _symbol)
  6482. {
  6483. firstActiveMapping = severityMappings.ordinality();
  6484. activeSymbol = _symbol;
  6485. }
  6486. void ErrorSeverityMapper::restoreState(const ErrorSeverityMapperState & saved)
  6487. {
  6488. severityMappings.trunc(saved.maxMappings);
  6489. firstActiveMapping = saved.firstActiveMapping;
  6490. activeSymbol = saved.symbol;
  6491. }
  6492. void ErrorSeverityMapper::exportMappings(IWorkUnit * wu) const
  6493. {
  6494. IndirectErrorReceiver::exportMappings(wu);
  6495. const unsigned max = severityMappings.ordinality();
  6496. for (unsigned i=firstActiveMapping; i < max; i++)
  6497. {
  6498. IHqlExpression & cur = severityMappings.item(i);
  6499. wu->setWarningSeverity((unsigned)getIntValue(cur.queryChild(0)), getCheckSeverity(cur.queryChild(1)->queryName()));
  6500. }
  6501. }
  6502. IError * ErrorSeverityMapper::mapError(IError * error)
  6503. {
  6504. //An error that is fatal cannot be mapped.
  6505. Owned<IError> mappedError = IndirectErrorReceiver::mapError(error);
  6506. if (!isFatal(mappedError))
  6507. {
  6508. //This takes precedence over mappings in the parent
  6509. ErrorSeverity newSeverity = getWarningAction(mappedError->errorCode(), severityMappings, firstActiveMapping, SeverityUnknown);
  6510. if (newSeverity != SeverityUnknown)
  6511. return mappedError->cloneSetSeverity(newSeverity);
  6512. WarnErrorCategory category = mappedError->getCategory();
  6513. if (categoryAction[category] != SeverityUnknown)
  6514. return mappedError->cloneSetSeverity(categoryAction[category]);
  6515. if (categoryAction[CategoryAll] != SeverityUnknown)
  6516. return mappedError->cloneSetSeverity(categoryAction[CategoryAll]);
  6517. }
  6518. return mappedError.getClear();
  6519. }
  6520. //---------------------------------------------------------------------------------------------------------------------
  6521. bool isGlobalOnWarning(IHqlExpression * expr)
  6522. {
  6523. return ((expr->getOperator() == no_setmeta) && (expr->queryChild(0)->queryName() == onWarningAtom));
  6524. }
  6525. //---------------------------------------------------------------------------
  6526. static HqlTransformerInfo globalOnWarningCollectorInfo("GlobalOnWarningCollector");
  6527. class GlobalOnWarningCollector : public QuickHqlTransformer
  6528. {
  6529. public:
  6530. GlobalOnWarningCollector(ErrorSeverityMapper & _mapper) :
  6531. QuickHqlTransformer(globalOnWarningCollectorInfo, NULL), mapper(_mapper)
  6532. {
  6533. }
  6534. virtual void doAnalyse(IHqlExpression * expr)
  6535. {
  6536. IHqlExpression * body = expr->queryBody();
  6537. //Ugly... If the syntax check is called on something containing a forward module then this code
  6538. //might be called with a placeholder symbol (which has a NULL body).
  6539. if (!body)
  6540. return;
  6541. if (isGlobalOnWarning(body))
  6542. mapper.addOnWarning(body);
  6543. QuickHqlTransformer::doAnalyse(body);
  6544. }
  6545. protected:
  6546. ErrorSeverityMapper & mapper;
  6547. };
  6548. static HqlTransformerInfo warningCollectingTransformerInfo("WarningCollectingTransformer");
  6549. class WarningCollectingTransformer : public QuickHqlTransformer
  6550. {
  6551. public:
  6552. WarningCollectingTransformer(IErrorReceiver & _errs) :
  6553. QuickHqlTransformer(warningCollectingTransformerInfo, &_errs), mapper(_errs)
  6554. {
  6555. }
  6556. virtual void doAnalyse(IHqlExpression * expr)
  6557. {
  6558. switch (expr->getAnnotationKind())
  6559. {
  6560. case annotate_meta:
  6561. {
  6562. unsigned max = mapper.processMetaAnnotation(expr);
  6563. QuickHqlTransformer::doAnalyse(expr);
  6564. mapper.restoreLocalOnWarnings(max);
  6565. return;
  6566. }
  6567. case annotate_warning:
  6568. {
  6569. IError * error = static_cast<CHqlWarningAnnotation *>(expr)->queryWarning();
  6570. Owned<IError> mappedError = mapper.mapError(error);
  6571. mapper.report(mappedError);
  6572. break;
  6573. }
  6574. case annotate_symbol:
  6575. {
  6576. ErrorSeverityMapper::SymbolScope saved(mapper, expr);
  6577. QuickHqlTransformer::doAnalyse(expr);
  6578. return;
  6579. }
  6580. }
  6581. QuickHqlTransformer::doAnalyse(expr);
  6582. }
  6583. protected:
  6584. ErrorSeverityMapper mapper;
  6585. };
  6586. void gatherParseWarnings(IErrorReceiver * errs, IHqlExpression * expr, IErrorArray & orphanedWarnings)
  6587. {
  6588. if (!errs || !expr)
  6589. return;
  6590. Owned<IErrorReceiver> deduper = createDedupingErrorReceiver(*errs);
  6591. //First collect any #ONWARNINGs held in the parsed expression tree
  6592. Owned<ErrorSeverityMapper> globalOnWarning = new ErrorSeverityMapper(*deduper);
  6593. GlobalOnWarningCollector globalCollector(*globalOnWarning);
  6594. globalCollector.analyse(expr);
  6595. //Now walk all expressions, outputting warnings and processing local onWarnings
  6596. WarningCollectingTransformer warningCollector(*globalOnWarning);
  6597. warningCollector.analyse(expr);
  6598. ForEachItemIn(i, orphanedWarnings)
  6599. {
  6600. Owned<IError> mappedError = globalOnWarning->mapError(&orphanedWarnings.item(i));
  6601. globalOnWarning->report(mappedError);
  6602. }
  6603. }
  6604. //---------------------------------------------------------------------------
  6605. bool isActiveRow(IHqlExpression * expr)
  6606. {
  6607. switch (expr->getOperator())
  6608. {
  6609. case no_select:
  6610. return !isNewSelector(expr);
  6611. default:
  6612. return isAlwaysActiveRow(expr);
  6613. }
  6614. }
  6615. StringBuffer & convertToValidLabel(StringBuffer &out, const char * in, unsigned inlen)
  6616. {
  6617. for (unsigned o = 0; o < inlen; o++)
  6618. {
  6619. unsigned char c = in[o];
  6620. if (isalnum(c))
  6621. out.append(c);
  6622. else
  6623. out.append('_');
  6624. }
  6625. return out;
  6626. }
  6627. template <class ARRAY>
  6628. bool doArraysSame(ARRAY & left, ARRAY & right)
  6629. {
  6630. if (left.ordinality() != right.ordinality())
  6631. return false;
  6632. return memcmp(left.getArray(), right.getArray(), left.ordinality() * sizeof(CInterface*)) == 0;
  6633. }
  6634. bool arraysSame(HqlExprArray & left, HqlExprArray & right)
  6635. {
  6636. return doArraysSame(left, right);
  6637. }
  6638. bool arraysSame(HqlExprCopyArray & left, HqlExprCopyArray & right)
  6639. {
  6640. return doArraysSame(left, right);
  6641. }
  6642. bool isFailAction(IHqlExpression * expr)
  6643. {
  6644. return expr && (expr->getOperator() == no_fail);
  6645. }
  6646. bool isFailureGuard(IHqlExpression * expr)
  6647. {
  6648. if (expr->getOperator() == no_if)
  6649. return isFailAction(expr->queryChild(1)) || isFailAction(expr->queryChild(2));
  6650. return false;
  6651. }
  6652. extern HQL_API bool isKeyedDataset(IHqlExpression * expr)
  6653. {
  6654. switch (expr->getOperator())
  6655. {
  6656. case no_keyedlimit:
  6657. return true;
  6658. case no_filter:
  6659. return filterIsKeyed(expr);
  6660. case no_hqlproject:
  6661. case no_newusertable:
  6662. case no_aggregate:
  6663. case no_newaggregate:
  6664. return expr->hasAttribute(keyedAtom);
  6665. }
  6666. return false;
  6667. }
  6668. extern HQL_API bool isSteppedDataset(IHqlExpression * expr)
  6669. {
  6670. switch (expr->getOperator())
  6671. {
  6672. case no_stepped:
  6673. case no_mergejoin:
  6674. case no_nwayjoin:
  6675. return true;
  6676. }
  6677. return false;
  6678. }
  6679. extern HQL_API IHqlExpression * queryFieldFromExpr(IHqlExpression * expr)
  6680. {
  6681. for (;;)
  6682. {
  6683. switch (expr->getOperator())
  6684. {
  6685. case no_field:
  6686. return expr;
  6687. case no_indirect:
  6688. expr = expr->queryChild(0);
  6689. break;
  6690. case no_select:
  6691. expr = expr->queryChild(1);
  6692. break;
  6693. default:
  6694. return expr;
  6695. }
  6696. }
  6697. }
  6698. extern HQL_API IHqlExpression * queryFieldFromSelect(IHqlExpression * expr)
  6699. {
  6700. IHqlExpression * ret = queryFieldFromExpr(expr);
  6701. assertex(ret->getOperator() == no_field);
  6702. return ret;
  6703. }
  6704. extern HQL_API bool isValidFieldReference(IHqlExpression * expr)
  6705. {
  6706. switch (expr->getOperator())
  6707. {
  6708. case no_select:
  6709. case no_field:
  6710. case no_indirect:
  6711. return true;
  6712. case no_param:
  6713. return expr->hasAttribute(fieldAtom);
  6714. }
  6715. return false;
  6716. }
  6717. extern HQL_API bool isFieldSelectedFromRecord(IHqlExpression * expr)
  6718. {
  6719. switch (expr->getOperator())
  6720. {
  6721. case no_select:
  6722. case no_indirect:
  6723. expr = expr->queryChild(0);
  6724. break;
  6725. default:
  6726. return false;
  6727. }
  6728. for (;;)
  6729. {
  6730. switch (expr->getOperator())
  6731. {
  6732. case no_record:
  6733. return true;
  6734. case no_select:
  6735. case no_indirect:
  6736. expr = expr->queryChild(0);
  6737. break;
  6738. default:
  6739. return false;
  6740. }
  6741. }
  6742. }
  6743. void createClearAssigns(HqlExprArray & assigns, IHqlExpression * record, IHqlExpression * targetSelector)
  6744. {
  6745. ForEachChild(idx, record)
  6746. {
  6747. IHqlExpression * field = record->queryChild(idx);
  6748. switch (field->getOperator())
  6749. {
  6750. case no_ifblock:
  6751. createClearAssigns(assigns, field->queryChild(1), targetSelector);
  6752. break;
  6753. case no_record:
  6754. createClearAssigns(assigns, field, targetSelector);
  6755. break;
  6756. case no_field:
  6757. {
  6758. OwnedHqlExpr newTargetSelector = createSelectExpr(LINK(targetSelector), LINK(field));
  6759. IHqlExpression * value = createNullExpr(newTargetSelector);
  6760. assigns.append(*createAssign(LINK(newTargetSelector), value));
  6761. break;
  6762. }
  6763. case no_attr:
  6764. case no_attr_link:
  6765. case no_attr_expr:
  6766. break;
  6767. }
  6768. }
  6769. }
  6770. IHqlExpression * createClearTransform(IHqlExpression * record)
  6771. {
  6772. HqlExprArray assigns;
  6773. OwnedHqlExpr self = getSelf(record);
  6774. createClearAssigns(assigns, record, self);
  6775. return createValue(no_transform, makeTransformType(record->getType()), assigns);
  6776. }
  6777. IHqlExpression * createDefaultAssertMessage(IHqlExpression * cond)
  6778. {
  6779. if (cond->getOperator() == no_assertconstant)
  6780. {
  6781. OwnedHqlExpr msg = createDefaultAssertMessage(cond->queryChild(0));
  6782. return createWrapper(no_assertconstant, msg.getClear());
  6783. }
  6784. StringBuffer suffix;
  6785. getExprECL(cond, suffix, true);
  6786. node_operator op = cond->getOperator();
  6787. StringBuffer temp;
  6788. switch (op)
  6789. {
  6790. case no_eq:
  6791. case no_ne:
  6792. case no_gt:
  6793. case no_ge:
  6794. case no_lt:
  6795. case no_le:
  6796. break;
  6797. default:
  6798. return createConstant(temp.append("Assert failed: ").append(suffix));
  6799. }
  6800. IHqlExpression * lhs = cond->queryChild(0);
  6801. IHqlExpression * rhs = cond->queryChild(1);
  6802. if (!lhs->queryType()->isScalar() || !rhs->queryType()->isScalar())
  6803. return createConstant(temp.append("Assert failed: ").append(suffix));
  6804. StringBuffer prefix;
  6805. prefix.append("Assert (");
  6806. suffix.insert(0, ") failed [");
  6807. suffix.append("]");
  6808. StringBuffer cmpText;
  6809. cmpText.append(" ").append(getOpString(op)).append(" ");
  6810. OwnedITypeInfo unknownStringType = makeStringType(UNKNOWN_LENGTH, NULL, NULL);
  6811. OwnedITypeInfo unknownVarStringType = makeVarStringType(UNKNOWN_LENGTH, NULL, NULL);
  6812. HqlExprArray args;
  6813. args.append(*createConstant(prefix));
  6814. args.append(*ensureExprType(lhs, unknownStringType));
  6815. args.append(*createConstant(cmpText));
  6816. args.append(*ensureExprType(rhs, unknownStringType));
  6817. args.append(*createConstant(suffix));
  6818. return createBalanced(no_concat, unknownVarStringType, args);
  6819. }
  6820. //-------------------------------------------------------------------------------------------------------------------
  6821. static char const gccMangledIntegers[2][8] = {
  6822. { 'h', 't', 'j', 'j', 'y', 'y', 'y', 'y' },
  6823. { 'c', 's', 'i', 'i', 'x', 'x', 'x', 'x' }
  6824. };
  6825. // gcc see http://www.codesourcery.com/public/cxx-abi/abi.html#mangling
  6826. class GccCppNameMangler
  6827. {
  6828. public:
  6829. bool mangleFunctionName(StringBuffer & mangled, IHqlExpression * funcdef)
  6830. {
  6831. IHqlExpression *body = funcdef->queryChild(0);
  6832. IHqlExpression *formals = funcdef->queryChild(1);
  6833. ITypeInfo * retType = funcdef->queryType()->queryChildType();
  6834. enum { ServiceApi, RtlApi, BcdApi, CApi, CppApi, LocalApi } api = ServiceApi;
  6835. if (body->hasAttribute(eclrtlAtom))
  6836. api = RtlApi;
  6837. else if (body->hasAttribute(bcdAtom))
  6838. api = BcdApi;
  6839. else if (body->hasAttribute(cAtom))
  6840. api = CApi;
  6841. else if (body->hasAttribute(cppAtom))
  6842. api = CppApi;
  6843. else if (body->hasAttribute(localAtom))
  6844. api = LocalApi;
  6845. StringBuffer entrypoint;
  6846. getAttribute(body, entrypointAtom, entrypoint);
  6847. if (entrypoint.length() == 0)
  6848. return false;
  6849. if ((api == ServiceApi) || api == CApi)
  6850. {
  6851. mangled.append(entrypoint); // extern "C"
  6852. return true;
  6853. }
  6854. if (body->hasAttribute(oldSetFormatAtom))
  6855. return false;
  6856. mangled.append("_Z");
  6857. StringBuffer namespaceValue;
  6858. getAttribute(body, namespaceAtom, namespaceValue);
  6859. if (namespaceValue.length())
  6860. mangled.append("N").append(namespaceValue.length()).append(namespaceValue);
  6861. mangled.append(entrypoint.length()).append(entrypoint);
  6862. if (namespaceValue.length())
  6863. mangled.append("E");
  6864. StringBuffer mangledReturn;
  6865. StringBuffer mangledReturnParameters;
  6866. mangleFunctionReturnType(mangledReturn, mangledReturnParameters, retType);
  6867. if (functionBodyUsesContext(body))
  6868. mangled.append("P12ICodeContext");
  6869. else if (body->hasAttribute(globalContextAtom) )
  6870. mangled.append("P18IGlobalCodeContext");
  6871. else if (body->hasAttribute(userMatchFunctionAtom))
  6872. mangled.append("P12IMatchWalker");
  6873. mangled.append(mangledReturnParameters);
  6874. if (formals->numChildren())
  6875. {
  6876. bool hasMeta = getBoolAttribute(body, passParameterMetaAtom, false);
  6877. ForEachChild(i, formals)
  6878. {
  6879. IHqlExpression * param = formals->queryChild(i);
  6880. ITypeInfo *paramType = param->queryType();
  6881. bool isOut = param->hasAttribute(outAtom);
  6882. bool isConst = !param->hasAttribute(noConstAtom);
  6883. if (isOut)
  6884. mangled.append("R");
  6885. if (!mangleSimpleType(mangled, paramType, isConst, hasMeta))
  6886. return false;
  6887. }
  6888. }
  6889. else
  6890. mangled.append('v');
  6891. return true;
  6892. }
  6893. protected:
  6894. bool mangleSimpleType(StringBuffer & result, ITypeInfo * type, bool hasConst, bool hasMeta)
  6895. {
  6896. if (!type)
  6897. return false;
  6898. switch (type->getTypeCode())
  6899. {
  6900. case type_boolean:
  6901. result.append("b");
  6902. return true;
  6903. case type_int:
  6904. case type_swapint:
  6905. result.append(gccMangledIntegers[type->isSigned() ? 1 : 0][type->getSize()-1]);
  6906. return true;
  6907. case type_real:
  6908. result.append(type->getSize() == 4 ? "f" : "d");
  6909. return true;
  6910. case type_decimal:
  6911. //Should really define this properly (size, precision, ptr)
  6912. return false;
  6913. case type_string:
  6914. case type_qstring:
  6915. case type_utf8:
  6916. if (type->getSize() == UNKNOWN_LENGTH)
  6917. result.append("j");
  6918. result.append(lookupRepeat(hasConst ? "PKc" : "Pc"));
  6919. return true;
  6920. case type_varstring:
  6921. result.append(lookupRepeat(hasConst ? "PKc" : "Pc"));
  6922. return true;
  6923. case type_data:
  6924. if (type->getSize() == UNKNOWN_LENGTH)
  6925. result.append("j");
  6926. result.append(lookupRepeat(hasConst ? "PKv" : "Pv"));
  6927. return true;
  6928. case type_unicode:
  6929. if (type->getSize() == UNKNOWN_LENGTH)
  6930. result.append("j");
  6931. result.append(lookupRepeat(hasConst ? "PKt" : "Pt"));
  6932. return true;
  6933. case type_varunicode:
  6934. result.append(lookupRepeat(hasConst ? "PKt" : "Pt"));
  6935. return true;
  6936. case type_char:
  6937. result.append("c");
  6938. return true;
  6939. case type_enumerated:
  6940. return mangleSimpleType(result, type->queryChildType(), hasConst, hasMeta);
  6941. case type_pointer:
  6942. result.append("P");
  6943. return mangleSimpleType(result, type->queryChildType(), hasConst, hasMeta);
  6944. case type_array:
  6945. result.append("A").append(type->getSize()).append("_");;
  6946. return mangleSimpleType(result, type->queryChildType(), hasConst, hasMeta);
  6947. case type_table:
  6948. case type_groupedtable:
  6949. result.append("j"); // size32_t
  6950. result.append(lookupRepeat(hasConst ? "PKv" : "Pv")); // [const] void *
  6951. return true;
  6952. case type_set:
  6953. result.append("b"); // bool
  6954. result.append("j"); // unsigned
  6955. result.append(lookupRepeat(hasConst ? "PKv" : "Pv")); // *
  6956. return true;
  6957. case type_row:
  6958. if (hasMeta)
  6959. result.append(lookupRepeat("R15IOutputMetaData"));
  6960. result.append(lookupRepeat("PKh")); // Does not seem to depend on const
  6961. return true;
  6962. case type_void:
  6963. result.append("v");
  6964. return true;
  6965. case type_scope:
  6966. case type_transform:
  6967. case type_function:
  6968. case type_any:
  6969. case type_packedint:
  6970. case type_alien:
  6971. case type_class:
  6972. case type_date:
  6973. //may possibly have some support in the future, but not yet...
  6974. return false;
  6975. }
  6976. throwUnexpected();
  6977. }
  6978. StringArray repeatsSeen;
  6979. StringBuffer thisRepeat;
  6980. const char *lookupRepeat(const char *typeStr)
  6981. {
  6982. ForEachItemIn(idx, repeatsSeen)
  6983. {
  6984. if (streq(repeatsSeen.item(idx), typeStr))
  6985. return thisRepeat.appendf("S%d_", idx).str();
  6986. }
  6987. repeatsSeen.append(typeStr);
  6988. return typeStr;
  6989. }
  6990. bool mangleFunctionReturnType(StringBuffer & returnType, StringBuffer & params, ITypeInfo * retType)
  6991. {
  6992. type_t tc = retType->getTypeCode();
  6993. switch (tc)
  6994. {
  6995. case type_varstring:
  6996. if (retType->getSize() == UNKNOWN_LENGTH)
  6997. returnType.append("Pc"); // char *
  6998. else
  6999. params.append("Pc"); // char *
  7000. break;
  7001. case type_varunicode:
  7002. if (retType->getSize() == UNKNOWN_LENGTH)
  7003. returnType.append("Pt"); // ushort *
  7004. else
  7005. params.append("Pt"); // ushort *
  7006. break;
  7007. case type_qstring:
  7008. case type_string:
  7009. case type_utf8:
  7010. if (retType->getSize() == UNKNOWN_LENGTH)
  7011. {
  7012. params.append("Rj"); // size32_t &
  7013. params.append("RPc"); // char * &
  7014. }
  7015. else
  7016. params.append("Pc"); // char *
  7017. break;
  7018. case type_data:
  7019. if (retType->getSize() == UNKNOWN_LENGTH)
  7020. {
  7021. params.append("Rj"); // size32_t &
  7022. params.append("RPv"); // void * &
  7023. }
  7024. else
  7025. params.append("Pv"); // void *
  7026. break;
  7027. case type_unicode:
  7028. if (retType->getSize() == UNKNOWN_LENGTH)
  7029. {
  7030. params.append("Rj"); // size32_t &
  7031. params.append("RPt"); // UChar * &
  7032. }
  7033. else
  7034. params.append("Pt"); // UChar *
  7035. break;
  7036. case type_table:
  7037. case type_groupedtable:
  7038. params.append("Rj"); // size32_t &
  7039. params.append("RPv"); // void * &
  7040. break;
  7041. case type_set:
  7042. params.append("Rb"); // bool &
  7043. params.append("Rj"); // size32_t &
  7044. params.append("RPv"); // void * &
  7045. break;
  7046. case type_row:
  7047. params.append("Ph"); // byte *
  7048. break;
  7049. }
  7050. return true;
  7051. }
  7052. };
  7053. //-------------------------------------------------------------------------------------------------------------------
  7054. //See http://www.kegel.com/mangle.html for details
  7055. //See http://www.agner.org/optimize/calling_conventions.pdf for details
  7056. static const char * const vs6MangledIntegers[2][8] = {
  7057. { "E", "G", "I", "I", "_K", "_K", "_K", "_K" },
  7058. { "D", "F", "H", "H", "_J", "_J", "_J", "_J" }
  7059. };
  7060. class Vs6CppNameMangler
  7061. {
  7062. public:
  7063. Vs6CppNameMangler()
  7064. {
  7065. // Assuming Windows on ARM64 will have the same mangling
  7066. #ifdef __64BIT__
  7067. pointerBaseCode.set("E");
  7068. #endif
  7069. }
  7070. bool mangle(StringBuffer & mangled, IHqlExpression * funcdef)
  7071. {
  7072. IHqlExpression *body = funcdef->queryChild(0);
  7073. IHqlExpression *formals = funcdef->queryChild(1);
  7074. enum { ServiceApi, RtlApi, BcdApi, CApi, LocalApi } api = ServiceApi;
  7075. if (body->hasAttribute(eclrtlAtom))
  7076. api = RtlApi;
  7077. else if (body->hasAttribute(bcdAtom))
  7078. api = BcdApi;
  7079. else if (body->hasAttribute(cAtom))
  7080. api = CApi;
  7081. else if (body->hasAttribute(localAtom))
  7082. api = LocalApi;
  7083. StringBuffer entrypoint;
  7084. getAttribute(body, entrypointAtom, entrypoint);
  7085. if (entrypoint.length() == 0)
  7086. return false;
  7087. if ((api == ServiceApi) || api == CApi)
  7088. {
  7089. mangled.append(entrypoint); // extern "C"
  7090. return true;
  7091. }
  7092. if (body->hasAttribute(oldSetFormatAtom))
  7093. return false;
  7094. mangled.append("?").append(entrypoint).append("@@").append("Y");
  7095. switch (api)
  7096. {
  7097. case CApi:
  7098. mangled.append("A"); // _cdecl
  7099. break;
  7100. case BcdApi:
  7101. mangled.append("T"); // __fastcall"
  7102. break;
  7103. default:
  7104. mangled.append("A"); // _cdecl
  7105. break;
  7106. // mangled.append("G"); // __stdcall
  7107. }
  7108. StringBuffer mangledReturn;
  7109. StringBuffer mangledReturnParameters;
  7110. ITypeInfo * retType = funcdef->queryType()->queryChildType();
  7111. mangleFunctionReturnType(mangledReturn, mangledReturnParameters, retType);
  7112. mangled.append(mangledReturn);
  7113. if (functionBodyUsesContext(body))
  7114. mangled.append("PVICodeContext@@");
  7115. else if (body->hasAttribute(globalContextAtom) )
  7116. mangled.append("PVIGlobalCodeContext@@");
  7117. else if (body->hasAttribute(userMatchFunctionAtom))
  7118. mangled.append("PVIMatchWalker@@");
  7119. if (mangledReturnParameters.length())
  7120. mangled.append(mangledReturnParameters);
  7121. ForEachChild(i, formals)
  7122. {
  7123. IHqlExpression * param = formals->queryChild(i);
  7124. ITypeInfo *paramType = param->queryType();
  7125. bool isOut = param->hasAttribute(outAtom);
  7126. bool isConst = !param->hasAttribute(noConstAtom);
  7127. if (isOut)
  7128. appendRef(mangled, false);
  7129. if (!mangleSimpleType(mangled, paramType, isConst))
  7130. return false;
  7131. }
  7132. mangled.append("@Z");
  7133. return true;
  7134. }
  7135. protected:
  7136. bool mangleSimpleType(StringBuffer & result, ITypeInfo * type, bool hasConst)
  7137. {
  7138. if (!type)
  7139. return false;
  7140. switch (type->getTypeCode())
  7141. {
  7142. case type_boolean:
  7143. result.append("_N");
  7144. return true;
  7145. case type_int:
  7146. case type_swapint:
  7147. result.append(vs6MangledIntegers[type->isSigned() ? 1 : 0][type->getSize()-1]);
  7148. return true;
  7149. case type_real:
  7150. result.append(type->getSize() == 4 ? "M" : "N");
  7151. return true;
  7152. case type_decimal:
  7153. //Should really define this properly (size, precision, ptr)
  7154. return false;
  7155. case type_string:
  7156. case type_qstring:
  7157. case type_utf8:
  7158. if (type->getSize() == UNKNOWN_LENGTH)
  7159. result.append("I");
  7160. appendPtr(result, hasConst).append("D");
  7161. return true;
  7162. case type_varstring:
  7163. appendPtr(result, hasConst).append("D");
  7164. return true;
  7165. case type_data:
  7166. if (type->getSize() == UNKNOWN_LENGTH)
  7167. result.append("I");
  7168. appendPtr(result, hasConst).append("X");
  7169. return true;
  7170. case type_unicode:
  7171. if (type->getSize() == UNKNOWN_LENGTH)
  7172. result.append("I");
  7173. appendPtr(result, hasConst).append("G");
  7174. return true;
  7175. case type_varunicode:
  7176. appendPtr(result, hasConst).append("G");
  7177. return true;
  7178. case type_char:
  7179. result.append("D");
  7180. return true;
  7181. case type_enumerated:
  7182. return mangleSimpleType(result, type->queryChildType(), hasConst);
  7183. case type_pointer:
  7184. result.append("PEB");
  7185. return mangleSimpleType(result, type->queryChildType(), hasConst);
  7186. case type_array:
  7187. return false; // QEA???
  7188. case type_table:
  7189. case type_groupedtable:
  7190. result.append("I"); // size32_t
  7191. appendPtr(result, hasConst).append("X");
  7192. return true;
  7193. case type_set:
  7194. result.append("_N"); // bool
  7195. result.append("I"); // unsigned
  7196. appendPtr(result, hasConst).append("X");
  7197. return true;
  7198. case type_row:
  7199. appendPtr(result, hasConst).append("E");
  7200. return true;
  7201. case type_void:
  7202. result.append("X");
  7203. return true;
  7204. case type_scope:
  7205. case type_transform:
  7206. case type_function:
  7207. case type_any:
  7208. case type_packedint:
  7209. case type_alien:
  7210. case type_class:
  7211. case type_date:
  7212. //may possibly have some support in the future, but not yet...
  7213. return false;
  7214. }
  7215. throwUnexpected();
  7216. }
  7217. bool mangleFunctionReturnType(StringBuffer & returnType, StringBuffer & params, ITypeInfo * retType)
  7218. {
  7219. type_t tc = retType->getTypeCode();
  7220. bool hasConst = false;
  7221. switch (tc)
  7222. {
  7223. case type_varstring:
  7224. if (retType->getSize() == UNKNOWN_LENGTH)
  7225. {
  7226. appendPtr(returnType, hasConst).append("D"); // char *
  7227. }
  7228. else
  7229. {
  7230. returnType.append("X");
  7231. appendPtr(params, hasConst).append("D"); // char *
  7232. }
  7233. break;
  7234. case type_varunicode:
  7235. if (retType->getSize() == UNKNOWN_LENGTH)
  7236. {
  7237. appendPtr(returnType, hasConst).append("G"); // char *
  7238. }
  7239. else
  7240. {
  7241. returnType.append("X");
  7242. appendPtr(params, hasConst).append("G"); // char *
  7243. }
  7244. break;
  7245. case type_qstring:
  7246. case type_string:
  7247. case type_utf8:
  7248. returnType.append("X");
  7249. appendString(params, retType, "D");
  7250. break;
  7251. case type_data:
  7252. returnType.append("X");
  7253. appendString(params, retType, "X");
  7254. break;
  7255. case type_unicode:
  7256. returnType.append("X");
  7257. appendString(params, retType, "G");
  7258. break;
  7259. case type_table:
  7260. case type_groupedtable:
  7261. returnType.append("X");
  7262. appendRef(params, false).append("I"); // size32_t &
  7263. appendRef(params, false);
  7264. appendPtr(params, false).append("X"); // void * &
  7265. break;
  7266. case type_set:
  7267. returnType.append("X");
  7268. appendRef(params, false).append("_N"); // bool &
  7269. appendRef(params, false).append("I"); // size32_t &
  7270. appendRef(params, false);
  7271. appendPtr(params, false).append("X"); // void * &
  7272. break;
  7273. case type_row:
  7274. returnType.append("X");
  7275. appendPtr(params, false).append("E"); // byte *
  7276. break;
  7277. default:
  7278. return mangleSimpleType(returnType, retType, false);
  7279. }
  7280. return true;
  7281. }
  7282. StringBuffer & appendPtr(StringBuffer & s, bool hasConst) { return s.append("P").append(pointerBaseCode).append(hasConst ? "B" : "A"); }
  7283. StringBuffer & appendRef(StringBuffer & s, bool hasConst) { return s.append("A").append(pointerBaseCode).append(hasConst ? "B" : "A"); }
  7284. StringBuffer & appendString(StringBuffer & params, ITypeInfo * type, const char * suffix)
  7285. {
  7286. if (type->getSize() == UNKNOWN_LENGTH)
  7287. {
  7288. appendRef(params, false).append("I"); // size32_t &
  7289. appendRef(params, false);
  7290. appendPtr(params, false).append(suffix); // X * &
  7291. }
  7292. else
  7293. appendPtr(params, false).append(suffix); // X *
  7294. return params;
  7295. }
  7296. protected:
  7297. StringAttr pointerBaseCode;
  7298. };
  7299. //-------------------------------------------------------------------------------------------------------------------
  7300. //This code is provisional, and needs a lot more testing. However it seems to work on my limited examples.
  7301. bool createMangledFunctionName(StringBuffer & mangled, IHqlExpression * funcdef, CompilerType compiler)
  7302. {
  7303. switch (compiler)
  7304. {
  7305. case GccCppCompiler:
  7306. {
  7307. GccCppNameMangler mangler;
  7308. return mangler.mangleFunctionName(mangled, funcdef);
  7309. }
  7310. case Vs6CppCompiler:
  7311. {
  7312. Vs6CppNameMangler mangler;
  7313. return mangler.mangle(mangled, funcdef);
  7314. }
  7315. }
  7316. return false;
  7317. }
  7318. bool createMangledFunctionName(StringBuffer & mangled, IHqlExpression * funcdef)
  7319. {
  7320. return createMangledFunctionName(mangled, funcdef, DEFAULT_COMPILER);
  7321. }
  7322. //-------------------------------------------------------------------------------------------------------------------
  7323. static void trimSlash(StringBuffer & name)
  7324. {
  7325. unsigned len = name.length();
  7326. if (len && name.charAt(len-1) == '/')
  7327. name.setLength(len-1);
  7328. }
  7329. void extractXmlName(StringBuffer & name, StringBuffer * itemName, StringBuffer * valueName, IHqlExpression * field, const char * defaultItemName, bool reading)
  7330. {
  7331. IHqlExpression * xpathAttr = field->queryAttribute(xpathAtom);
  7332. if (xpathAttr)
  7333. {
  7334. StringBuffer tagName;
  7335. IHqlExpression * xpath = xpathAttr->queryChild(0);
  7336. xpath->queryValue()->getStringValue(tagName);
  7337. unsigned lenContents = strlen(XPATH_CONTENTS_TEXT);
  7338. unsigned lenTagName = tagName.length();
  7339. if ((lenTagName >= lenContents) && (memcmp(tagName.str() + (lenTagName - lenContents), XPATH_CONTENTS_TEXT, lenContents) == 0))
  7340. tagName.setLength(lenTagName - lenContents);
  7341. //Only take the xpath if it isn't an attribute, sub element, or a filtered element.
  7342. //we should probably think about handling attributes as a special case.
  7343. //would probably mean two passes.
  7344. if (!tagName.length())
  7345. return;
  7346. const char * text = tagName.str();
  7347. if (reading || !strchr(text, '['))
  7348. {
  7349. const char * sep = strchr(text, '/');
  7350. if (valueName && sep)
  7351. {
  7352. const char * sep2 = strchr(sep+1, '/');
  7353. if (sep2)
  7354. {
  7355. valueName->append(sep2+1);
  7356. itemName->append(sep2-(sep+1), (sep+1));
  7357. name.append(sep-text, text);
  7358. trimSlash(name);
  7359. return;
  7360. }
  7361. }
  7362. trimSlash(tagName);
  7363. const char * text = tagName.str();
  7364. if (reading || !strchr(text+1, '@'))
  7365. {
  7366. if (itemName)
  7367. {
  7368. const char * sep = strrchr(text, '/');
  7369. if (sep)
  7370. {
  7371. name.append(sep-text, text);
  7372. itemName->append(strlen(sep+1), sep+1);
  7373. }
  7374. else
  7375. itemName->append(tagName);
  7376. return;
  7377. }
  7378. else
  7379. {
  7380. name.append(tagName);
  7381. }
  7382. }
  7383. }
  7384. }
  7385. else
  7386. {
  7387. IHqlExpression * namedAttr = field->queryAttribute(namedAtom);
  7388. if (namedAttr)
  7389. namedAttr->queryChild(0)->queryValue()->getStringValue(name);
  7390. }
  7391. bool useDefaultName = (name.length() == 0);
  7392. if (useDefaultName)
  7393. {
  7394. StringBuffer tagName;
  7395. tagName.append(field->queryName()).toLowerCase();
  7396. name.append(tagName);
  7397. }
  7398. if (itemName && itemName->length() == 0)
  7399. {
  7400. if (useDefaultName)
  7401. itemName->append(defaultItemName);
  7402. else
  7403. {
  7404. itemName->append(name);
  7405. name.clear();
  7406. }
  7407. }
  7408. }
  7409. void extractXmlName(SharedHqlExpr & name, OwnedHqlExpr * itemName, OwnedHqlExpr * valueName, IHqlExpression * field, const char * defaultItemName, bool reading)
  7410. {
  7411. StringBuffer nameText, itemNameText, valueNameText;
  7412. extractXmlName(nameText, itemName ? &itemNameText : NULL, valueName ? &valueNameText : NULL, field, defaultItemName, reading);
  7413. if (valueNameText.length())
  7414. valueName->setown(createConstant(constUnknownVarStringType->castFrom(valueNameText.length(), valueNameText.str())));
  7415. if (itemNameText.length())
  7416. itemName->setown(createConstant(constUnknownVarStringType->castFrom(itemNameText.length(), itemNameText.str())));
  7417. if (nameText.length())
  7418. name.setown(createConstant(constUnknownVarStringType->castFrom(nameText.length(), nameText.str())));
  7419. }
  7420. //-------------------------------------------------------------------------------------------------------------------
  7421. /*
  7422. * the xml schema is being generated
  7423. * there is a dataset with a single element (with xpaths for the element and the row)
  7424. * that element has an xpath of ''
  7425. then generate a simplified schema
  7426. */
  7427. static ITypeInfo * containsSingleSimpleFieldBlankXPath(IHqlExpression * record)
  7428. {
  7429. if (record->numChildren() != 1)
  7430. return NULL;
  7431. IHqlExpression * field = record->queryChild(0);
  7432. if (field->getOperator() != no_field)
  7433. return NULL;
  7434. IHqlExpression * xpath = field->queryAttribute(xpathAtom);
  7435. if (!xpath)
  7436. return NULL;
  7437. StringBuffer xpathText;
  7438. if (getStringValue(xpathText, xpath->queryChild(0)).length() != 0)
  7439. return NULL;
  7440. ITypeInfo * type = field->queryType();
  7441. if (type->getTypeCode() == type_alien)
  7442. type = queryAlienType(type)->queryLogicalType();
  7443. return type;
  7444. }
  7445. class EclXmlSchemaBuilder
  7446. {
  7447. public:
  7448. EclXmlSchemaBuilder(ISchemaBuilder & _builder, bool _useXPath)
  7449. : builder(_builder), useXPath(_useXPath)
  7450. {
  7451. }
  7452. void build(IHqlExpression * record, bool &hasMixedContent, unsigned keyedCount) const;
  7453. void build(IHqlExpression * record, unsigned keyedCount) const {bool mixed; build(record, mixed, keyedCount);}
  7454. protected:
  7455. void extractName(StringBuffer & name, StringBuffer * itemName, StringBuffer * valueName, IHqlExpression * field, const char * defaultItemName) const;
  7456. protected:
  7457. ISchemaBuilder & builder;
  7458. bool useXPath;
  7459. };
  7460. void EclXmlSchemaBuilder::build(IHqlExpression * record, bool &hasMixedContent, unsigned keyedCount) const
  7461. {
  7462. StringBuffer name, childName;
  7463. ForEachChild(i, record)
  7464. {
  7465. IHqlExpression * cur = record->queryChild(i);
  7466. switch (cur->getOperator())
  7467. {
  7468. case no_field:
  7469. {
  7470. ITypeInfo * type = cur->queryType();
  7471. switch (cur->queryType()->getTypeCode())
  7472. {
  7473. case type_row:
  7474. {
  7475. extractName(name.clear(), NULL, NULL, cur, NULL);
  7476. unsigned updateMixed=0;
  7477. builder.beginRecord(name, false, &updateMixed);
  7478. bool mixed = false;
  7479. build(cur->queryRecord(), (name.length()) ? mixed : hasMixedContent, 0);
  7480. if (mixed)
  7481. builder.updateMixedRecord(updateMixed, true);
  7482. builder.endRecord(name);
  7483. break;
  7484. }
  7485. case type_set:
  7486. {
  7487. extractName(name.clear(), &childName.clear(), NULL, cur, "Item");
  7488. if (name.length())
  7489. builder.addSetField(name, childName, *type);
  7490. else
  7491. hasMixedContent = true;
  7492. break;
  7493. }
  7494. case type_dictionary:
  7495. case type_table:
  7496. case type_groupedtable:
  7497. {
  7498. extractName(name.clear(), &childName.clear(), NULL, cur, "Row");
  7499. ITypeInfo * singleFieldType = (useXPath && name.length() && childName.length()) ? containsSingleSimpleFieldBlankXPath(cur->queryRecord()) : NULL;
  7500. if (!singleFieldType || !builder.addSingleFieldDataset(name, childName, *singleFieldType))
  7501. {
  7502. unsigned updateMixed = 0;
  7503. bool mixed = false;
  7504. if (builder.beginDataset(name, childName, false, &updateMixed))
  7505. {
  7506. build(cur->queryRecord(), (name.length()) ? mixed : hasMixedContent, 0);
  7507. if (mixed)
  7508. builder.updateMixedRecord(updateMixed, true);
  7509. }
  7510. builder.endDataset(name, childName);
  7511. }
  7512. break;
  7513. }
  7514. case type_alien:
  7515. type = queryAlienType(type)->queryLogicalType();
  7516. //fallthrough
  7517. default:
  7518. extractName(name.clear(), NULL, NULL, cur, NULL);
  7519. if (name.length())
  7520. builder.addField(name, *type, i < keyedCount);
  7521. else
  7522. hasMixedContent = true;
  7523. break;
  7524. }
  7525. break;
  7526. }
  7527. case no_ifblock:
  7528. builder.beginIfBlock();
  7529. build(cur->queryChild(1), hasMixedContent, 0);
  7530. builder.endIfBlock();
  7531. break;
  7532. case no_record:
  7533. build(cur, hasMixedContent, 0);
  7534. break;
  7535. }
  7536. }
  7537. }
  7538. void EclXmlSchemaBuilder::extractName(StringBuffer & name, StringBuffer * itemName, StringBuffer * valueName, IHqlExpression * field, const char * defaultItemName) const
  7539. {
  7540. if (useXPath)
  7541. {
  7542. ::extractXmlName(name, itemName, valueName, field, defaultItemName, false);
  7543. }
  7544. else
  7545. {
  7546. name.append(field->queryName()).toLowerCase();
  7547. if (itemName)
  7548. itemName->append(defaultItemName);
  7549. }
  7550. }
  7551. void getRecordXmlSchema(StringBuffer & result, IHqlExpression * record, bool useXPath, unsigned keyedCount)
  7552. {
  7553. XmlSchemaBuilder xmlbuilder(false);
  7554. EclXmlSchemaBuilder builder(xmlbuilder, useXPath);
  7555. builder.build(record, keyedCount);
  7556. xmlbuilder.getXml(result);
  7557. }
  7558. //---------------------------------------------------------------------------
  7559. static IHqlExpression * simplifyInExpr(IHqlExpression * expr)
  7560. {
  7561. IHqlExpression * ret = querySimplifyInExpr(expr);
  7562. if (ret)
  7563. return ret;
  7564. return LINK(expr);
  7565. }
  7566. IHqlExpression * querySimplifyInExpr(IHqlExpression * expr)
  7567. {
  7568. node_operator op = expr->getOperator();
  7569. switch (op)
  7570. {
  7571. case no_in:
  7572. case no_notin:
  7573. break;
  7574. default:
  7575. return NULL;
  7576. }
  7577. IHqlExpression * lhs = expr->queryChild(0);
  7578. IHqlExpression * rhs = expr->queryChild(1);
  7579. HqlExprArray args;
  7580. OwnedHqlExpr ret;
  7581. switch (rhs->getOperator())
  7582. {
  7583. case no_addsets:
  7584. {
  7585. OwnedHqlExpr newLeft = createBoolExpr(op, LINK(lhs), LINK(rhs->queryChild(0)));
  7586. OwnedHqlExpr newRight = createBoolExpr(op, LINK(lhs), LINK(rhs->queryChild(1)));
  7587. args.append(*simplifyInExpr(newLeft));
  7588. args.append(*simplifyInExpr(newRight));
  7589. ret.setown(createValue((op == no_in) ? no_or : no_and, makeBoolType(), args));
  7590. break;
  7591. }
  7592. case no_if:
  7593. {
  7594. OwnedHqlExpr newLeft = createBoolExpr(op, LINK(lhs), LINK(rhs->queryChild(1)));
  7595. OwnedHqlExpr newRight = createBoolExpr(op, LINK(lhs), LINK(rhs->queryChild(2)));
  7596. args.append(*LINK(rhs->queryChild(0)));
  7597. args.append(*simplifyInExpr(newLeft));
  7598. args.append(*simplifyInExpr(newRight));
  7599. ret.setown(createValue(no_if, makeBoolType(), args));
  7600. break;
  7601. }
  7602. }
  7603. if (ret)
  7604. return expr->cloneAllAnnotations(ret);
  7605. return NULL;
  7606. }
  7607. bool canSetBeAll(IHqlExpression * expr)
  7608. {
  7609. if (!expr)
  7610. return false;
  7611. switch (expr->getOperator())
  7612. {
  7613. case no_createset:
  7614. case no_list:
  7615. return false;
  7616. //more: no_addsets, no_if
  7617. case no_if:
  7618. return canSetBeAll(expr->queryChild(1)) || canSetBeAll(expr->queryChild(2));
  7619. case no_cast:
  7620. case no_implicitcast:
  7621. return canSetBeAll(expr->queryChild(0));
  7622. }
  7623. return true;
  7624. }
  7625. extern HQL_API bool hasNonNullRecord(ITypeInfo * type)
  7626. {
  7627. IHqlExpression * record = queryRecord(type);
  7628. if (!record)
  7629. return false;
  7630. return record->numChildren() != 0;
  7631. }
  7632. extern HQL_API IHqlExpression * createSizeof(IHqlExpression * expr)
  7633. {
  7634. return createValue(no_sizeof, LINK(sizetType), LINK(expr));
  7635. }
  7636. extern HQL_API bool allParametersHaveDefaults(IHqlExpression * function)
  7637. {
  7638. assertex(function->isFunction());
  7639. IHqlExpression * formals = queryFunctionParameters(function);
  7640. IHqlExpression * defaults = queryFunctionDefaults(function);
  7641. ForEachChild(idx, formals)
  7642. {
  7643. IHqlExpression * defvalue = queryDefaultValue(defaults, idx);
  7644. if (!defvalue)
  7645. return false;
  7646. }
  7647. return true;
  7648. }
  7649. extern HQL_API bool expandMissingDefaultsAsStoreds(HqlExprArray & args, IHqlExpression * function)
  7650. {
  7651. assertex(function->isFunction());
  7652. IHqlExpression * formals = queryFunctionParameters(function);
  7653. IHqlExpression * defaults = queryFunctionDefaults(function);
  7654. try
  7655. {
  7656. ForEachChild(idx, formals)
  7657. {
  7658. IHqlExpression *formal = formals->queryChild(idx);
  7659. IHqlExpression * defvalue = queryDefaultValue(defaults, idx);
  7660. if (defvalue)
  7661. {
  7662. args.append(*LINK(defvalue));
  7663. }
  7664. else
  7665. {
  7666. OwnedHqlExpr nullValue = createNullExpr(formal->queryType());
  7667. OwnedHqlExpr storedName = createConstant(str(formal->queryName()));
  7668. OwnedHqlExpr stored = createValue(no_stored, makeVoidType(), storedName.getClear());
  7669. HqlExprArray colonArgs;
  7670. colonArgs.append(*LINK(nullValue));
  7671. colonArgs.append(*LINK(stored));
  7672. args.append(*createWrapper(no_colon, formal->queryType(), colonArgs));
  7673. }
  7674. }
  7675. }
  7676. catch (IException * e)
  7677. {
  7678. e->Release();
  7679. return false;
  7680. }
  7681. return true;
  7682. }
  7683. //--------------------------------------------------------------------------------------------------------------------
  7684. const unsigned maxSensibleInlineElementSize = 10000;
  7685. class ConstantRowCreator
  7686. {
  7687. public:
  7688. ConstantRowCreator(MemoryBuffer & _out) : out(_out) { expectedIndex = 0; }
  7689. bool buildTransformRow(IHqlExpression * transform);
  7690. bool processFieldValue(IHqlExpression * optField, ITypeInfo * lhsType, IHqlExpression * rhs);
  7691. protected:
  7692. bool expandAssignChildren(IHqlExpression * expr);
  7693. bool expandAssignElement(IHqlExpression * expr);
  7694. bool processElement(IHqlExpression * expr, IHqlExpression * parentSelector);
  7695. bool processRecord(IHqlExpression * record, IHqlExpression * parentSelector);
  7696. IHqlExpression * queryMatchingAssign(IHqlExpression * self, IHqlExpression * search);
  7697. protected:
  7698. Owned<NestedHqlMapTransformer> mapper;
  7699. MemoryBuffer & out;
  7700. HqlExprCopyArray assigns;
  7701. unsigned expectedIndex;
  7702. };
  7703. bool ConstantRowCreator::expandAssignChildren(IHqlExpression * expr)
  7704. {
  7705. ForEachChild(i, expr)
  7706. {
  7707. IHqlExpression * cur = expr->queryChild(i);
  7708. if (!expandAssignElement(cur))
  7709. return false;
  7710. }
  7711. return true;
  7712. }
  7713. bool ConstantRowCreator::expandAssignElement(IHqlExpression * expr)
  7714. {
  7715. switch (expr->getOperator())
  7716. {
  7717. case no_assignall:
  7718. case no_transform:
  7719. case no_newtransform:
  7720. return expandAssignChildren(expr);
  7721. case no_assign:
  7722. assigns.append(*expr);
  7723. return true;
  7724. case no_skip:
  7725. return false;
  7726. case no_alias_scope:
  7727. expandAssignElement(expr->queryChild(0));
  7728. return true;
  7729. case no_attr:
  7730. case no_attr_link:
  7731. case no_attr_expr:
  7732. return true;
  7733. default:
  7734. return false;
  7735. }
  7736. }
  7737. IHqlExpression * ConstantRowCreator::queryMatchingAssign(IHqlExpression * self, IHqlExpression * search)
  7738. {
  7739. const unsigned endIndex = expectedIndex;
  7740. unsigned searchIndex = expectedIndex;
  7741. do
  7742. {
  7743. IHqlExpression & candidate = assigns.item(searchIndex);
  7744. IHqlExpression * lhs = candidate.queryChild(0);
  7745. IHqlExpression * candidateField = lhs->queryChild(1);
  7746. searchIndex++;
  7747. if (searchIndex == assigns.ordinality())
  7748. searchIndex = 0;
  7749. if (candidateField == search)
  7750. {
  7751. expectedIndex = searchIndex;
  7752. return &candidate;
  7753. }
  7754. } while (searchIndex != endIndex);
  7755. throwUnexpected();
  7756. }
  7757. bool ConstantRowCreator::processFieldValue(IHqlExpression * optLhs, ITypeInfo * lhsType, IHqlExpression * rhs)
  7758. {
  7759. size32_t lenLhs = lhsType->getStringLen();
  7760. size32_t sizeLhs = lhsType->getSize();
  7761. node_operator rhsOp = rhs->getOperator();
  7762. switch (lhsType->getTypeCode())
  7763. {
  7764. case type_packedint:
  7765. {
  7766. if (!rhs->queryValue())
  7767. return false;
  7768. unsigned orig = out.length();
  7769. void *tgt = out.reserve(9);
  7770. rtlSetPackedUnsigned(tgt, rhs->queryValue()->getIntValue());
  7771. unsigned actualSize = rtlGetPackedSize(tgt);
  7772. out.setLength(orig+actualSize);
  7773. return true;
  7774. }
  7775. case type_set:
  7776. if (isNullList(rhs))
  7777. {
  7778. out.append(false);
  7779. rtlWriteSize32t(out.reserve(sizeof(size32_t)), 0);
  7780. return true;
  7781. }
  7782. if (rhsOp == no_all)
  7783. {
  7784. out.append(true);
  7785. rtlWriteSize32t(out.reserve(sizeof(size32_t)), 0);
  7786. return true;
  7787. }
  7788. if (rhsOp == no_list)
  7789. {
  7790. ITypeInfo * elemType = lhsType->queryChildType();
  7791. out.append(false);
  7792. unsigned patchOffset = out.length();
  7793. out.reserve(sizeof(size32_t));
  7794. const size_t startOffset = out.length();
  7795. ForEachChild(i, rhs)
  7796. {
  7797. if (!processFieldValue(NULL, elemType, rhs->queryChild(i)))
  7798. return false;
  7799. }
  7800. const size_t setLength = out.length() - startOffset;
  7801. out.writeDirect(patchOffset, sizeof(size32_t), &setLength);
  7802. byte * patchPos = (byte *)out.bufferBase() + patchOffset;
  7803. rtlWriteSize32t(patchPos, setLength);
  7804. return true;
  7805. }
  7806. return false;
  7807. case type_row:
  7808. if (rhsOp == no_null)
  7809. return createConstantNullRow(out, queryOriginalRecord(lhsType));
  7810. if (rhsOp == no_createrow)
  7811. return createConstantRow(out, rhs->queryChild(0));
  7812. return false;
  7813. case type_dictionary:
  7814. case type_table:
  7815. case type_groupedtable:
  7816. {
  7817. assertex(optLhs);
  7818. IHqlExpression * field = optLhs->queryChild(1);
  7819. if (!field->hasAttribute(countAtom) && !field->hasAttribute(sizeofAtom))
  7820. {
  7821. if (field->hasAttribute(_linkCounted_Atom))
  7822. {
  7823. if (rhsOp == no_null)
  7824. {
  7825. rtlWriteSize32t(out.reserve(sizeof(size32_t)), 0);
  7826. memset(out.reserve(sizeof(byte * *)), 0, sizeof(byte * *));
  7827. return true;
  7828. }
  7829. }
  7830. else
  7831. {
  7832. switch (rhsOp)
  7833. {
  7834. case no_null:
  7835. {
  7836. rtlWriteSize32t(out.reserve(sizeof(size32_t)), 0);
  7837. return true;
  7838. }
  7839. case no_inlinetable:
  7840. {
  7841. unsigned patchOffset = out.length();
  7842. out.reserve(sizeof(size32_t));
  7843. unsigned startOffset = out.length();
  7844. IHqlExpression * transforms = rhs->queryChild(0);
  7845. ForEachChild(i, transforms)
  7846. {
  7847. if (!createConstantRow(out, transforms->queryChild(i)))
  7848. return false;
  7849. }
  7850. byte * patchPos = (byte *)out.bufferBase() + patchOffset;
  7851. rtlWriteSize32t(patchPos, out.length() - startOffset);
  7852. return true;
  7853. }
  7854. }
  7855. }
  7856. }
  7857. return false;
  7858. }
  7859. }
  7860. if ((lenLhs != UNKNOWN_LENGTH) && (lenLhs > maxSensibleInlineElementSize))
  7861. return false;
  7862. OwnedHqlExpr castRhs = ensureExprType(rhs, lhsType);
  7863. IValue * castValue = castRhs->queryValue();
  7864. if (!castValue)
  7865. return false;
  7866. if (optLhs && mapper)
  7867. mapper->setMapping(optLhs, castRhs);
  7868. ITypeInfo * castValueType = castValue->queryType();
  7869. size32_t lenValue = castValueType->getStringLen();
  7870. assertex(lenLhs == UNKNOWN_LENGTH || lenLhs == lenValue);
  7871. switch (lhsType->getTypeCode())
  7872. {
  7873. case type_boolean:
  7874. case type_int:
  7875. case type_swapint:
  7876. case type_real:
  7877. case type_decimal:
  7878. {
  7879. void * temp = out.reserve(sizeLhs);
  7880. castValue->toMem(temp);
  7881. return true;
  7882. }
  7883. case type_data:
  7884. case type_string:
  7885. {
  7886. if (lenLhs == UNKNOWN_LENGTH)
  7887. rtlWriteInt4(out.reserve(sizeof(size32_t)), lenValue);
  7888. castValue->toMem(out.reserve(lenValue));
  7889. return true;
  7890. }
  7891. case type_varunicode:
  7892. {
  7893. if (sizeLhs == UNKNOWN_LENGTH)
  7894. {
  7895. void * target = out.reserve((lenValue+1)*sizeof(UChar));
  7896. castValue->toMem(target);
  7897. }
  7898. else
  7899. {
  7900. UChar * target = (UChar *) out.reserve(sizeLhs*sizeof(UChar));
  7901. for (size32_t pos = 0; pos < sizeLhs; pos++)
  7902. target[pos] = (UChar) ' ';
  7903. castValue->toMem(target);
  7904. }
  7905. return true;
  7906. }
  7907. case type_varstring:
  7908. {
  7909. //Move to else
  7910. if (sizeLhs == UNKNOWN_LENGTH)
  7911. {
  7912. void * target = out.reserve(lenValue+1);
  7913. castValue->toMem(target);
  7914. }
  7915. else
  7916. {
  7917. void * target = out.reserve(sizeLhs);
  7918. memset(target, ' ', sizeLhs); // spaces expand better in the c++
  7919. castValue->toMem(target);
  7920. }
  7921. return true;
  7922. }
  7923. case type_utf8:
  7924. case type_unicode:
  7925. case type_qstring:
  7926. {
  7927. if (lenLhs == UNKNOWN_LENGTH)
  7928. rtlWriteInt4(out.reserve(sizeof(size32_t)), lenValue);
  7929. castValue->toMem(out.reserve(castValue->getSize()));
  7930. return true;
  7931. }
  7932. }
  7933. return false;
  7934. }
  7935. bool ConstantRowCreator::processElement(IHqlExpression * expr, IHqlExpression * parentSelector)
  7936. {
  7937. switch (expr->getOperator())
  7938. {
  7939. case no_ifblock:
  7940. {
  7941. OwnedHqlExpr test = replaceSelector(expr->queryChild(0), querySelfReference(), parentSelector);
  7942. OwnedHqlExpr foldedTest = mapper->transformRoot(test);
  7943. foldedTest.setown(foldHqlExpression(foldedTest)); // can only contain references to self, so don't need to worry about other datasets in scope being messed up.
  7944. IValue * foldedValue = foldedTest->queryValue();
  7945. if (!foldedValue)
  7946. return false;
  7947. if (!foldedValue->getBoolValue())
  7948. return true;
  7949. return processRecord(expr->queryChild(1), parentSelector);
  7950. }
  7951. break;
  7952. case no_record:
  7953. return processRecord(expr, parentSelector);
  7954. case no_field:
  7955. {
  7956. IHqlExpression * match = queryMatchingAssign(parentSelector, expr);
  7957. if (!match || (match->getOperator() != no_assign))
  7958. return false;
  7959. return processFieldValue(match->queryChild(0), expr->queryType(), match->queryChild(1));
  7960. }
  7961. default:
  7962. return true;
  7963. }
  7964. }
  7965. bool ConstantRowCreator::processRecord(IHqlExpression * record, IHqlExpression * parentSelector)
  7966. {
  7967. ForEachChild(idx, record)
  7968. {
  7969. if (!processElement(record->queryChild(idx), parentSelector))
  7970. return false;
  7971. }
  7972. return true;
  7973. }
  7974. bool ConstantRowCreator::buildTransformRow(IHqlExpression * transform)
  7975. {
  7976. expectedIndex = 0;
  7977. if (!expandAssignChildren(transform))
  7978. return false;
  7979. if (recordContainsIfBlock(transform->queryRecord()))
  7980. mapper.setown(new NestedHqlMapTransformer);
  7981. unsigned savedLength = out.length();
  7982. OwnedHqlExpr self = getSelf(transform);
  7983. if (processRecord(transform->queryRecord(), self))
  7984. return true;
  7985. out.setLength(savedLength);
  7986. return false;
  7987. }
  7988. bool createConstantRow(MemoryBuffer & target, IHqlExpression * transform)
  7989. {
  7990. ConstantRowCreator builder(target);
  7991. return builder.buildTransformRow(transform);
  7992. }
  7993. bool createConstantField(MemoryBuffer & target, IHqlExpression * field, IHqlExpression * value)
  7994. {
  7995. ConstantRowCreator builder(target);
  7996. return builder.processFieldValue(field, field->queryType(), value);
  7997. }
  7998. IHqlExpression * createConstantRowExpr(IHqlExpression * transform)
  7999. {
  8000. MemoryBuffer rowData;
  8001. if (!createConstantRow(rowData, transform))
  8002. return NULL;
  8003. Owned<IValue> value = createDataValue(rowData.toByteArray(), rowData.length());
  8004. return createConstant(value.getClear());
  8005. }
  8006. bool createConstantNullRow(MemoryBuffer & target, IHqlExpression * record)
  8007. {
  8008. //MORE: More efficient to not go via a temporary transform
  8009. OwnedHqlExpr nullTransform = createClearTransform(record);
  8010. return createConstantRow(target, nullTransform);
  8011. }
  8012. IHqlExpression * createConstantNullRowExpr(IHqlExpression * record)
  8013. {
  8014. //MORE: optimize
  8015. OwnedHqlExpr nullTransform = createClearTransform(record);
  8016. return createConstantRowExpr(nullTransform);
  8017. }
  8018. IHqlExpression * ensureOwned(IHqlExpression * expr)
  8019. {
  8020. if (expr->isDataset())
  8021. {
  8022. if (hasLinkCountedModifier(expr))
  8023. return createDataset(no_owned_ds, LINK(expr));
  8024. }
  8025. return LINK(expr);
  8026. }
  8027. IError * annotateExceptionWithLocation(IException * e, IHqlExpression * location)
  8028. {
  8029. StringBuffer errorMsg;
  8030. e->errorMessage(errorMsg);
  8031. unsigned code = e->errorCode();
  8032. return createError(code, errorMsg.str(), str(location->querySourcePath()), location->getStartLine(), location->getStartColumn(), 0);
  8033. }
  8034. StringBuffer & appendLocation(StringBuffer & s, IHqlExpression * location, const char * suffix)
  8035. {
  8036. if (location)
  8037. {
  8038. int line = location->getStartLine();
  8039. int column = location->getStartColumn();
  8040. s.append(str(location->querySourcePath()));
  8041. if (line)
  8042. {
  8043. s.append("(").append(location->getStartLine());
  8044. if (column)
  8045. s.append(",").append(location->getStartColumn());
  8046. s.append(")");
  8047. }
  8048. s.append(suffix);
  8049. }
  8050. return s;
  8051. }
  8052. //---------------------------------------------------------------------------------------------------------------------
  8053. static bool doReportDroppedFields(IHqlSimpleScope * newScope, IHqlExpression * oldRecord, IErrorReceiver &err, ECLlocation &location)
  8054. {
  8055. bool allDropped = true; // until we find one that isn't
  8056. ForEachChild(i, oldRecord)
  8057. {
  8058. IHqlExpression * cur = oldRecord->queryChild(i);
  8059. switch (cur->getOperator())
  8060. {
  8061. case no_record:
  8062. allDropped = doReportDroppedFields(newScope, cur, err, location) && allDropped;
  8063. break;
  8064. case no_ifblock:
  8065. allDropped = doReportDroppedFields(newScope, cur->queryChild(1), err, location) && allDropped;
  8066. break;
  8067. case no_field:
  8068. {
  8069. OwnedHqlExpr newField = newScope->lookupSymbol(cur->queryId());
  8070. if (!newField)
  8071. {
  8072. VStringBuffer msg("Field %s is present in DFS file but not in ECL definition", str(cur->queryId()));
  8073. err.reportWarning(CategoryInformation, HQLINFO_FieldNotPresentInECL, msg.str(), str(location.sourcePath), location.lineno, location.column, location.position);
  8074. }
  8075. else
  8076. {
  8077. allDropped = false;
  8078. if (newField->queryType() != cur->queryType())
  8079. {
  8080. VStringBuffer msg("Field %s type mismatch: DFS reports ", str(cur->queryId()));
  8081. cur->queryType()->getECLType(msg).append(" but ECL declared ");
  8082. newField->queryType()->getECLType(msg);
  8083. err.reportWarning(CategoryDFS, HQLWRN_DFSlookupTypeMismatch, msg.str(), str(location.sourcePath), location.lineno, location.column, location.position);
  8084. }
  8085. }
  8086. }
  8087. }
  8088. }
  8089. return allDropped;
  8090. }
  8091. void reportDroppedFields(IHqlExpression * newRecord, IHqlExpression * oldRecord, IErrorReceiver &err, ECLlocation &location)
  8092. {
  8093. if (doReportDroppedFields(newRecord->querySimpleScope(), oldRecord, err, location))
  8094. {
  8095. err.reportWarning(CategoryDFS, HQLWRN_NoFieldsMatch, "No matching fields found in ECL definition", str(location.sourcePath), location.lineno, location.column, location.position);
  8096. }
  8097. }
  8098. //---------------------------------------------------------------------------------------------------------------------
  8099. static void createMappingAssigns(HqlExprArray & assigns, IHqlExpression * selfSelector, IHqlExpression * oldSelector, IHqlSimpleScope * oldScope, IHqlExpression * newRecord, bool replaceMissingWithDefault, IErrorReceiver &err, ECLlocation &location)
  8100. {
  8101. ForEachChild(i, newRecord)
  8102. {
  8103. IHqlExpression * cur = newRecord->queryChild(i);
  8104. switch (cur->getOperator())
  8105. {
  8106. case no_record:
  8107. createMappingAssigns(assigns, selfSelector, oldSelector, oldScope, cur, replaceMissingWithDefault, err, location);
  8108. break;
  8109. case no_ifblock:
  8110. createMappingAssigns(assigns, selfSelector, oldSelector, oldScope, cur->queryChild(1), replaceMissingWithDefault, err, location);
  8111. break;
  8112. case no_field:
  8113. {
  8114. OwnedHqlExpr oldSelected;
  8115. OwnedHqlExpr oldField = oldScope->lookupSymbol(cur->queryId());
  8116. if (!oldField)
  8117. {
  8118. assertex(replaceMissingWithDefault);
  8119. oldSelected.setown(createNullExpr(cur));
  8120. VStringBuffer msg("Field %s is not present in DFS file - default value will be used", str(cur->queryId()));
  8121. err.reportWarning(CategoryInformation, HQLWRN_FieldNotPresentInDFS, msg.str(), str(location.sourcePath), location.lineno, location.column, location.position);
  8122. }
  8123. else
  8124. {
  8125. oldSelected.setown(createSelectExpr(LINK(oldSelector), LINK(oldField)));
  8126. }
  8127. OwnedHqlExpr selfSelected = createSelectExpr(LINK(selfSelector), LINK(cur));
  8128. if (selfSelected->queryRecord() != oldSelected->queryRecord())
  8129. {
  8130. if (!oldSelected->isDatarow())
  8131. {
  8132. assertex(replaceMissingWithDefault);
  8133. VStringBuffer msg("Field %s cannot be mapped - incompatible type ", str(cur->queryId()));
  8134. cur->queryType()->getECLType(msg).append(" (expected ");
  8135. getFriendlyTypeStr(oldSelected->queryType(),msg).append(')');
  8136. err.reportError(HQLERR_DFSlookupIncompatible, msg.str(), str(location.sourcePath), location.lineno, location.column, location.position);
  8137. }
  8138. OwnedHqlExpr childSelf = getSelf(cur);
  8139. OwnedHqlExpr childTransform = createMappingTransform(childSelf, oldSelected, replaceMissingWithDefault, err, location);
  8140. OwnedHqlExpr createRowExpr = createRow(no_createrow, childTransform.getClear());
  8141. assigns.append(*createAssign(selfSelected.getClear(), createRowExpr.getClear()));
  8142. }
  8143. else
  8144. {
  8145. if (!cur->queryType()->assignableFrom(oldSelected->queryType()))
  8146. {
  8147. assertex(replaceMissingWithDefault);
  8148. VStringBuffer msg("Field %s cannot be mapped - incompatible type ", str(cur->queryId()));
  8149. cur->queryType()->getECLType(msg).append(" (expected ");
  8150. getFriendlyTypeStr(oldSelected->queryType(),msg).append(')');
  8151. err.reportError(HQLERR_DFSlookupIncompatible, msg.str(), str(location.sourcePath), location.lineno, location.column, location.position);
  8152. }
  8153. assigns.append(*createAssign(selfSelected.getClear(), oldSelected.getClear()));
  8154. }
  8155. }
  8156. }
  8157. }
  8158. }
  8159. IHqlExpression * createMappingTransform(IHqlExpression * selfSelector, IHqlExpression * inSelector, bool replaceMissingWithDefault, IErrorReceiver &err, ECLlocation &location)
  8160. {
  8161. HqlExprArray assigns;
  8162. IHqlExpression * selfRecord = selfSelector->queryRecord();
  8163. IHqlExpression * inRecord = inSelector->queryRecord();
  8164. createMappingAssigns(assigns, selfSelector, inSelector, inRecord->querySimpleScope(), selfRecord, replaceMissingWithDefault, err, location);
  8165. return createValue(no_transform, makeTransformType(selfRecord->getType()), assigns);
  8166. }
  8167. //---------------------------------------------------------------------------------------------------------------------
  8168. IHqlExpression * expandMacroDefinition(IHqlExpression * expr, HqlLookupContext & ctx, bool reportError)
  8169. {
  8170. assertex(expr->isMacro());
  8171. Owned<IProperties> macroParms = createProperties();
  8172. IHqlExpression * macroBodyExpr;
  8173. if (expr->getOperator() == no_funcdef)
  8174. {
  8175. IHqlExpression * formals = expr->queryChild(1);
  8176. IHqlExpression * defaults = expr->queryChild(2);
  8177. ForEachChild(i, formals)
  8178. {
  8179. IHqlExpression* formal = formals->queryChild(i);
  8180. IHqlExpression* def = queryDefaultValue(defaults, i);
  8181. StringBuffer curParam;
  8182. if (!def || !getFoldedConstantText(curParam, def))
  8183. {
  8184. if (reportError)
  8185. ctx.errs->reportError(HQLERR_CannotSubmitMacroX, "Cannot submit a MACRO with parameters that do no have default values", NULL, 1, 0, 0);
  8186. return NULL;
  8187. }
  8188. macroParms->setProp(str(formal->queryName()), curParam.str());
  8189. }
  8190. macroBodyExpr = expr->queryChild(0);
  8191. }
  8192. else
  8193. macroBodyExpr = expr;
  8194. IFileContents * macroContents = static_cast<IFileContents *>(macroBodyExpr->queryUnknownExtra());
  8195. size32_t len = macroContents->length();
  8196. //Strangely some macros still have the ENDMACRO on the end, and others don't. This should be removed really.
  8197. StringBuffer macroText;
  8198. macroText.append(len, macroContents->getText());
  8199. if ((len >= 8) && strieq(macroText.str()+(len-8),"ENDMACRO"))
  8200. macroText.setLength(len-8);
  8201. //Now append a semi colon since that is how macros are normally called.
  8202. macroText.append(";");
  8203. //This might be cleaner if it was implemented by parsing the text myModule.myAttribute().
  8204. //It would make implementing default parameters easy. However it could introduce other problems
  8205. //with implicitly importing myModule.
  8206. Owned<IFileContents> mappedContents = createFileContentsFromText(macroText.length(), macroText.str(), macroContents->querySourcePath(), false, NULL);
  8207. Owned<IHqlScope> scope = createPrivateScope();
  8208. if (queryLegacyImportSemantics())
  8209. importRootModulesToScope(scope, ctx);
  8210. return parseQuery(scope, mappedContents, ctx, NULL, macroParms, true, true);
  8211. }
  8212. static IHqlExpression * transformAttributeToQuery(IHqlExpression * expr, HqlLookupContext & ctx, bool syntaxCheck)
  8213. {
  8214. if (expr->isMacro())
  8215. return expandMacroDefinition(expr, ctx, true);
  8216. if (expr->isFunction())
  8217. {
  8218. //If a scope with parameters then assume we are building a library.
  8219. if (expr->isScope())
  8220. return LINK(expr);
  8221. HqlExprArray actuals;
  8222. if (!allParametersHaveDefaults(expr))
  8223. {
  8224. if (!expandMissingDefaultsAsStoreds(actuals, expr))
  8225. {
  8226. //For each parameter that doesn't have a default, create a stored variable of the appropriate type
  8227. //with a null value as the default value, and use that.
  8228. const char * name = str(expr->queryName());
  8229. StringBuffer msg;
  8230. msg.appendf("Definition %s() does not supply default values for all parameters", name ? name : "");
  8231. ctx.errs->reportError(HQLERR_CannotSubmitFunction, msg.str(), NULL, 1, 0, 0);
  8232. return NULL;
  8233. }
  8234. }
  8235. return createBoundFunction(ctx.errs, expr, actuals, ctx.functionCache, ctx.queryExpandCallsWhenBound());
  8236. }
  8237. if (expr->isScope())
  8238. {
  8239. IHqlScope * scope = expr->queryScope();
  8240. OwnedHqlExpr main = scope->lookupSymbol(createIdAtom("main"), LSFpublic, ctx);
  8241. if (main)
  8242. return main.getClear();
  8243. if (!syntaxCheck)
  8244. {
  8245. StringBuffer msg;
  8246. const char * name = scope->queryFullName();
  8247. msg.appendf("Module %s does not EXPORT an attribute main()", name ? name : "");
  8248. ctx.errs->reportError(HQLERR_CannotSubmitModule, msg.str(), NULL, 1, 0, 0);
  8249. return NULL;
  8250. }
  8251. }
  8252. return LINK(expr);
  8253. }
  8254. IHqlExpression * convertAttributeToQuery(IHqlExpression * expr, HqlLookupContext & ctx, bool syntaxCheck)
  8255. {
  8256. OwnedHqlExpr query = LINK(expr);
  8257. for (;;)
  8258. {
  8259. OwnedHqlExpr transformed = transformAttributeToQuery(query, ctx, syntaxCheck);
  8260. if (!transformed || transformed == query)
  8261. return transformed.getClear();
  8262. query.set(transformed);
  8263. }
  8264. }
  8265. bool isSetWithUnknownElementSize(ITypeInfo * type)
  8266. {
  8267. switch (type->getTypeCode())
  8268. {
  8269. case type_set:
  8270. case type_array:
  8271. return isUnknownSize(type->queryChildType());
  8272. }
  8273. return false;
  8274. }
  8275. IHqlExpression * replaceParameters(IHqlExpression * body, IHqlExpression * oldParams, IHqlExpression * newParams)
  8276. {
  8277. HqlMapTransformer simpleTransformer;
  8278. ForEachChild(i, oldParams)
  8279. {
  8280. IHqlExpression * from = oldParams->queryChild(i);
  8281. IHqlExpression * to = newParams->queryChild(i);
  8282. simpleTransformer.setMapping(from, to);
  8283. }
  8284. return simpleTransformer.transformRoot(body);
  8285. }
  8286. //---------------------------------------------------------------------------------------------------------------------
  8287. /*
  8288. Aliases are nasty...they can occur in two different situations
  8289. i) The user specifies TABLE(x) to create an alias
  8290. ii) The scope checking spots that an alias is being implicitly created.
  8291. 1) exists(join(ds, ds, left.id*3=right.id));
  8292. ds_1 := table(ds);
  8293. ds(exists(ds_1(ds_1.id=ds.id*3)));
  8294. a) ds is a table
  8295. b) ds is a filtered table.
  8296. c) ds is an implicitly normalized dataset (ds.child);
  8297. d) ds is a projected table
  8298. e) ds is a filtered projected table.
  8299. 2) ds(exists(join(child, child, left.id*3=right.id)));
  8300. child_1 = table(ds.child);
  8301. ds(exists(child(exists(child1(child_1.id = child.id*3)));
  8302. a) ds is a table
  8303. b) ds is a filtered table.
  8304. c) ds is an implicitly normalized dataset (ds.child);
  8305. d) ds is a projected table
  8306. e) ds is a filtered projected table.
  8307. When either of these occurs a no_dataset_alias node is added to the tree with a unique id. We don't want to modify
  8308. any of the input datasets - because we want them to stay common as long as possible - otherwise code like
  8309. ds(field in ds(filter)) would cause ds to become split in two - and it should mean the same thing.
  8310. For implicit aliases they will be added around the dataset that is ambiguous.
  8311. - It would be simpler to add them around the table that is ambiguous (Table is a dataset that defines a column list)
  8312. but that means that sort, filters etc. aren't commoned up.
  8313. - When the code is actually generated the base table is modified - which ensures no ambiguous expressions are
  8314. actually present when generating.
  8315. E.g,
  8316. x := ds(a <> 0);
  8317. x(b in set(x(c <> 0), b))
  8318. becomes
  8319. x := ds(a <> 0);
  8320. x' = table(x);
  8321. x'(b in set(x(c <> 0), b))
  8322. To avoid that the aliases is not added around a dataset that has already been aliased in the dataset that uses it.
  8323. When the expression comes to be generated/evaluated, the underlying table of the dataset expression is modified to
  8324. include a unique id. The root table doesn't need to be modified because no selectors for that can be in scope.
  8325. */
  8326. IHqlExpression * queryTableOrSplitter(IHqlExpression * expr)
  8327. {
  8328. for (;;)
  8329. {
  8330. node_operator op = expr->getOperator();
  8331. if (op == no_compound)
  8332. expr = expr->queryChild(1);
  8333. else if (definesColumnList(expr))
  8334. return expr;
  8335. else if (op == no_split)
  8336. return expr;
  8337. else
  8338. expr = expr->queryChild(0);
  8339. }
  8340. }
  8341. //Convert no_dataset_alias(expr, uid) to expr'
  8342. IHqlExpression * normalizeDatasetAlias(IHqlExpression * expr)
  8343. {
  8344. IHqlExpression * uid = expr->queryAttribute(_uid_Atom);
  8345. assertex(uid);
  8346. IHqlExpression * dataset = expr->queryChild(0);
  8347. IHqlExpression * table = queryTableOrSplitter(dataset);
  8348. //If the alias is based on a splitter then we need to ensure the splitter expression stays the same - otherwise
  8349. //if won't be commoned up. So add a alias with a _normalized_Atom to ensure everything followed that will be
  8350. //unique. Otherwise add a unique id onto the underlying table to ensure unique expressions.
  8351. OwnedHqlExpr newTable;
  8352. node_operator tableOp = table->getOperator();
  8353. if ((tableOp == no_split) || (tableOp == no_rows))
  8354. newTable.setown(createDataset(no_dataset_alias, LINK(table), createComma(createUniqueId(), createAttribute(_normalized_Atom))));
  8355. else
  8356. newTable.setown(appendOwnedOperand(table, LINK(uid)));
  8357. return replaceDataset(dataset, table, newTable);
  8358. }
  8359. //---------------------------------------------------------------------------------------------------------------------
  8360. //This should only be called on source activities, and on inline datasets.
  8361. IHqlExpression * normalizeAnyDatasetAliases(IHqlExpression * expr)
  8362. {
  8363. //It is useful to also be able to call this on no_sum(aliased-dataset)
  8364. if (!containsDatasetAliasLocally(expr) && !expr->isAggregate())
  8365. return LINK(expr);
  8366. node_operator op = expr->getOperator();
  8367. IHqlExpression * selector = NULL;
  8368. switch (getChildDatasetType(expr))
  8369. {
  8370. case childdataset_none:
  8371. if ((op == no_select) && isNewSelector(expr))
  8372. break;
  8373. return LINK(expr);
  8374. case childdataset_dataset:
  8375. case childdataset_dataset_noscope:
  8376. case childdataset_datasetleft:
  8377. case childdataset_top_left_right:
  8378. selector = expr->queryChild(0)->queryNormalizedSelector();
  8379. break;
  8380. case childdataset_left:
  8381. case childdataset_leftright:
  8382. case childdataset_many:
  8383. case childdataset_many_noscope:
  8384. break;
  8385. default:
  8386. return LINK(expr);
  8387. throwUnexpected();
  8388. }
  8389. bool same = true;
  8390. HqlExprArray args;
  8391. unsigned max = getNumChildTables(expr);
  8392. for (unsigned i=0; i < max; i++)
  8393. {
  8394. IHqlExpression * dataset = expr->queryChild(i);
  8395. OwnedHqlExpr newDataset = normalizeAnyDatasetAliases(dataset);
  8396. if (dataset != newDataset)
  8397. same = false;
  8398. args.append(*newDataset.getClear());
  8399. }
  8400. OwnedHqlExpr transformed;
  8401. if (same)
  8402. transformed.set(expr);
  8403. else
  8404. {
  8405. if (selector)
  8406. {
  8407. assertex(max == 1);
  8408. replaceSelectors(args, expr, max, selector, args.item(0).queryNormalizedSelector());
  8409. }
  8410. else
  8411. unwindChildren(args, expr, max);
  8412. transformed.setown(expr->clone(args));
  8413. }
  8414. if ((op == no_dataset_alias) && !transformed->hasAttribute(_normalized_Atom))
  8415. return normalizeDatasetAlias(transformed);
  8416. return transformed.getClear();
  8417. }
  8418. bool userPreventsSort(IHqlExpression * noSortAttr, node_operator side)
  8419. {
  8420. if (!noSortAttr)
  8421. return false;
  8422. IHqlExpression * child = noSortAttr->queryChild(0);
  8423. if (!child)
  8424. return true;
  8425. IAtom * name = child->queryName();
  8426. if (side == no_left)
  8427. return name == leftAtom;
  8428. if (side == no_right)
  8429. return name == rightAtom;
  8430. throwUnexpected();
  8431. }
  8432. //-------------------------------------------------------------------------------------------------
  8433. IHqlExpression * queryTransformAssign(IHqlExpression * transform, IHqlExpression * searchField)
  8434. {
  8435. while (transform->getOperator() == no_alias_scope)
  8436. transform = transform->queryChild(0);
  8437. ForEachChild(i, transform)
  8438. {
  8439. IHqlExpression * cur = transform->queryChild(i);
  8440. if (cur->getOperator() == no_alias_scope)
  8441. cur = cur->queryChild(0);
  8442. switch (cur->getOperator())
  8443. {
  8444. case no_assignall:
  8445. {
  8446. IHqlExpression * ret = queryTransformAssign(cur, searchField);
  8447. if (ret)
  8448. return ret;
  8449. break;
  8450. }
  8451. case no_assign:
  8452. {
  8453. IHqlExpression * lhs = cur->queryChild(0)->queryChild(1);
  8454. if (lhs == searchField)
  8455. return cur;
  8456. if (lhs->queryId() == searchField->queryId())
  8457. return cur;
  8458. break;
  8459. }
  8460. }
  8461. }
  8462. return NULL;
  8463. }
  8464. IHqlExpression * queryTransformAssignValue(IHqlExpression * transform, IHqlExpression * searchField)
  8465. {
  8466. IHqlExpression * value = queryTransformAssign(transform, searchField);
  8467. if (value)
  8468. return value->queryChild(1);
  8469. return NULL;
  8470. }
  8471. //-------------------------------------------------------------------------------------------------
  8472. IHqlExpression * convertSetToExpression(bool isAll, size32_t len, const void * ptr, ITypeInfo * setType)
  8473. {
  8474. HqlExprArray results;
  8475. const byte *presult = (const byte *) ptr;
  8476. const byte *presult_end = presult + len;
  8477. if (isAll)
  8478. return createValue(no_all, LINK(setType));
  8479. ITypeInfo * elementType = setType->queryChildType();
  8480. switch(elementType->getTypeCode())
  8481. {
  8482. case type_unicode:
  8483. while (presult < presult_end)
  8484. {
  8485. const size32_t numUChars = *((size32_t *) presult);
  8486. presult += sizeof(size32_t);
  8487. results.append(*createConstant(createUnicodeValue(numUChars, presult, LINK(elementType))));
  8488. presult += numUChars*sizeof(UChar);
  8489. };
  8490. break;
  8491. case type_string:
  8492. while (presult < presult_end)
  8493. {
  8494. const size32_t numUChars = *((size32_t *) presult);
  8495. presult += sizeof(size32_t);
  8496. results.append(*createConstant(createStringValue( (const char*)presult, (unsigned)numUChars)));
  8497. presult += numUChars;
  8498. };
  8499. break;
  8500. default:
  8501. UNIMPLEMENTED;
  8502. }
  8503. return createValue(no_list, LINK(setType), results);
  8504. }
  8505. //-------------------------------------------------------------------------------------------------
  8506. void getFieldTypeInfo(FieldTypeInfoStruct &out, ITypeInfo *type)
  8507. {
  8508. assertex(type);
  8509. type_t tc = type->getTypeCode();
  8510. if (tc == type_record)
  8511. type = queryUnqualifiedType(type);
  8512. if (tc == type_alien)
  8513. {
  8514. ITypeInfo * physicalType = queryAlienType(type)->queryPhysicalType();
  8515. if (physicalType->getSize() != UNKNOWN_LENGTH)
  8516. {
  8517. //Don't use the generated class for xml generation since it will generate physical rather than logical
  8518. out.fieldType |= (RFTMalien|RFTMinvalidxml|RFTMnoserialize);
  8519. type = physicalType;
  8520. tc = type->getTypeCode();
  8521. }
  8522. else
  8523. {
  8524. out.fieldType |= RFTMunknownsize;
  8525. //can't work out the size of the field - to keep it as unknown for the moment.
  8526. //until the alien field type is supported
  8527. }
  8528. }
  8529. out.fieldType |= tc;
  8530. out.length = type->getSize();
  8531. out.locale = nullptr;
  8532. out.className = nullptr;
  8533. if (out.length == UNKNOWN_LENGTH)
  8534. {
  8535. out.fieldType |= RFTMunknownsize;
  8536. out.length = 0;
  8537. }
  8538. switch (tc)
  8539. {
  8540. case type_boolean:
  8541. out.className = "RtlBoolTypeInfo";
  8542. break;
  8543. case type_real:
  8544. out.className ="RtlRealTypeInfo";
  8545. break;
  8546. case type_date:
  8547. case type_enumerated:
  8548. case type_int:
  8549. out.className = "RtlIntTypeInfo";
  8550. if (!type->isSigned())
  8551. out.fieldType |= RFTMunsigned;
  8552. break;
  8553. case type_swapint:
  8554. out.className = "RtlSwapIntTypeInfo";
  8555. if (!type->isSigned())
  8556. out.fieldType |= RFTMunsigned;
  8557. break;
  8558. case type_packedint:
  8559. out.className = "RtlPackedIntTypeInfo";
  8560. if (!type->isSigned())
  8561. out.fieldType |= RFTMunsigned;
  8562. break;
  8563. case type_decimal:
  8564. out.className = "RtlDecimalTypeInfo";
  8565. if (!type->isSigned())
  8566. out.fieldType |= RFTMunsigned;
  8567. out.length = type->getDigits() | (type->getPrecision() << 16);
  8568. break;
  8569. case type_char:
  8570. out.className = "RtlCharTypeInfo";
  8571. break;
  8572. case type_data:
  8573. out.className = "RtlDataTypeInfo";
  8574. break;
  8575. case type_qstring:
  8576. out.className = "RtlQStringTypeInfo";
  8577. out.length = type->getStringLen();
  8578. break;
  8579. case type_varstring:
  8580. out.className = "RtlVarStringTypeInfo";
  8581. if (type->queryCharset() && type->queryCharset()->queryName()==ebcdicAtom)
  8582. out.fieldType |= RFTMebcdic;
  8583. out.length = type->getStringLen();
  8584. break;
  8585. case type_string:
  8586. out.className = "RtlStringTypeInfo";
  8587. if (type->queryCharset() && type->queryCharset()->queryName()==ebcdicAtom)
  8588. out.fieldType |= RFTMebcdic;
  8589. break;
  8590. case type_bitfield:
  8591. {
  8592. out.className = "RtlBitfieldTypeInfo";
  8593. unsigned size = type->queryChildType()->getSize();
  8594. unsigned bitsize = type->getBitSize();
  8595. unsigned offset = (unsigned)getIntValue(queryAttributeChild(type, bitfieldOffsetAtom, 0),-1);
  8596. bool isLastBitfield = (queryAttribute(type, isLastBitfieldAtom) != NULL);
  8597. if (isLastBitfield)
  8598. out.fieldType |= RFTMislastbitfield;
  8599. if (!type->isSigned())
  8600. out.fieldType |= RFTMunsigned;
  8601. out.length = size | (bitsize << 8) | (offset << 16);
  8602. break;
  8603. }
  8604. case type_record:
  8605. {
  8606. IHqlExpression * record = ::queryRecord(type);
  8607. out.className = "RtlRecordTypeInfo";
  8608. out.length = getMinRecordSize(record);
  8609. if (!isFixedSizeRecord(record))
  8610. out.fieldType |= RFTMunknownsize;
  8611. break;
  8612. }
  8613. case type_row:
  8614. {
  8615. out.className = "RtlRowTypeInfo";
  8616. if (hasLinkCountedModifier(type))
  8617. out.fieldType |= RFTMlinkcounted;
  8618. break;
  8619. }
  8620. case type_table:
  8621. case type_groupedtable:
  8622. {
  8623. out.className = "RtlDatasetTypeInfo";
  8624. if (hasLinkCountedModifier(type))
  8625. {
  8626. out.fieldType |= RFTMlinkcounted;
  8627. out.fieldType &= ~RFTMunknownsize;
  8628. }
  8629. break;
  8630. }
  8631. case type_dictionary:
  8632. {
  8633. out.className = "RtlDictionaryTypeInfo";
  8634. out.fieldType |= RFTMnoserialize;
  8635. if (hasLinkCountedModifier(type))
  8636. {
  8637. out.fieldType |= RFTMlinkcounted;
  8638. out.fieldType &= ~RFTMunknownsize;
  8639. }
  8640. break;
  8641. }
  8642. case type_set:
  8643. out.className = "RtlSetTypeInfo";
  8644. break;
  8645. case type_unicode:
  8646. out.className = "RtlUnicodeTypeInfo";
  8647. out.locale = str(type->queryLocale());
  8648. out.length = type->getStringLen();
  8649. break;
  8650. case type_varunicode:
  8651. out.className = "RtlVarUnicodeTypeInfo";
  8652. out.locale = str(type->queryLocale());
  8653. out.length = type->getStringLen();
  8654. break;
  8655. case type_utf8:
  8656. out.className = "RtlUtf8TypeInfo";
  8657. out.locale = str(type->queryLocale());
  8658. out.length = type->getStringLen();
  8659. break;
  8660. case type_blob:
  8661. case type_pointer:
  8662. case type_class:
  8663. case type_array:
  8664. case type_void:
  8665. case type_alien:
  8666. case type_none:
  8667. case type_any:
  8668. case type_pattern:
  8669. case type_rule:
  8670. case type_token:
  8671. case type_feature:
  8672. case type_event:
  8673. case type_null:
  8674. case type_scope:
  8675. case type_transform:
  8676. default:
  8677. out.className = "RtlUnimplementedTypeInfo";
  8678. out.fieldType |= (RFTMcontainsunknown|RFTMinvalidxml|RFTMnoserialize);
  8679. break;
  8680. }
  8681. }
  8682. bool checkXpathIsNonScalar(const char *xpath)
  8683. {
  8684. return (strpbrk(xpath, "/?*[]<>")!=NULL); //anything other than a single tag/attr name cannot name a scalar field
  8685. }
  8686. unsigned buildRtlRecordFields(IRtlFieldTypeDeserializer &deserializer, unsigned &idx, const RtlFieldInfo * * fieldsArray, IHqlExpression *record, IHqlExpression *rowRecord)
  8687. {
  8688. unsigned typeFlags = 0;
  8689. ForEachChild(i, record)
  8690. {
  8691. unsigned fieldFlags = 0;
  8692. IHqlExpression * field = record->queryChild(i);
  8693. switch (field->getOperator())
  8694. {
  8695. case no_ifblock:
  8696. typeFlags |= RFTMnoserialize;
  8697. break;
  8698. case no_field:
  8699. {
  8700. ITypeInfo *fieldType = field->queryType();
  8701. switch (fieldType->getTypeCode())
  8702. {
  8703. case type_alien:
  8704. //MORE:::
  8705. break;
  8706. case type_row:
  8707. //Backward compatibility - should revisit
  8708. fieldType = fieldType->queryChildType();
  8709. break;
  8710. case type_bitfield:
  8711. UNIMPLEMENTED;
  8712. break;
  8713. }
  8714. const RtlTypeInfo *type = buildRtlType(deserializer, fieldType);
  8715. typeFlags |= type->fieldType & RFTMinherited;
  8716. StringBuffer lowerName;
  8717. lowerName.append(field->queryName()).toLowerCase();
  8718. StringBuffer xpathName, xpathItem;
  8719. switch (field->queryType()->getTypeCode())
  8720. {
  8721. case type_set:
  8722. extractXmlName(xpathName, &xpathItem, NULL, field, "Item", false);
  8723. break;
  8724. case type_dictionary:
  8725. case type_table:
  8726. case type_groupedtable:
  8727. extractXmlName(xpathName, &xpathItem, NULL, field, "Row", false);
  8728. //Following should be in the type processing, and the type should include the information
  8729. if (field->hasAttribute(sizeAtom) || field->hasAttribute(countAtom))
  8730. fieldFlags |= RFTMinvalidxml;
  8731. break;
  8732. default:
  8733. extractXmlName(xpathName, NULL, NULL, field, NULL, false);
  8734. break;
  8735. }
  8736. //Format of the xpath field is (nested-item 0x01 repeated-item)
  8737. if (xpathItem.length())
  8738. xpathName.append(xpathCompoundSeparatorChar).append(xpathItem);
  8739. if (xpathName.charAt(0) == '@')
  8740. fieldFlags |= RFTMhasxmlattr;
  8741. if (checkXpathIsNonScalar(xpathName))
  8742. fieldFlags |= RFTMhasnonscalarxpath;
  8743. const char *xpath = xpathName.str();
  8744. if (strcmp(lowerName, xpath)==0)
  8745. xpath = nullptr;
  8746. MemoryBuffer defaultInitializer;
  8747. IHqlExpression *defaultValue = queryAttributeChild(field, defaultAtom, 0);
  8748. if (defaultValue)
  8749. {
  8750. LinkedHqlExpr targetField = field;
  8751. if (fieldType->getTypeCode() == type_bitfield)
  8752. targetField.setown(createField(field->queryId(), LINK(fieldType->queryChildType()), NULL));
  8753. if (!createConstantField(defaultInitializer, targetField, defaultValue))
  8754. UNIMPLEMENTED; // MORE - fail more gracefully!
  8755. }
  8756. fieldsArray[idx] = deserializer.addFieldInfo(lowerName, xpath, type, fieldFlags, (const char *) defaultInitializer.detach());
  8757. typeFlags |= fieldFlags & RFTMinherited;
  8758. idx++;
  8759. break;
  8760. }
  8761. case no_record:
  8762. typeFlags |= buildRtlRecordFields(deserializer, idx, fieldsArray, field, rowRecord);
  8763. break;
  8764. }
  8765. }
  8766. return typeFlags;
  8767. }
  8768. const RtlTypeInfo *buildRtlType(IRtlFieldTypeDeserializer &deserializer, ITypeInfo *type)
  8769. {
  8770. assertex(type);
  8771. switch (type->getTypeCode())
  8772. {
  8773. case type_alien:
  8774. //MORE:::
  8775. break;
  8776. case type_row:
  8777. //Backward compatibility - should revisit
  8778. return buildRtlType(deserializer, type->queryChildType());
  8779. //case type_bitfield:
  8780. //fieldKey contains a field with a type annotated with offsets/isLastBitfield
  8781. //OwnedHqlExpr fieldKey = getRtlFieldKey(field, rowRecord);
  8782. //return buildRtlType(deserializer, fieldKey->queryType());
  8783. }
  8784. const RtlTypeInfo * found = deserializer.lookupType(type);
  8785. if (found)
  8786. return found;
  8787. FieldTypeInfoStruct info;
  8788. getFieldTypeInfo(info, type);
  8789. switch (info.fieldType & RFTMkind)
  8790. {
  8791. case type_record:
  8792. {
  8793. IHqlExpression * record = ::queryRecord(type);
  8794. unsigned numFields = getFlatFieldCount(record);
  8795. info.fieldsArray = new const RtlFieldInfo * [numFields+1];
  8796. unsigned idx = 0;
  8797. info.fieldType |= buildRtlRecordFields(deserializer, idx, info.fieldsArray, record, record);
  8798. info.fieldsArray[idx] = nullptr;
  8799. break;
  8800. }
  8801. case type_row:
  8802. {
  8803. info.childType = buildRtlType(deserializer, ::queryRecordType(type));
  8804. break;
  8805. }
  8806. case type_table:
  8807. case type_groupedtable:
  8808. {
  8809. info.childType = buildRtlType(deserializer, ::queryRecordType(type));
  8810. break;
  8811. }
  8812. case type_dictionary:
  8813. return nullptr; // MORE - does this leak?
  8814. case type_set:
  8815. info.childType = buildRtlType(deserializer, type->queryChildType());
  8816. break;
  8817. }
  8818. if (info.childType)
  8819. info.fieldType |= info.childType->fieldType & RFTMinherited;
  8820. return deserializer.addType(info, type);
  8821. }