fts5_index.c 288 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408
  1. /*
  2. ** 2014 May 31
  3. **
  4. ** The author disclaims copyright to this source code. In place of
  5. ** a legal notice, here is a blessing:
  6. **
  7. ** May you do good and not evil.
  8. ** May you find forgiveness for yourself and forgive others.
  9. ** May you share freely, never taking more than you give.
  10. **
  11. ******************************************************************************
  12. **
  13. ** Low level access to the FTS index stored in the database file. The
  14. ** routines in this file file implement all read and write access to the
  15. ** %_data table. Other parts of the system access this functionality via
  16. ** the interface defined in fts5Int.h.
  17. */
  18. #include "fts5Int.h"
  19. /*
  20. ** Overview:
  21. **
  22. ** The %_data table contains all the FTS indexes for an FTS5 virtual table.
  23. ** As well as the main term index, there may be up to 31 prefix indexes.
  24. ** The format is similar to FTS3/4, except that:
  25. **
  26. ** * all segment b-tree leaf data is stored in fixed size page records
  27. ** (e.g. 1000 bytes). A single doclist may span multiple pages. Care is
  28. ** taken to ensure it is possible to iterate in either direction through
  29. ** the entries in a doclist, or to seek to a specific entry within a
  30. ** doclist, without loading it into memory.
  31. **
  32. ** * large doclists that span many pages have associated "doclist index"
  33. ** records that contain a copy of the first rowid on each page spanned by
  34. ** the doclist. This is used to speed up seek operations, and merges of
  35. ** large doclists with very small doclists.
  36. **
  37. ** * extra fields in the "structure record" record the state of ongoing
  38. ** incremental merge operations.
  39. **
  40. */
  41. #define FTS5_OPT_WORK_UNIT 1000 /* Number of leaf pages per optimize step */
  42. #define FTS5_WORK_UNIT 64 /* Number of leaf pages in unit of work */
  43. #define FTS5_MIN_DLIDX_SIZE 4 /* Add dlidx if this many empty pages */
  44. #define FTS5_MAIN_PREFIX '0'
  45. #if FTS5_MAX_PREFIX_INDEXES > 31
  46. # error "FTS5_MAX_PREFIX_INDEXES is too large"
  47. #endif
  48. #define FTS5_MAX_LEVEL 64
  49. /*
  50. ** There are two versions of the format used for the structure record:
  51. **
  52. ** 1. the legacy format, that may be read by all fts5 versions, and
  53. **
  54. ** 2. the V2 format, which is used by contentless_delete=1 databases.
  55. **
  56. ** Both begin with a 4-byte "configuration cookie" value. Then, a legacy
  57. ** format structure record contains a varint - the number of levels in
  58. ** the structure. Whereas a V2 structure record contains the constant
  59. ** 4 bytes [0xff 0x00 0x00 0x01]. This is unambiguous as the value of a
  60. ** varint has to be at least 16256 to begin with "0xFF". And the default
  61. ** maximum number of levels is 64.
  62. **
  63. ** See below for more on structure record formats.
  64. */
  65. #define FTS5_STRUCTURE_V2 "\xFF\x00\x00\x01"
  66. /*
  67. ** Details:
  68. **
  69. ** The %_data table managed by this module,
  70. **
  71. ** CREATE TABLE %_data(id INTEGER PRIMARY KEY, block BLOB);
  72. **
  73. ** , contains the following 6 types of records. See the comments surrounding
  74. ** the FTS5_*_ROWID macros below for a description of how %_data rowids are
  75. ** assigned to each fo them.
  76. **
  77. ** 1. Structure Records:
  78. **
  79. ** The set of segments that make up an index - the index structure - are
  80. ** recorded in a single record within the %_data table. The record consists
  81. ** of a single 32-bit configuration cookie value followed by a list of
  82. ** SQLite varints.
  83. **
  84. ** If the structure record is a V2 record, the configuration cookie is
  85. ** followed by the following 4 bytes: [0xFF 0x00 0x00 0x01].
  86. **
  87. ** Next, the record continues with three varints:
  88. **
  89. ** + number of levels,
  90. ** + total number of segments on all levels,
  91. ** + value of write counter.
  92. **
  93. ** Then, for each level from 0 to nMax:
  94. **
  95. ** + number of input segments in ongoing merge.
  96. ** + total number of segments in level.
  97. ** + for each segment from oldest to newest:
  98. ** + segment id (always > 0)
  99. ** + first leaf page number (often 1, always greater than 0)
  100. ** + final leaf page number
  101. **
  102. ** Then, for V2 structures only:
  103. **
  104. ** + lower origin counter value,
  105. ** + upper origin counter value,
  106. ** + the number of tombstone hash pages.
  107. **
  108. ** 2. The Averages Record:
  109. **
  110. ** A single record within the %_data table. The data is a list of varints.
  111. ** The first value is the number of rows in the index. Then, for each column
  112. ** from left to right, the total number of tokens in the column for all
  113. ** rows of the table.
  114. **
  115. ** 3. Segment leaves:
  116. **
  117. ** TERM/DOCLIST FORMAT:
  118. **
  119. ** Most of each segment leaf is taken up by term/doclist data. The
  120. ** general format of term/doclist, starting with the first term
  121. ** on the leaf page, is:
  122. **
  123. ** varint : size of first term
  124. ** blob: first term data
  125. ** doclist: first doclist
  126. ** zero-or-more {
  127. ** varint: number of bytes in common with previous term
  128. ** varint: number of bytes of new term data (nNew)
  129. ** blob: nNew bytes of new term data
  130. ** doclist: next doclist
  131. ** }
  132. **
  133. ** doclist format:
  134. **
  135. ** varint: first rowid
  136. ** poslist: first poslist
  137. ** zero-or-more {
  138. ** varint: rowid delta (always > 0)
  139. ** poslist: next poslist
  140. ** }
  141. **
  142. ** poslist format:
  143. **
  144. ** varint: size of poslist in bytes multiplied by 2, not including
  145. ** this field. Plus 1 if this entry carries the "delete" flag.
  146. ** collist: collist for column 0
  147. ** zero-or-more {
  148. ** 0x01 byte
  149. ** varint: column number (I)
  150. ** collist: collist for column I
  151. ** }
  152. **
  153. ** collist format:
  154. **
  155. ** varint: first offset + 2
  156. ** zero-or-more {
  157. ** varint: offset delta + 2
  158. ** }
  159. **
  160. ** PAGE FORMAT
  161. **
  162. ** Each leaf page begins with a 4-byte header containing 2 16-bit
  163. ** unsigned integer fields in big-endian format. They are:
  164. **
  165. ** * The byte offset of the first rowid on the page, if it exists
  166. ** and occurs before the first term (otherwise 0).
  167. **
  168. ** * The byte offset of the start of the page footer. If the page
  169. ** footer is 0 bytes in size, then this field is the same as the
  170. ** size of the leaf page in bytes.
  171. **
  172. ** The page footer consists of a single varint for each term located
  173. ** on the page. Each varint is the byte offset of the current term
  174. ** within the page, delta-compressed against the previous value. In
  175. ** other words, the first varint in the footer is the byte offset of
  176. ** the first term, the second is the byte offset of the second less that
  177. ** of the first, and so on.
  178. **
  179. ** The term/doclist format described above is accurate if the entire
  180. ** term/doclist data fits on a single leaf page. If this is not the case,
  181. ** the format is changed in two ways:
  182. **
  183. ** + if the first rowid on a page occurs before the first term, it
  184. ** is stored as a literal value:
  185. **
  186. ** varint: first rowid
  187. **
  188. ** + the first term on each page is stored in the same way as the
  189. ** very first term of the segment:
  190. **
  191. ** varint : size of first term
  192. ** blob: first term data
  193. **
  194. ** 5. Segment doclist indexes:
  195. **
  196. ** Doclist indexes are themselves b-trees, however they usually consist of
  197. ** a single leaf record only. The format of each doclist index leaf page
  198. ** is:
  199. **
  200. ** * Flags byte. Bits are:
  201. ** 0x01: Clear if leaf is also the root page, otherwise set.
  202. **
  203. ** * Page number of fts index leaf page. As a varint.
  204. **
  205. ** * First rowid on page indicated by previous field. As a varint.
  206. **
  207. ** * A list of varints, one for each subsequent termless page. A
  208. ** positive delta if the termless page contains at least one rowid,
  209. ** or an 0x00 byte otherwise.
  210. **
  211. ** Internal doclist index nodes are:
  212. **
  213. ** * Flags byte. Bits are:
  214. ** 0x01: Clear for root page, otherwise set.
  215. **
  216. ** * Page number of first child page. As a varint.
  217. **
  218. ** * Copy of first rowid on page indicated by previous field. As a varint.
  219. **
  220. ** * A list of delta-encoded varints - the first rowid on each subsequent
  221. ** child page.
  222. **
  223. ** 6. Tombstone Hash Page
  224. **
  225. ** These records are only ever present in contentless_delete=1 tables.
  226. ** There are zero or more of these associated with each segment. They
  227. ** are used to store the tombstone rowids for rows contained in the
  228. ** associated segments.
  229. **
  230. ** The set of nHashPg tombstone hash pages associated with a single
  231. ** segment together form a single hash table containing tombstone rowids.
  232. ** To find the page of the hash on which a key might be stored:
  233. **
  234. ** iPg = (rowid % nHashPg)
  235. **
  236. ** Then, within page iPg, which has nSlot slots:
  237. **
  238. ** iSlot = (rowid / nHashPg) % nSlot
  239. **
  240. ** Each tombstone hash page begins with an 8 byte header:
  241. **
  242. ** 1-byte: Key-size (the size in bytes of each slot). Either 4 or 8.
  243. ** 1-byte: rowid-0-tombstone flag. This flag is only valid on the
  244. ** first tombstone hash page for each segment (iPg=0). If set,
  245. ** the hash table contains rowid 0. If clear, it does not.
  246. ** Rowid 0 is handled specially.
  247. ** 2-bytes: unused.
  248. ** 4-bytes: Big-endian integer containing number of entries on page.
  249. **
  250. ** Following this are nSlot 4 or 8 byte slots (depending on the key-size
  251. ** in the first byte of the page header). The number of slots may be
  252. ** determined based on the size of the page record and the key-size:
  253. **
  254. ** nSlot = (nByte - 8) / key-size
  255. */
  256. /*
  257. ** Rowids for the averages and structure records in the %_data table.
  258. */
  259. #define FTS5_AVERAGES_ROWID 1 /* Rowid used for the averages record */
  260. #define FTS5_STRUCTURE_ROWID 10 /* The structure record */
  261. /*
  262. ** Macros determining the rowids used by segment leaves and dlidx leaves
  263. ** and nodes. All nodes and leaves are stored in the %_data table with large
  264. ** positive rowids.
  265. **
  266. ** Each segment has a unique non-zero 16-bit id.
  267. **
  268. ** The rowid for each segment leaf is found by passing the segment id and
  269. ** the leaf page number to the FTS5_SEGMENT_ROWID macro. Leaves are numbered
  270. ** sequentially starting from 1.
  271. */
  272. #define FTS5_DATA_ID_B 16 /* Max seg id number 65535 */
  273. #define FTS5_DATA_DLI_B 1 /* Doclist-index flag (1 bit) */
  274. #define FTS5_DATA_HEIGHT_B 5 /* Max dlidx tree height of 32 */
  275. #define FTS5_DATA_PAGE_B 31 /* Max page number of 2147483648 */
  276. #define fts5_dri(segid, dlidx, height, pgno) ( \
  277. ((i64)(segid) << (FTS5_DATA_PAGE_B+FTS5_DATA_HEIGHT_B+FTS5_DATA_DLI_B)) + \
  278. ((i64)(dlidx) << (FTS5_DATA_PAGE_B + FTS5_DATA_HEIGHT_B)) + \
  279. ((i64)(height) << (FTS5_DATA_PAGE_B)) + \
  280. ((i64)(pgno)) \
  281. )
  282. #define FTS5_SEGMENT_ROWID(segid, pgno) fts5_dri(segid, 0, 0, pgno)
  283. #define FTS5_DLIDX_ROWID(segid, height, pgno) fts5_dri(segid, 1, height, pgno)
  284. #define FTS5_TOMBSTONE_ROWID(segid,ipg) fts5_dri(segid+(1<<16), 0, 0, ipg)
  285. #ifdef SQLITE_DEBUG
  286. int sqlite3Fts5Corrupt() { return SQLITE_CORRUPT_VTAB; }
  287. #endif
  288. /*
  289. ** Each time a blob is read from the %_data table, it is padded with this
  290. ** many zero bytes. This makes it easier to decode the various record formats
  291. ** without overreading if the records are corrupt.
  292. */
  293. #define FTS5_DATA_ZERO_PADDING 8
  294. #define FTS5_DATA_PADDING 20
  295. typedef struct Fts5Data Fts5Data;
  296. typedef struct Fts5DlidxIter Fts5DlidxIter;
  297. typedef struct Fts5DlidxLvl Fts5DlidxLvl;
  298. typedef struct Fts5DlidxWriter Fts5DlidxWriter;
  299. typedef struct Fts5Iter Fts5Iter;
  300. typedef struct Fts5PageWriter Fts5PageWriter;
  301. typedef struct Fts5SegIter Fts5SegIter;
  302. typedef struct Fts5DoclistIter Fts5DoclistIter;
  303. typedef struct Fts5SegWriter Fts5SegWriter;
  304. typedef struct Fts5Structure Fts5Structure;
  305. typedef struct Fts5StructureLevel Fts5StructureLevel;
  306. typedef struct Fts5StructureSegment Fts5StructureSegment;
  307. typedef struct Fts5TokenDataIter Fts5TokenDataIter;
  308. typedef struct Fts5TokenDataMap Fts5TokenDataMap;
  309. typedef struct Fts5TombstoneArray Fts5TombstoneArray;
  310. struct Fts5Data {
  311. u8 *p; /* Pointer to buffer containing record */
  312. int nn; /* Size of record in bytes */
  313. int szLeaf; /* Size of leaf without page-index */
  314. };
  315. /*
  316. ** One object per %_data table.
  317. **
  318. ** nContentlessDelete:
  319. ** The number of contentless delete operations since the most recent
  320. ** call to fts5IndexFlush() or fts5IndexDiscardData(). This is tracked
  321. ** so that extra auto-merge work can be done by fts5IndexFlush() to
  322. ** account for the delete operations.
  323. */
  324. struct Fts5Index {
  325. Fts5Config *pConfig; /* Virtual table configuration */
  326. char *zDataTbl; /* Name of %_data table */
  327. int nWorkUnit; /* Leaf pages in a "unit" of work */
  328. /*
  329. ** Variables related to the accumulation of tokens and doclists within the
  330. ** in-memory hash tables before they are flushed to disk.
  331. */
  332. Fts5Hash *pHash; /* Hash table for in-memory data */
  333. int nPendingData; /* Current bytes of pending data */
  334. i64 iWriteRowid; /* Rowid for current doc being written */
  335. int bDelete; /* Current write is a delete */
  336. int nContentlessDelete; /* Number of contentless delete ops */
  337. int nPendingRow; /* Number of INSERT in hash table */
  338. /* Error state. */
  339. int rc; /* Current error code */
  340. int flushRc;
  341. /* State used by the fts5DataXXX() functions. */
  342. sqlite3_blob *pReader; /* RO incr-blob open on %_data table */
  343. sqlite3_stmt *pWriter; /* "INSERT ... %_data VALUES(?,?)" */
  344. sqlite3_stmt *pDeleter; /* "DELETE FROM %_data ... id>=? AND id<=?" */
  345. sqlite3_stmt *pIdxWriter; /* "INSERT ... %_idx VALUES(?,?,?,?)" */
  346. sqlite3_stmt *pIdxDeleter; /* "DELETE FROM %_idx WHERE segid=?" */
  347. sqlite3_stmt *pIdxSelect;
  348. sqlite3_stmt *pIdxNextSelect;
  349. int nRead; /* Total number of blocks read */
  350. sqlite3_stmt *pDeleteFromIdx;
  351. sqlite3_stmt *pDataVersion;
  352. i64 iStructVersion; /* data_version when pStruct read */
  353. Fts5Structure *pStruct; /* Current db structure (or NULL) */
  354. };
  355. struct Fts5DoclistIter {
  356. u8 *aEof; /* Pointer to 1 byte past end of doclist */
  357. /* Output variables. aPoslist==0 at EOF */
  358. i64 iRowid;
  359. u8 *aPoslist;
  360. int nPoslist;
  361. int nSize;
  362. };
  363. /*
  364. ** The contents of the "structure" record for each index are represented
  365. ** using an Fts5Structure record in memory. Which uses instances of the
  366. ** other Fts5StructureXXX types as components.
  367. **
  368. ** nOriginCntr:
  369. ** This value is set to non-zero for structure records created for
  370. ** contentlessdelete=1 tables only. In that case it represents the
  371. ** origin value to apply to the next top-level segment created.
  372. */
  373. struct Fts5StructureSegment {
  374. int iSegid; /* Segment id */
  375. int pgnoFirst; /* First leaf page number in segment */
  376. int pgnoLast; /* Last leaf page number in segment */
  377. /* contentlessdelete=1 tables only: */
  378. u64 iOrigin1;
  379. u64 iOrigin2;
  380. int nPgTombstone; /* Number of tombstone hash table pages */
  381. u64 nEntryTombstone; /* Number of tombstone entries that "count" */
  382. u64 nEntry; /* Number of rows in this segment */
  383. };
  384. struct Fts5StructureLevel {
  385. int nMerge; /* Number of segments in incr-merge */
  386. int nSeg; /* Total number of segments on level */
  387. Fts5StructureSegment *aSeg; /* Array of segments. aSeg[0] is oldest. */
  388. };
  389. struct Fts5Structure {
  390. int nRef; /* Object reference count */
  391. u64 nWriteCounter; /* Total leaves written to level 0 */
  392. u64 nOriginCntr; /* Origin value for next top-level segment */
  393. int nSegment; /* Total segments in this structure */
  394. int nLevel; /* Number of levels in this index */
  395. Fts5StructureLevel aLevel[1]; /* Array of nLevel level objects */
  396. };
  397. /*
  398. ** An object of type Fts5SegWriter is used to write to segments.
  399. */
  400. struct Fts5PageWriter {
  401. int pgno; /* Page number for this page */
  402. int iPrevPgidx; /* Previous value written into pgidx */
  403. Fts5Buffer buf; /* Buffer containing leaf data */
  404. Fts5Buffer pgidx; /* Buffer containing page-index */
  405. Fts5Buffer term; /* Buffer containing previous term on page */
  406. };
  407. struct Fts5DlidxWriter {
  408. int pgno; /* Page number for this page */
  409. int bPrevValid; /* True if iPrev is valid */
  410. i64 iPrev; /* Previous rowid value written to page */
  411. Fts5Buffer buf; /* Buffer containing page data */
  412. };
  413. struct Fts5SegWriter {
  414. int iSegid; /* Segid to write to */
  415. Fts5PageWriter writer; /* PageWriter object */
  416. i64 iPrevRowid; /* Previous rowid written to current leaf */
  417. u8 bFirstRowidInDoclist; /* True if next rowid is first in doclist */
  418. u8 bFirstRowidInPage; /* True if next rowid is first in page */
  419. /* TODO1: Can use (writer.pgidx.n==0) instead of bFirstTermInPage */
  420. u8 bFirstTermInPage; /* True if next term will be first in leaf */
  421. int nLeafWritten; /* Number of leaf pages written */
  422. int nEmpty; /* Number of contiguous term-less nodes */
  423. int nDlidx; /* Allocated size of aDlidx[] array */
  424. Fts5DlidxWriter *aDlidx; /* Array of Fts5DlidxWriter objects */
  425. /* Values to insert into the %_idx table */
  426. Fts5Buffer btterm; /* Next term to insert into %_idx table */
  427. int iBtPage; /* Page number corresponding to btterm */
  428. };
  429. typedef struct Fts5CResult Fts5CResult;
  430. struct Fts5CResult {
  431. u16 iFirst; /* aSeg[] index of firstest iterator */
  432. u8 bTermEq; /* True if the terms are equal */
  433. };
  434. /*
  435. ** Object for iterating through a single segment, visiting each term/rowid
  436. ** pair in the segment.
  437. **
  438. ** pSeg:
  439. ** The segment to iterate through.
  440. **
  441. ** iLeafPgno:
  442. ** Current leaf page number within segment.
  443. **
  444. ** iLeafOffset:
  445. ** Byte offset within the current leaf that is the first byte of the
  446. ** position list data (one byte passed the position-list size field).
  447. **
  448. ** pLeaf:
  449. ** Buffer containing current leaf page data. Set to NULL at EOF.
  450. **
  451. ** iTermLeafPgno, iTermLeafOffset:
  452. ** Leaf page number containing the last term read from the segment. And
  453. ** the offset immediately following the term data.
  454. **
  455. ** flags:
  456. ** Mask of FTS5_SEGITER_XXX values. Interpreted as follows:
  457. **
  458. ** FTS5_SEGITER_ONETERM:
  459. ** If set, set the iterator to point to EOF after the current doclist
  460. ** has been exhausted. Do not proceed to the next term in the segment.
  461. **
  462. ** FTS5_SEGITER_REVERSE:
  463. ** This flag is only ever set if FTS5_SEGITER_ONETERM is also set. If
  464. ** it is set, iterate through rowid in descending order instead of the
  465. ** default ascending order.
  466. **
  467. ** iRowidOffset/nRowidOffset/aRowidOffset:
  468. ** These are used if the FTS5_SEGITER_REVERSE flag is set.
  469. **
  470. ** For each rowid on the page corresponding to the current term, the
  471. ** corresponding aRowidOffset[] entry is set to the byte offset of the
  472. ** start of the "position-list-size" field within the page.
  473. **
  474. ** iTermIdx:
  475. ** Index of current term on iTermLeafPgno.
  476. **
  477. ** apTombstone/nTombstone:
  478. ** These are used for contentless_delete=1 tables only. When the cursor
  479. ** is first allocated, the apTombstone[] array is allocated so that it
  480. ** is large enough for all tombstones hash pages associated with the
  481. ** segment. The pages themselves are loaded lazily from the database as
  482. ** they are required.
  483. */
  484. struct Fts5SegIter {
  485. Fts5StructureSegment *pSeg; /* Segment to iterate through */
  486. int flags; /* Mask of configuration flags */
  487. int iLeafPgno; /* Current leaf page number */
  488. Fts5Data *pLeaf; /* Current leaf data */
  489. Fts5Data *pNextLeaf; /* Leaf page (iLeafPgno+1) */
  490. i64 iLeafOffset; /* Byte offset within current leaf */
  491. Fts5TombstoneArray *pTombArray; /* Array of tombstone pages */
  492. /* Next method */
  493. void (*xNext)(Fts5Index*, Fts5SegIter*, int*);
  494. /* The page and offset from which the current term was read. The offset
  495. ** is the offset of the first rowid in the current doclist. */
  496. int iTermLeafPgno;
  497. int iTermLeafOffset;
  498. int iPgidxOff; /* Next offset in pgidx */
  499. int iEndofDoclist;
  500. /* The following are only used if the FTS5_SEGITER_REVERSE flag is set. */
  501. int iRowidOffset; /* Current entry in aRowidOffset[] */
  502. int nRowidOffset; /* Allocated size of aRowidOffset[] array */
  503. int *aRowidOffset; /* Array of offset to rowid fields */
  504. Fts5DlidxIter *pDlidx; /* If there is a doclist-index */
  505. /* Variables populated based on current entry. */
  506. Fts5Buffer term; /* Current term */
  507. i64 iRowid; /* Current rowid */
  508. int nPos; /* Number of bytes in current position list */
  509. u8 bDel; /* True if the delete flag is set */
  510. };
  511. /*
  512. ** Array of tombstone pages. Reference counted.
  513. */
  514. struct Fts5TombstoneArray {
  515. int nRef; /* Number of pointers to this object */
  516. int nTombstone;
  517. Fts5Data *apTombstone[1]; /* Array of tombstone pages */
  518. };
  519. /*
  520. ** Argument is a pointer to an Fts5Data structure that contains a
  521. ** leaf page.
  522. */
  523. #define ASSERT_SZLEAF_OK(x) assert( \
  524. (x)->szLeaf==(x)->nn || (x)->szLeaf==fts5GetU16(&(x)->p[2]) \
  525. )
  526. #define FTS5_SEGITER_ONETERM 0x01
  527. #define FTS5_SEGITER_REVERSE 0x02
  528. /*
  529. ** Argument is a pointer to an Fts5Data structure that contains a leaf
  530. ** page. This macro evaluates to true if the leaf contains no terms, or
  531. ** false if it contains at least one term.
  532. */
  533. #define fts5LeafIsTermless(x) ((x)->szLeaf >= (x)->nn)
  534. #define fts5LeafTermOff(x, i) (fts5GetU16(&(x)->p[(x)->szLeaf + (i)*2]))
  535. #define fts5LeafFirstRowidOff(x) (fts5GetU16((x)->p))
  536. /*
  537. ** Object for iterating through the merged results of one or more segments,
  538. ** visiting each term/rowid pair in the merged data.
  539. **
  540. ** nSeg is always a power of two greater than or equal to the number of
  541. ** segments that this object is merging data from. Both the aSeg[] and
  542. ** aFirst[] arrays are sized at nSeg entries. The aSeg[] array is padded
  543. ** with zeroed objects - these are handled as if they were iterators opened
  544. ** on empty segments.
  545. **
  546. ** The results of comparing segments aSeg[N] and aSeg[N+1], where N is an
  547. ** even number, is stored in aFirst[(nSeg+N)/2]. The "result" of the
  548. ** comparison in this context is the index of the iterator that currently
  549. ** points to the smaller term/rowid combination. Iterators at EOF are
  550. ** considered to be greater than all other iterators.
  551. **
  552. ** aFirst[1] contains the index in aSeg[] of the iterator that points to
  553. ** the smallest key overall. aFirst[0] is unused.
  554. **
  555. ** poslist:
  556. ** Used by sqlite3Fts5IterPoslist() when the poslist needs to be buffered.
  557. ** There is no way to tell if this is populated or not.
  558. **
  559. ** pColset:
  560. ** If not NULL, points to an object containing a set of column indices.
  561. ** Only matches that occur in one of these columns will be returned.
  562. ** The Fts5Iter does not own the Fts5Colset object, and so it is not
  563. ** freed when the iterator is closed - it is owned by the upper layer.
  564. */
  565. struct Fts5Iter {
  566. Fts5IndexIter base; /* Base class containing output vars */
  567. Fts5TokenDataIter *pTokenDataIter;
  568. Fts5Index *pIndex; /* Index that owns this iterator */
  569. Fts5Buffer poslist; /* Buffer containing current poslist */
  570. Fts5Colset *pColset; /* Restrict matches to these columns */
  571. /* Invoked to set output variables. */
  572. void (*xSetOutputs)(Fts5Iter*, Fts5SegIter*);
  573. int nSeg; /* Size of aSeg[] array */
  574. int bRev; /* True to iterate in reverse order */
  575. u8 bSkipEmpty; /* True to skip deleted entries */
  576. i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */
  577. Fts5CResult *aFirst; /* Current merge state (see above) */
  578. Fts5SegIter aSeg[1]; /* Array of segment iterators */
  579. };
  580. /*
  581. ** An instance of the following type is used to iterate through the contents
  582. ** of a doclist-index record.
  583. **
  584. ** pData:
  585. ** Record containing the doclist-index data.
  586. **
  587. ** bEof:
  588. ** Set to true once iterator has reached EOF.
  589. **
  590. ** iOff:
  591. ** Set to the current offset within record pData.
  592. */
  593. struct Fts5DlidxLvl {
  594. Fts5Data *pData; /* Data for current page of this level */
  595. int iOff; /* Current offset into pData */
  596. int bEof; /* At EOF already */
  597. int iFirstOff; /* Used by reverse iterators */
  598. /* Output variables */
  599. int iLeafPgno; /* Page number of current leaf page */
  600. i64 iRowid; /* First rowid on leaf iLeafPgno */
  601. };
  602. struct Fts5DlidxIter {
  603. int nLvl;
  604. int iSegid;
  605. Fts5DlidxLvl aLvl[1];
  606. };
  607. static void fts5PutU16(u8 *aOut, u16 iVal){
  608. aOut[0] = (iVal>>8);
  609. aOut[1] = (iVal&0xFF);
  610. }
  611. static u16 fts5GetU16(const u8 *aIn){
  612. return ((u16)aIn[0] << 8) + aIn[1];
  613. }
  614. /*
  615. ** The only argument points to a buffer at least 8 bytes in size. This
  616. ** function interprets the first 8 bytes of the buffer as a 64-bit big-endian
  617. ** unsigned integer and returns the result.
  618. */
  619. static u64 fts5GetU64(u8 *a){
  620. return ((u64)a[0] << 56)
  621. + ((u64)a[1] << 48)
  622. + ((u64)a[2] << 40)
  623. + ((u64)a[3] << 32)
  624. + ((u64)a[4] << 24)
  625. + ((u64)a[5] << 16)
  626. + ((u64)a[6] << 8)
  627. + ((u64)a[7] << 0);
  628. }
  629. /*
  630. ** The only argument points to a buffer at least 4 bytes in size. This
  631. ** function interprets the first 4 bytes of the buffer as a 32-bit big-endian
  632. ** unsigned integer and returns the result.
  633. */
  634. static u32 fts5GetU32(const u8 *a){
  635. return ((u32)a[0] << 24)
  636. + ((u32)a[1] << 16)
  637. + ((u32)a[2] << 8)
  638. + ((u32)a[3] << 0);
  639. }
  640. /*
  641. ** Write iVal, formated as a 64-bit big-endian unsigned integer, to the
  642. ** buffer indicated by the first argument.
  643. */
  644. static void fts5PutU64(u8 *a, u64 iVal){
  645. a[0] = ((iVal >> 56) & 0xFF);
  646. a[1] = ((iVal >> 48) & 0xFF);
  647. a[2] = ((iVal >> 40) & 0xFF);
  648. a[3] = ((iVal >> 32) & 0xFF);
  649. a[4] = ((iVal >> 24) & 0xFF);
  650. a[5] = ((iVal >> 16) & 0xFF);
  651. a[6] = ((iVal >> 8) & 0xFF);
  652. a[7] = ((iVal >> 0) & 0xFF);
  653. }
  654. /*
  655. ** Write iVal, formated as a 32-bit big-endian unsigned integer, to the
  656. ** buffer indicated by the first argument.
  657. */
  658. static void fts5PutU32(u8 *a, u32 iVal){
  659. a[0] = ((iVal >> 24) & 0xFF);
  660. a[1] = ((iVal >> 16) & 0xFF);
  661. a[2] = ((iVal >> 8) & 0xFF);
  662. a[3] = ((iVal >> 0) & 0xFF);
  663. }
  664. /*
  665. ** Allocate and return a buffer at least nByte bytes in size.
  666. **
  667. ** If an OOM error is encountered, return NULL and set the error code in
  668. ** the Fts5Index handle passed as the first argument.
  669. */
  670. static void *fts5IdxMalloc(Fts5Index *p, sqlite3_int64 nByte){
  671. return sqlite3Fts5MallocZero(&p->rc, nByte);
  672. }
  673. /*
  674. ** Compare the contents of the pLeft buffer with the pRight/nRight blob.
  675. **
  676. ** Return -ve if pLeft is smaller than pRight, 0 if they are equal or
  677. ** +ve if pRight is smaller than pLeft. In other words:
  678. **
  679. ** res = *pLeft - *pRight
  680. */
  681. #ifdef SQLITE_DEBUG
  682. static int fts5BufferCompareBlob(
  683. Fts5Buffer *pLeft, /* Left hand side of comparison */
  684. const u8 *pRight, int nRight /* Right hand side of comparison */
  685. ){
  686. int nCmp = MIN(pLeft->n, nRight);
  687. int res = memcmp(pLeft->p, pRight, nCmp);
  688. return (res==0 ? (pLeft->n - nRight) : res);
  689. }
  690. #endif
  691. /*
  692. ** Compare the contents of the two buffers using memcmp(). If one buffer
  693. ** is a prefix of the other, it is considered the lesser.
  694. **
  695. ** Return -ve if pLeft is smaller than pRight, 0 if they are equal or
  696. ** +ve if pRight is smaller than pLeft. In other words:
  697. **
  698. ** res = *pLeft - *pRight
  699. */
  700. static int fts5BufferCompare(Fts5Buffer *pLeft, Fts5Buffer *pRight){
  701. int nCmp, res;
  702. nCmp = MIN(pLeft->n, pRight->n);
  703. assert( nCmp<=0 || pLeft->p!=0 );
  704. assert( nCmp<=0 || pRight->p!=0 );
  705. res = fts5Memcmp(pLeft->p, pRight->p, nCmp);
  706. return (res==0 ? (pLeft->n - pRight->n) : res);
  707. }
  708. static int fts5LeafFirstTermOff(Fts5Data *pLeaf){
  709. int ret;
  710. fts5GetVarint32(&pLeaf->p[pLeaf->szLeaf], ret);
  711. return ret;
  712. }
  713. /*
  714. ** Close the read-only blob handle, if it is open.
  715. */
  716. void sqlite3Fts5IndexCloseReader(Fts5Index *p){
  717. if( p->pReader ){
  718. sqlite3_blob *pReader = p->pReader;
  719. p->pReader = 0;
  720. sqlite3_blob_close(pReader);
  721. }
  722. }
  723. /*
  724. ** Retrieve a record from the %_data table.
  725. **
  726. ** If an error occurs, NULL is returned and an error left in the
  727. ** Fts5Index object.
  728. */
  729. static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
  730. Fts5Data *pRet = 0;
  731. if( p->rc==SQLITE_OK ){
  732. int rc = SQLITE_OK;
  733. if( p->pReader ){
  734. /* This call may return SQLITE_ABORT if there has been a savepoint
  735. ** rollback since it was last used. In this case a new blob handle
  736. ** is required. */
  737. sqlite3_blob *pBlob = p->pReader;
  738. p->pReader = 0;
  739. rc = sqlite3_blob_reopen(pBlob, iRowid);
  740. assert( p->pReader==0 );
  741. p->pReader = pBlob;
  742. if( rc!=SQLITE_OK ){
  743. sqlite3Fts5IndexCloseReader(p);
  744. }
  745. if( rc==SQLITE_ABORT ) rc = SQLITE_OK;
  746. }
  747. /* If the blob handle is not open at this point, open it and seek
  748. ** to the requested entry. */
  749. if( p->pReader==0 && rc==SQLITE_OK ){
  750. Fts5Config *pConfig = p->pConfig;
  751. rc = sqlite3_blob_open(pConfig->db,
  752. pConfig->zDb, p->zDataTbl, "block", iRowid, 0, &p->pReader
  753. );
  754. }
  755. /* If either of the sqlite3_blob_open() or sqlite3_blob_reopen() calls
  756. ** above returned SQLITE_ERROR, return SQLITE_CORRUPT_VTAB instead.
  757. ** All the reasons those functions might return SQLITE_ERROR - missing
  758. ** table, missing row, non-blob/text in block column - indicate
  759. ** backing store corruption. */
  760. if( rc==SQLITE_ERROR ) rc = FTS5_CORRUPT;
  761. if( rc==SQLITE_OK ){
  762. u8 *aOut = 0; /* Read blob data into this buffer */
  763. int nByte = sqlite3_blob_bytes(p->pReader);
  764. int szData = (sizeof(Fts5Data) + 7) & ~7;
  765. sqlite3_int64 nAlloc = szData + nByte + FTS5_DATA_PADDING;
  766. pRet = (Fts5Data*)sqlite3_malloc64(nAlloc);
  767. if( pRet ){
  768. pRet->nn = nByte;
  769. aOut = pRet->p = (u8*)pRet + szData;
  770. }else{
  771. rc = SQLITE_NOMEM;
  772. }
  773. if( rc==SQLITE_OK ){
  774. rc = sqlite3_blob_read(p->pReader, aOut, nByte, 0);
  775. }
  776. if( rc!=SQLITE_OK ){
  777. sqlite3_free(pRet);
  778. pRet = 0;
  779. }else{
  780. /* TODO1: Fix this */
  781. pRet->p[nByte] = 0x00;
  782. pRet->p[nByte+1] = 0x00;
  783. pRet->szLeaf = fts5GetU16(&pRet->p[2]);
  784. }
  785. }
  786. p->rc = rc;
  787. p->nRead++;
  788. }
  789. assert( (pRet==0)==(p->rc!=SQLITE_OK) );
  790. assert( pRet==0 || EIGHT_BYTE_ALIGNMENT( pRet->p ) );
  791. return pRet;
  792. }
  793. /*
  794. ** Release a reference to data record returned by an earlier call to
  795. ** fts5DataRead().
  796. */
  797. static void fts5DataRelease(Fts5Data *pData){
  798. sqlite3_free(pData);
  799. }
  800. static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){
  801. Fts5Data *pRet = fts5DataRead(p, iRowid);
  802. if( pRet ){
  803. if( pRet->nn<4 || pRet->szLeaf>pRet->nn ){
  804. p->rc = FTS5_CORRUPT;
  805. fts5DataRelease(pRet);
  806. pRet = 0;
  807. }
  808. }
  809. return pRet;
  810. }
  811. static int fts5IndexPrepareStmt(
  812. Fts5Index *p,
  813. sqlite3_stmt **ppStmt,
  814. char *zSql
  815. ){
  816. if( p->rc==SQLITE_OK ){
  817. if( zSql ){
  818. p->rc = sqlite3_prepare_v3(p->pConfig->db, zSql, -1,
  819. SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB,
  820. ppStmt, 0);
  821. }else{
  822. p->rc = SQLITE_NOMEM;
  823. }
  824. }
  825. sqlite3_free(zSql);
  826. return p->rc;
  827. }
  828. /*
  829. ** INSERT OR REPLACE a record into the %_data table.
  830. */
  831. static void fts5DataWrite(Fts5Index *p, i64 iRowid, const u8 *pData, int nData){
  832. if( p->rc!=SQLITE_OK ) return;
  833. if( p->pWriter==0 ){
  834. Fts5Config *pConfig = p->pConfig;
  835. fts5IndexPrepareStmt(p, &p->pWriter, sqlite3_mprintf(
  836. "REPLACE INTO '%q'.'%q_data'(id, block) VALUES(?,?)",
  837. pConfig->zDb, pConfig->zName
  838. ));
  839. if( p->rc ) return;
  840. }
  841. sqlite3_bind_int64(p->pWriter, 1, iRowid);
  842. sqlite3_bind_blob(p->pWriter, 2, pData, nData, SQLITE_STATIC);
  843. sqlite3_step(p->pWriter);
  844. p->rc = sqlite3_reset(p->pWriter);
  845. sqlite3_bind_null(p->pWriter, 2);
  846. }
  847. /*
  848. ** Execute the following SQL:
  849. **
  850. ** DELETE FROM %_data WHERE id BETWEEN $iFirst AND $iLast
  851. */
  852. static void fts5DataDelete(Fts5Index *p, i64 iFirst, i64 iLast){
  853. if( p->rc!=SQLITE_OK ) return;
  854. if( p->pDeleter==0 ){
  855. Fts5Config *pConfig = p->pConfig;
  856. char *zSql = sqlite3_mprintf(
  857. "DELETE FROM '%q'.'%q_data' WHERE id>=? AND id<=?",
  858. pConfig->zDb, pConfig->zName
  859. );
  860. if( fts5IndexPrepareStmt(p, &p->pDeleter, zSql) ) return;
  861. }
  862. sqlite3_bind_int64(p->pDeleter, 1, iFirst);
  863. sqlite3_bind_int64(p->pDeleter, 2, iLast);
  864. sqlite3_step(p->pDeleter);
  865. p->rc = sqlite3_reset(p->pDeleter);
  866. }
  867. /*
  868. ** Remove all records associated with segment iSegid.
  869. */
  870. static void fts5DataRemoveSegment(Fts5Index *p, Fts5StructureSegment *pSeg){
  871. int iSegid = pSeg->iSegid;
  872. i64 iFirst = FTS5_SEGMENT_ROWID(iSegid, 0);
  873. i64 iLast = FTS5_SEGMENT_ROWID(iSegid+1, 0)-1;
  874. fts5DataDelete(p, iFirst, iLast);
  875. if( pSeg->nPgTombstone ){
  876. i64 iTomb1 = FTS5_TOMBSTONE_ROWID(iSegid, 0);
  877. i64 iTomb2 = FTS5_TOMBSTONE_ROWID(iSegid, pSeg->nPgTombstone-1);
  878. fts5DataDelete(p, iTomb1, iTomb2);
  879. }
  880. if( p->pIdxDeleter==0 ){
  881. Fts5Config *pConfig = p->pConfig;
  882. fts5IndexPrepareStmt(p, &p->pIdxDeleter, sqlite3_mprintf(
  883. "DELETE FROM '%q'.'%q_idx' WHERE segid=?",
  884. pConfig->zDb, pConfig->zName
  885. ));
  886. }
  887. if( p->rc==SQLITE_OK ){
  888. sqlite3_bind_int(p->pIdxDeleter, 1, iSegid);
  889. sqlite3_step(p->pIdxDeleter);
  890. p->rc = sqlite3_reset(p->pIdxDeleter);
  891. }
  892. }
  893. /*
  894. ** Release a reference to an Fts5Structure object returned by an earlier
  895. ** call to fts5StructureRead() or fts5StructureDecode().
  896. */
  897. static void fts5StructureRelease(Fts5Structure *pStruct){
  898. if( pStruct && 0>=(--pStruct->nRef) ){
  899. int i;
  900. assert( pStruct->nRef==0 );
  901. for(i=0; i<pStruct->nLevel; i++){
  902. sqlite3_free(pStruct->aLevel[i].aSeg);
  903. }
  904. sqlite3_free(pStruct);
  905. }
  906. }
  907. static void fts5StructureRef(Fts5Structure *pStruct){
  908. pStruct->nRef++;
  909. }
  910. void *sqlite3Fts5StructureRef(Fts5Index *p){
  911. fts5StructureRef(p->pStruct);
  912. return (void*)p->pStruct;
  913. }
  914. void sqlite3Fts5StructureRelease(void *p){
  915. if( p ){
  916. fts5StructureRelease((Fts5Structure*)p);
  917. }
  918. }
  919. int sqlite3Fts5StructureTest(Fts5Index *p, void *pStruct){
  920. if( p->pStruct!=(Fts5Structure*)pStruct ){
  921. return SQLITE_ABORT;
  922. }
  923. return SQLITE_OK;
  924. }
  925. /*
  926. ** Ensure that structure object (*pp) is writable.
  927. **
  928. ** This function is a no-op if (*pRc) is not SQLITE_OK when it is called. If
  929. ** an error occurs, (*pRc) is set to an SQLite error code before returning.
  930. */
  931. static void fts5StructureMakeWritable(int *pRc, Fts5Structure **pp){
  932. Fts5Structure *p = *pp;
  933. if( *pRc==SQLITE_OK && p->nRef>1 ){
  934. i64 nByte = sizeof(Fts5Structure)+(p->nLevel-1)*sizeof(Fts5StructureLevel);
  935. Fts5Structure *pNew;
  936. pNew = (Fts5Structure*)sqlite3Fts5MallocZero(pRc, nByte);
  937. if( pNew ){
  938. int i;
  939. memcpy(pNew, p, nByte);
  940. for(i=0; i<p->nLevel; i++) pNew->aLevel[i].aSeg = 0;
  941. for(i=0; i<p->nLevel; i++){
  942. Fts5StructureLevel *pLvl = &pNew->aLevel[i];
  943. nByte = sizeof(Fts5StructureSegment) * pNew->aLevel[i].nSeg;
  944. pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(pRc, nByte);
  945. if( pLvl->aSeg==0 ){
  946. for(i=0; i<p->nLevel; i++){
  947. sqlite3_free(pNew->aLevel[i].aSeg);
  948. }
  949. sqlite3_free(pNew);
  950. return;
  951. }
  952. memcpy(pLvl->aSeg, p->aLevel[i].aSeg, nByte);
  953. }
  954. p->nRef--;
  955. pNew->nRef = 1;
  956. }
  957. *pp = pNew;
  958. }
  959. }
  960. /*
  961. ** Deserialize and return the structure record currently stored in serialized
  962. ** form within buffer pData/nData.
  963. **
  964. ** The Fts5Structure.aLevel[] and each Fts5StructureLevel.aSeg[] array
  965. ** are over-allocated by one slot. This allows the structure contents
  966. ** to be more easily edited.
  967. **
  968. ** If an error occurs, *ppOut is set to NULL and an SQLite error code
  969. ** returned. Otherwise, *ppOut is set to point to the new object and
  970. ** SQLITE_OK returned.
  971. */
  972. static int fts5StructureDecode(
  973. const u8 *pData, /* Buffer containing serialized structure */
  974. int nData, /* Size of buffer pData in bytes */
  975. int *piCookie, /* Configuration cookie value */
  976. Fts5Structure **ppOut /* OUT: Deserialized object */
  977. ){
  978. int rc = SQLITE_OK;
  979. int i = 0;
  980. int iLvl;
  981. int nLevel = 0;
  982. int nSegment = 0;
  983. sqlite3_int64 nByte; /* Bytes of space to allocate at pRet */
  984. Fts5Structure *pRet = 0; /* Structure object to return */
  985. int bStructureV2 = 0; /* True for FTS5_STRUCTURE_V2 */
  986. u64 nOriginCntr = 0; /* Largest origin value seen so far */
  987. /* Grab the cookie value */
  988. if( piCookie ) *piCookie = sqlite3Fts5Get32(pData);
  989. i = 4;
  990. /* Check if this is a V2 structure record. Set bStructureV2 if it is. */
  991. if( 0==memcmp(&pData[i], FTS5_STRUCTURE_V2, 4) ){
  992. i += 4;
  993. bStructureV2 = 1;
  994. }
  995. /* Read the total number of levels and segments from the start of the
  996. ** structure record. */
  997. i += fts5GetVarint32(&pData[i], nLevel);
  998. i += fts5GetVarint32(&pData[i], nSegment);
  999. if( nLevel>FTS5_MAX_SEGMENT || nLevel<0
  1000. || nSegment>FTS5_MAX_SEGMENT || nSegment<0
  1001. ){
  1002. return FTS5_CORRUPT;
  1003. }
  1004. nByte = (
  1005. sizeof(Fts5Structure) + /* Main structure */
  1006. sizeof(Fts5StructureLevel) * (nLevel-1) /* aLevel[] array */
  1007. );
  1008. pRet = (Fts5Structure*)sqlite3Fts5MallocZero(&rc, nByte);
  1009. if( pRet ){
  1010. pRet->nRef = 1;
  1011. pRet->nLevel = nLevel;
  1012. pRet->nSegment = nSegment;
  1013. i += sqlite3Fts5GetVarint(&pData[i], &pRet->nWriteCounter);
  1014. for(iLvl=0; rc==SQLITE_OK && iLvl<nLevel; iLvl++){
  1015. Fts5StructureLevel *pLvl = &pRet->aLevel[iLvl];
  1016. int nTotal = 0;
  1017. int iSeg;
  1018. if( i>=nData ){
  1019. rc = FTS5_CORRUPT;
  1020. }else{
  1021. i += fts5GetVarint32(&pData[i], pLvl->nMerge);
  1022. i += fts5GetVarint32(&pData[i], nTotal);
  1023. if( nTotal<pLvl->nMerge ) rc = FTS5_CORRUPT;
  1024. pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&rc,
  1025. nTotal * sizeof(Fts5StructureSegment)
  1026. );
  1027. nSegment -= nTotal;
  1028. }
  1029. if( rc==SQLITE_OK ){
  1030. pLvl->nSeg = nTotal;
  1031. for(iSeg=0; iSeg<nTotal; iSeg++){
  1032. Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg];
  1033. if( i>=nData ){
  1034. rc = FTS5_CORRUPT;
  1035. break;
  1036. }
  1037. assert( pSeg!=0 );
  1038. i += fts5GetVarint32(&pData[i], pSeg->iSegid);
  1039. i += fts5GetVarint32(&pData[i], pSeg->pgnoFirst);
  1040. i += fts5GetVarint32(&pData[i], pSeg->pgnoLast);
  1041. if( bStructureV2 ){
  1042. i += fts5GetVarint(&pData[i], &pSeg->iOrigin1);
  1043. i += fts5GetVarint(&pData[i], &pSeg->iOrigin2);
  1044. i += fts5GetVarint32(&pData[i], pSeg->nPgTombstone);
  1045. i += fts5GetVarint(&pData[i], &pSeg->nEntryTombstone);
  1046. i += fts5GetVarint(&pData[i], &pSeg->nEntry);
  1047. nOriginCntr = MAX(nOriginCntr, pSeg->iOrigin2);
  1048. }
  1049. if( pSeg->pgnoLast<pSeg->pgnoFirst ){
  1050. rc = FTS5_CORRUPT;
  1051. break;
  1052. }
  1053. }
  1054. if( iLvl>0 && pLvl[-1].nMerge && nTotal==0 ) rc = FTS5_CORRUPT;
  1055. if( iLvl==nLevel-1 && pLvl->nMerge ) rc = FTS5_CORRUPT;
  1056. }
  1057. }
  1058. if( nSegment!=0 && rc==SQLITE_OK ) rc = FTS5_CORRUPT;
  1059. if( bStructureV2 ){
  1060. pRet->nOriginCntr = nOriginCntr+1;
  1061. }
  1062. if( rc!=SQLITE_OK ){
  1063. fts5StructureRelease(pRet);
  1064. pRet = 0;
  1065. }
  1066. }
  1067. *ppOut = pRet;
  1068. return rc;
  1069. }
  1070. /*
  1071. ** Add a level to the Fts5Structure.aLevel[] array of structure object
  1072. ** (*ppStruct).
  1073. */
  1074. static void fts5StructureAddLevel(int *pRc, Fts5Structure **ppStruct){
  1075. fts5StructureMakeWritable(pRc, ppStruct);
  1076. assert( (ppStruct!=0 && (*ppStruct)!=0) || (*pRc)!=SQLITE_OK );
  1077. if( *pRc==SQLITE_OK ){
  1078. Fts5Structure *pStruct = *ppStruct;
  1079. int nLevel = pStruct->nLevel;
  1080. sqlite3_int64 nByte = (
  1081. sizeof(Fts5Structure) + /* Main structure */
  1082. sizeof(Fts5StructureLevel) * (nLevel+1) /* aLevel[] array */
  1083. );
  1084. pStruct = sqlite3_realloc64(pStruct, nByte);
  1085. if( pStruct ){
  1086. memset(&pStruct->aLevel[nLevel], 0, sizeof(Fts5StructureLevel));
  1087. pStruct->nLevel++;
  1088. *ppStruct = pStruct;
  1089. }else{
  1090. *pRc = SQLITE_NOMEM;
  1091. }
  1092. }
  1093. }
  1094. /*
  1095. ** Extend level iLvl so that there is room for at least nExtra more
  1096. ** segments.
  1097. */
  1098. static void fts5StructureExtendLevel(
  1099. int *pRc,
  1100. Fts5Structure *pStruct,
  1101. int iLvl,
  1102. int nExtra,
  1103. int bInsert
  1104. ){
  1105. if( *pRc==SQLITE_OK ){
  1106. Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl];
  1107. Fts5StructureSegment *aNew;
  1108. sqlite3_int64 nByte;
  1109. nByte = (pLvl->nSeg + nExtra) * sizeof(Fts5StructureSegment);
  1110. aNew = sqlite3_realloc64(pLvl->aSeg, nByte);
  1111. if( aNew ){
  1112. if( bInsert==0 ){
  1113. memset(&aNew[pLvl->nSeg], 0, sizeof(Fts5StructureSegment) * nExtra);
  1114. }else{
  1115. int nMove = pLvl->nSeg * sizeof(Fts5StructureSegment);
  1116. memmove(&aNew[nExtra], aNew, nMove);
  1117. memset(aNew, 0, sizeof(Fts5StructureSegment) * nExtra);
  1118. }
  1119. pLvl->aSeg = aNew;
  1120. }else{
  1121. *pRc = SQLITE_NOMEM;
  1122. }
  1123. }
  1124. }
  1125. static Fts5Structure *fts5StructureReadUncached(Fts5Index *p){
  1126. Fts5Structure *pRet = 0;
  1127. Fts5Config *pConfig = p->pConfig;
  1128. int iCookie; /* Configuration cookie */
  1129. Fts5Data *pData;
  1130. pData = fts5DataRead(p, FTS5_STRUCTURE_ROWID);
  1131. if( p->rc==SQLITE_OK ){
  1132. /* TODO: Do we need this if the leaf-index is appended? Probably... */
  1133. memset(&pData->p[pData->nn], 0, FTS5_DATA_PADDING);
  1134. p->rc = fts5StructureDecode(pData->p, pData->nn, &iCookie, &pRet);
  1135. if( p->rc==SQLITE_OK && (pConfig->pgsz==0 || pConfig->iCookie!=iCookie) ){
  1136. p->rc = sqlite3Fts5ConfigLoad(pConfig, iCookie);
  1137. }
  1138. fts5DataRelease(pData);
  1139. if( p->rc!=SQLITE_OK ){
  1140. fts5StructureRelease(pRet);
  1141. pRet = 0;
  1142. }
  1143. }
  1144. return pRet;
  1145. }
  1146. static i64 fts5IndexDataVersion(Fts5Index *p){
  1147. i64 iVersion = 0;
  1148. if( p->rc==SQLITE_OK ){
  1149. if( p->pDataVersion==0 ){
  1150. p->rc = fts5IndexPrepareStmt(p, &p->pDataVersion,
  1151. sqlite3_mprintf("PRAGMA %Q.data_version", p->pConfig->zDb)
  1152. );
  1153. if( p->rc ) return 0;
  1154. }
  1155. if( SQLITE_ROW==sqlite3_step(p->pDataVersion) ){
  1156. iVersion = sqlite3_column_int64(p->pDataVersion, 0);
  1157. }
  1158. p->rc = sqlite3_reset(p->pDataVersion);
  1159. }
  1160. return iVersion;
  1161. }
  1162. /*
  1163. ** Read, deserialize and return the structure record.
  1164. **
  1165. ** The Fts5Structure.aLevel[] and each Fts5StructureLevel.aSeg[] array
  1166. ** are over-allocated as described for function fts5StructureDecode()
  1167. ** above.
  1168. **
  1169. ** If an error occurs, NULL is returned and an error code left in the
  1170. ** Fts5Index handle. If an error has already occurred when this function
  1171. ** is called, it is a no-op.
  1172. */
  1173. static Fts5Structure *fts5StructureRead(Fts5Index *p){
  1174. if( p->pStruct==0 ){
  1175. p->iStructVersion = fts5IndexDataVersion(p);
  1176. if( p->rc==SQLITE_OK ){
  1177. p->pStruct = fts5StructureReadUncached(p);
  1178. }
  1179. }
  1180. #if 0
  1181. else{
  1182. Fts5Structure *pTest = fts5StructureReadUncached(p);
  1183. if( pTest ){
  1184. int i, j;
  1185. assert_nc( p->pStruct->nSegment==pTest->nSegment );
  1186. assert_nc( p->pStruct->nLevel==pTest->nLevel );
  1187. for(i=0; i<pTest->nLevel; i++){
  1188. assert_nc( p->pStruct->aLevel[i].nMerge==pTest->aLevel[i].nMerge );
  1189. assert_nc( p->pStruct->aLevel[i].nSeg==pTest->aLevel[i].nSeg );
  1190. for(j=0; j<pTest->aLevel[i].nSeg; j++){
  1191. Fts5StructureSegment *p1 = &pTest->aLevel[i].aSeg[j];
  1192. Fts5StructureSegment *p2 = &p->pStruct->aLevel[i].aSeg[j];
  1193. assert_nc( p1->iSegid==p2->iSegid );
  1194. assert_nc( p1->pgnoFirst==p2->pgnoFirst );
  1195. assert_nc( p1->pgnoLast==p2->pgnoLast );
  1196. }
  1197. }
  1198. fts5StructureRelease(pTest);
  1199. }
  1200. }
  1201. #endif
  1202. if( p->rc!=SQLITE_OK ) return 0;
  1203. assert( p->iStructVersion!=0 );
  1204. assert( p->pStruct!=0 );
  1205. fts5StructureRef(p->pStruct);
  1206. return p->pStruct;
  1207. }
  1208. static void fts5StructureInvalidate(Fts5Index *p){
  1209. if( p->pStruct ){
  1210. fts5StructureRelease(p->pStruct);
  1211. p->pStruct = 0;
  1212. }
  1213. }
  1214. /*
  1215. ** Return the total number of segments in index structure pStruct. This
  1216. ** function is only ever used as part of assert() conditions.
  1217. */
  1218. #ifdef SQLITE_DEBUG
  1219. static int fts5StructureCountSegments(Fts5Structure *pStruct){
  1220. int nSegment = 0; /* Total number of segments */
  1221. if( pStruct ){
  1222. int iLvl; /* Used to iterate through levels */
  1223. for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
  1224. nSegment += pStruct->aLevel[iLvl].nSeg;
  1225. }
  1226. }
  1227. return nSegment;
  1228. }
  1229. #endif
  1230. #define fts5BufferSafeAppendBlob(pBuf, pBlob, nBlob) { \
  1231. assert( (pBuf)->nSpace>=((pBuf)->n+nBlob) ); \
  1232. memcpy(&(pBuf)->p[(pBuf)->n], pBlob, nBlob); \
  1233. (pBuf)->n += nBlob; \
  1234. }
  1235. #define fts5BufferSafeAppendVarint(pBuf, iVal) { \
  1236. (pBuf)->n += sqlite3Fts5PutVarint(&(pBuf)->p[(pBuf)->n], (iVal)); \
  1237. assert( (pBuf)->nSpace>=(pBuf)->n ); \
  1238. }
  1239. /*
  1240. ** Serialize and store the "structure" record.
  1241. **
  1242. ** If an error occurs, leave an error code in the Fts5Index object. If an
  1243. ** error has already occurred, this function is a no-op.
  1244. */
  1245. static void fts5StructureWrite(Fts5Index *p, Fts5Structure *pStruct){
  1246. if( p->rc==SQLITE_OK ){
  1247. Fts5Buffer buf; /* Buffer to serialize record into */
  1248. int iLvl; /* Used to iterate through levels */
  1249. int iCookie; /* Cookie value to store */
  1250. int nHdr = (pStruct->nOriginCntr>0 ? (4+4+9+9+9) : (4+9+9));
  1251. assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) );
  1252. memset(&buf, 0, sizeof(Fts5Buffer));
  1253. /* Append the current configuration cookie */
  1254. iCookie = p->pConfig->iCookie;
  1255. if( iCookie<0 ) iCookie = 0;
  1256. if( 0==sqlite3Fts5BufferSize(&p->rc, &buf, nHdr) ){
  1257. sqlite3Fts5Put32(buf.p, iCookie);
  1258. buf.n = 4;
  1259. if( pStruct->nOriginCntr>0 ){
  1260. fts5BufferSafeAppendBlob(&buf, FTS5_STRUCTURE_V2, 4);
  1261. }
  1262. fts5BufferSafeAppendVarint(&buf, pStruct->nLevel);
  1263. fts5BufferSafeAppendVarint(&buf, pStruct->nSegment);
  1264. fts5BufferSafeAppendVarint(&buf, (i64)pStruct->nWriteCounter);
  1265. }
  1266. for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
  1267. int iSeg; /* Used to iterate through segments */
  1268. Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl];
  1269. fts5BufferAppendVarint(&p->rc, &buf, pLvl->nMerge);
  1270. fts5BufferAppendVarint(&p->rc, &buf, pLvl->nSeg);
  1271. assert( pLvl->nMerge<=pLvl->nSeg );
  1272. for(iSeg=0; iSeg<pLvl->nSeg; iSeg++){
  1273. Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg];
  1274. fts5BufferAppendVarint(&p->rc, &buf, pSeg->iSegid);
  1275. fts5BufferAppendVarint(&p->rc, &buf, pSeg->pgnoFirst);
  1276. fts5BufferAppendVarint(&p->rc, &buf, pSeg->pgnoLast);
  1277. if( pStruct->nOriginCntr>0 ){
  1278. fts5BufferAppendVarint(&p->rc, &buf, pSeg->iOrigin1);
  1279. fts5BufferAppendVarint(&p->rc, &buf, pSeg->iOrigin2);
  1280. fts5BufferAppendVarint(&p->rc, &buf, pSeg->nPgTombstone);
  1281. fts5BufferAppendVarint(&p->rc, &buf, pSeg->nEntryTombstone);
  1282. fts5BufferAppendVarint(&p->rc, &buf, pSeg->nEntry);
  1283. }
  1284. }
  1285. }
  1286. fts5DataWrite(p, FTS5_STRUCTURE_ROWID, buf.p, buf.n);
  1287. fts5BufferFree(&buf);
  1288. }
  1289. }
  1290. #if 0
  1291. static void fts5DebugStructure(int*,Fts5Buffer*,Fts5Structure*);
  1292. static void fts5PrintStructure(const char *zCaption, Fts5Structure *pStruct){
  1293. int rc = SQLITE_OK;
  1294. Fts5Buffer buf;
  1295. memset(&buf, 0, sizeof(buf));
  1296. fts5DebugStructure(&rc, &buf, pStruct);
  1297. fprintf(stdout, "%s: %s\n", zCaption, buf.p);
  1298. fflush(stdout);
  1299. fts5BufferFree(&buf);
  1300. }
  1301. #else
  1302. # define fts5PrintStructure(x,y)
  1303. #endif
  1304. static int fts5SegmentSize(Fts5StructureSegment *pSeg){
  1305. return 1 + pSeg->pgnoLast - pSeg->pgnoFirst;
  1306. }
  1307. /*
  1308. ** Return a copy of index structure pStruct. Except, promote as many
  1309. ** segments as possible to level iPromote. If an OOM occurs, NULL is
  1310. ** returned.
  1311. */
  1312. static void fts5StructurePromoteTo(
  1313. Fts5Index *p,
  1314. int iPromote,
  1315. int szPromote,
  1316. Fts5Structure *pStruct
  1317. ){
  1318. int il, is;
  1319. Fts5StructureLevel *pOut = &pStruct->aLevel[iPromote];
  1320. if( pOut->nMerge==0 ){
  1321. for(il=iPromote+1; il<pStruct->nLevel; il++){
  1322. Fts5StructureLevel *pLvl = &pStruct->aLevel[il];
  1323. if( pLvl->nMerge ) return;
  1324. for(is=pLvl->nSeg-1; is>=0; is--){
  1325. int sz = fts5SegmentSize(&pLvl->aSeg[is]);
  1326. if( sz>szPromote ) return;
  1327. fts5StructureExtendLevel(&p->rc, pStruct, iPromote, 1, 1);
  1328. if( p->rc ) return;
  1329. memcpy(pOut->aSeg, &pLvl->aSeg[is], sizeof(Fts5StructureSegment));
  1330. pOut->nSeg++;
  1331. pLvl->nSeg--;
  1332. }
  1333. }
  1334. }
  1335. }
  1336. /*
  1337. ** A new segment has just been written to level iLvl of index structure
  1338. ** pStruct. This function determines if any segments should be promoted
  1339. ** as a result. Segments are promoted in two scenarios:
  1340. **
  1341. ** a) If the segment just written is smaller than one or more segments
  1342. ** within the previous populated level, it is promoted to the previous
  1343. ** populated level.
  1344. **
  1345. ** b) If the segment just written is larger than the newest segment on
  1346. ** the next populated level, then that segment, and any other adjacent
  1347. ** segments that are also smaller than the one just written, are
  1348. ** promoted.
  1349. **
  1350. ** If one or more segments are promoted, the structure object is updated
  1351. ** to reflect this.
  1352. */
  1353. static void fts5StructurePromote(
  1354. Fts5Index *p, /* FTS5 backend object */
  1355. int iLvl, /* Index level just updated */
  1356. Fts5Structure *pStruct /* Index structure */
  1357. ){
  1358. if( p->rc==SQLITE_OK ){
  1359. int iTst;
  1360. int iPromote = -1;
  1361. int szPromote = 0; /* Promote anything this size or smaller */
  1362. Fts5StructureSegment *pSeg; /* Segment just written */
  1363. int szSeg; /* Size of segment just written */
  1364. int nSeg = pStruct->aLevel[iLvl].nSeg;
  1365. if( nSeg==0 ) return;
  1366. pSeg = &pStruct->aLevel[iLvl].aSeg[pStruct->aLevel[iLvl].nSeg-1];
  1367. szSeg = (1 + pSeg->pgnoLast - pSeg->pgnoFirst);
  1368. /* Check for condition (a) */
  1369. for(iTst=iLvl-1; iTst>=0 && pStruct->aLevel[iTst].nSeg==0; iTst--);
  1370. if( iTst>=0 ){
  1371. int i;
  1372. int szMax = 0;
  1373. Fts5StructureLevel *pTst = &pStruct->aLevel[iTst];
  1374. assert( pTst->nMerge==0 );
  1375. for(i=0; i<pTst->nSeg; i++){
  1376. int sz = pTst->aSeg[i].pgnoLast - pTst->aSeg[i].pgnoFirst + 1;
  1377. if( sz>szMax ) szMax = sz;
  1378. }
  1379. if( szMax>=szSeg ){
  1380. /* Condition (a) is true. Promote the newest segment on level
  1381. ** iLvl to level iTst. */
  1382. iPromote = iTst;
  1383. szPromote = szMax;
  1384. }
  1385. }
  1386. /* If condition (a) is not met, assume (b) is true. StructurePromoteTo()
  1387. ** is a no-op if it is not. */
  1388. if( iPromote<0 ){
  1389. iPromote = iLvl;
  1390. szPromote = szSeg;
  1391. }
  1392. fts5StructurePromoteTo(p, iPromote, szPromote, pStruct);
  1393. }
  1394. }
  1395. /*
  1396. ** Advance the iterator passed as the only argument. If the end of the
  1397. ** doclist-index page is reached, return non-zero.
  1398. */
  1399. static int fts5DlidxLvlNext(Fts5DlidxLvl *pLvl){
  1400. Fts5Data *pData = pLvl->pData;
  1401. if( pLvl->iOff==0 ){
  1402. assert( pLvl->bEof==0 );
  1403. pLvl->iOff = 1;
  1404. pLvl->iOff += fts5GetVarint32(&pData->p[1], pLvl->iLeafPgno);
  1405. pLvl->iOff += fts5GetVarint(&pData->p[pLvl->iOff], (u64*)&pLvl->iRowid);
  1406. pLvl->iFirstOff = pLvl->iOff;
  1407. }else{
  1408. int iOff;
  1409. for(iOff=pLvl->iOff; iOff<pData->nn; iOff++){
  1410. if( pData->p[iOff] ) break;
  1411. }
  1412. if( iOff<pData->nn ){
  1413. u64 iVal;
  1414. pLvl->iLeafPgno += (iOff - pLvl->iOff) + 1;
  1415. iOff += fts5GetVarint(&pData->p[iOff], &iVal);
  1416. pLvl->iRowid += iVal;
  1417. pLvl->iOff = iOff;
  1418. }else{
  1419. pLvl->bEof = 1;
  1420. }
  1421. }
  1422. return pLvl->bEof;
  1423. }
  1424. /*
  1425. ** Advance the iterator passed as the only argument.
  1426. */
  1427. static int fts5DlidxIterNextR(Fts5Index *p, Fts5DlidxIter *pIter, int iLvl){
  1428. Fts5DlidxLvl *pLvl = &pIter->aLvl[iLvl];
  1429. assert( iLvl<pIter->nLvl );
  1430. if( fts5DlidxLvlNext(pLvl) ){
  1431. if( (iLvl+1) < pIter->nLvl ){
  1432. fts5DlidxIterNextR(p, pIter, iLvl+1);
  1433. if( pLvl[1].bEof==0 ){
  1434. fts5DataRelease(pLvl->pData);
  1435. memset(pLvl, 0, sizeof(Fts5DlidxLvl));
  1436. pLvl->pData = fts5DataRead(p,
  1437. FTS5_DLIDX_ROWID(pIter->iSegid, iLvl, pLvl[1].iLeafPgno)
  1438. );
  1439. if( pLvl->pData ) fts5DlidxLvlNext(pLvl);
  1440. }
  1441. }
  1442. }
  1443. return pIter->aLvl[0].bEof;
  1444. }
  1445. static int fts5DlidxIterNext(Fts5Index *p, Fts5DlidxIter *pIter){
  1446. return fts5DlidxIterNextR(p, pIter, 0);
  1447. }
  1448. /*
  1449. ** The iterator passed as the first argument has the following fields set
  1450. ** as follows. This function sets up the rest of the iterator so that it
  1451. ** points to the first rowid in the doclist-index.
  1452. **
  1453. ** pData:
  1454. ** pointer to doclist-index record,
  1455. **
  1456. ** When this function is called pIter->iLeafPgno is the page number the
  1457. ** doclist is associated with (the one featuring the term).
  1458. */
  1459. static int fts5DlidxIterFirst(Fts5DlidxIter *pIter){
  1460. int i;
  1461. for(i=0; i<pIter->nLvl; i++){
  1462. fts5DlidxLvlNext(&pIter->aLvl[i]);
  1463. }
  1464. return pIter->aLvl[0].bEof;
  1465. }
  1466. static int fts5DlidxIterEof(Fts5Index *p, Fts5DlidxIter *pIter){
  1467. return p->rc!=SQLITE_OK || pIter->aLvl[0].bEof;
  1468. }
  1469. static void fts5DlidxIterLast(Fts5Index *p, Fts5DlidxIter *pIter){
  1470. int i;
  1471. /* Advance each level to the last entry on the last page */
  1472. for(i=pIter->nLvl-1; p->rc==SQLITE_OK && i>=0; i--){
  1473. Fts5DlidxLvl *pLvl = &pIter->aLvl[i];
  1474. while( fts5DlidxLvlNext(pLvl)==0 );
  1475. pLvl->bEof = 0;
  1476. if( i>0 ){
  1477. Fts5DlidxLvl *pChild = &pLvl[-1];
  1478. fts5DataRelease(pChild->pData);
  1479. memset(pChild, 0, sizeof(Fts5DlidxLvl));
  1480. pChild->pData = fts5DataRead(p,
  1481. FTS5_DLIDX_ROWID(pIter->iSegid, i-1, pLvl->iLeafPgno)
  1482. );
  1483. }
  1484. }
  1485. }
  1486. /*
  1487. ** Move the iterator passed as the only argument to the previous entry.
  1488. */
  1489. static int fts5DlidxLvlPrev(Fts5DlidxLvl *pLvl){
  1490. int iOff = pLvl->iOff;
  1491. assert( pLvl->bEof==0 );
  1492. if( iOff<=pLvl->iFirstOff ){
  1493. pLvl->bEof = 1;
  1494. }else{
  1495. u8 *a = pLvl->pData->p;
  1496. pLvl->iOff = 0;
  1497. fts5DlidxLvlNext(pLvl);
  1498. while( 1 ){
  1499. int nZero = 0;
  1500. int ii = pLvl->iOff;
  1501. u64 delta = 0;
  1502. while( a[ii]==0 ){
  1503. nZero++;
  1504. ii++;
  1505. }
  1506. ii += sqlite3Fts5GetVarint(&a[ii], &delta);
  1507. if( ii>=iOff ) break;
  1508. pLvl->iLeafPgno += nZero+1;
  1509. pLvl->iRowid += delta;
  1510. pLvl->iOff = ii;
  1511. }
  1512. }
  1513. return pLvl->bEof;
  1514. }
  1515. static int fts5DlidxIterPrevR(Fts5Index *p, Fts5DlidxIter *pIter, int iLvl){
  1516. Fts5DlidxLvl *pLvl = &pIter->aLvl[iLvl];
  1517. assert( iLvl<pIter->nLvl );
  1518. if( fts5DlidxLvlPrev(pLvl) ){
  1519. if( (iLvl+1) < pIter->nLvl ){
  1520. fts5DlidxIterPrevR(p, pIter, iLvl+1);
  1521. if( pLvl[1].bEof==0 ){
  1522. fts5DataRelease(pLvl->pData);
  1523. memset(pLvl, 0, sizeof(Fts5DlidxLvl));
  1524. pLvl->pData = fts5DataRead(p,
  1525. FTS5_DLIDX_ROWID(pIter->iSegid, iLvl, pLvl[1].iLeafPgno)
  1526. );
  1527. if( pLvl->pData ){
  1528. while( fts5DlidxLvlNext(pLvl)==0 );
  1529. pLvl->bEof = 0;
  1530. }
  1531. }
  1532. }
  1533. }
  1534. return pIter->aLvl[0].bEof;
  1535. }
  1536. static int fts5DlidxIterPrev(Fts5Index *p, Fts5DlidxIter *pIter){
  1537. return fts5DlidxIterPrevR(p, pIter, 0);
  1538. }
  1539. /*
  1540. ** Free a doclist-index iterator object allocated by fts5DlidxIterInit().
  1541. */
  1542. static void fts5DlidxIterFree(Fts5DlidxIter *pIter){
  1543. if( pIter ){
  1544. int i;
  1545. for(i=0; i<pIter->nLvl; i++){
  1546. fts5DataRelease(pIter->aLvl[i].pData);
  1547. }
  1548. sqlite3_free(pIter);
  1549. }
  1550. }
  1551. static Fts5DlidxIter *fts5DlidxIterInit(
  1552. Fts5Index *p, /* Fts5 Backend to iterate within */
  1553. int bRev, /* True for ORDER BY ASC */
  1554. int iSegid, /* Segment id */
  1555. int iLeafPg /* Leaf page number to load dlidx for */
  1556. ){
  1557. Fts5DlidxIter *pIter = 0;
  1558. int i;
  1559. int bDone = 0;
  1560. for(i=0; p->rc==SQLITE_OK && bDone==0; i++){
  1561. sqlite3_int64 nByte = sizeof(Fts5DlidxIter) + i * sizeof(Fts5DlidxLvl);
  1562. Fts5DlidxIter *pNew;
  1563. pNew = (Fts5DlidxIter*)sqlite3_realloc64(pIter, nByte);
  1564. if( pNew==0 ){
  1565. p->rc = SQLITE_NOMEM;
  1566. }else{
  1567. i64 iRowid = FTS5_DLIDX_ROWID(iSegid, i, iLeafPg);
  1568. Fts5DlidxLvl *pLvl = &pNew->aLvl[i];
  1569. pIter = pNew;
  1570. memset(pLvl, 0, sizeof(Fts5DlidxLvl));
  1571. pLvl->pData = fts5DataRead(p, iRowid);
  1572. if( pLvl->pData && (pLvl->pData->p[0] & 0x0001)==0 ){
  1573. bDone = 1;
  1574. }
  1575. pIter->nLvl = i+1;
  1576. }
  1577. }
  1578. if( p->rc==SQLITE_OK ){
  1579. pIter->iSegid = iSegid;
  1580. if( bRev==0 ){
  1581. fts5DlidxIterFirst(pIter);
  1582. }else{
  1583. fts5DlidxIterLast(p, pIter);
  1584. }
  1585. }
  1586. if( p->rc!=SQLITE_OK ){
  1587. fts5DlidxIterFree(pIter);
  1588. pIter = 0;
  1589. }
  1590. return pIter;
  1591. }
  1592. static i64 fts5DlidxIterRowid(Fts5DlidxIter *pIter){
  1593. return pIter->aLvl[0].iRowid;
  1594. }
  1595. static int fts5DlidxIterPgno(Fts5DlidxIter *pIter){
  1596. return pIter->aLvl[0].iLeafPgno;
  1597. }
  1598. /*
  1599. ** Load the next leaf page into the segment iterator.
  1600. */
  1601. static void fts5SegIterNextPage(
  1602. Fts5Index *p, /* FTS5 backend object */
  1603. Fts5SegIter *pIter /* Iterator to advance to next page */
  1604. ){
  1605. Fts5Data *pLeaf;
  1606. Fts5StructureSegment *pSeg = pIter->pSeg;
  1607. fts5DataRelease(pIter->pLeaf);
  1608. pIter->iLeafPgno++;
  1609. if( pIter->pNextLeaf ){
  1610. pIter->pLeaf = pIter->pNextLeaf;
  1611. pIter->pNextLeaf = 0;
  1612. }else if( pIter->iLeafPgno<=pSeg->pgnoLast ){
  1613. pIter->pLeaf = fts5LeafRead(p,
  1614. FTS5_SEGMENT_ROWID(pSeg->iSegid, pIter->iLeafPgno)
  1615. );
  1616. }else{
  1617. pIter->pLeaf = 0;
  1618. }
  1619. pLeaf = pIter->pLeaf;
  1620. if( pLeaf ){
  1621. pIter->iPgidxOff = pLeaf->szLeaf;
  1622. if( fts5LeafIsTermless(pLeaf) ){
  1623. pIter->iEndofDoclist = pLeaf->nn+1;
  1624. }else{
  1625. pIter->iPgidxOff += fts5GetVarint32(&pLeaf->p[pIter->iPgidxOff],
  1626. pIter->iEndofDoclist
  1627. );
  1628. }
  1629. }
  1630. }
  1631. /*
  1632. ** Argument p points to a buffer containing a varint to be interpreted as a
  1633. ** position list size field. Read the varint and return the number of bytes
  1634. ** read. Before returning, set *pnSz to the number of bytes in the position
  1635. ** list, and *pbDel to true if the delete flag is set, or false otherwise.
  1636. */
  1637. static int fts5GetPoslistSize(const u8 *p, int *pnSz, int *pbDel){
  1638. int nSz;
  1639. int n = 0;
  1640. fts5FastGetVarint32(p, n, nSz);
  1641. assert_nc( nSz>=0 );
  1642. *pnSz = nSz/2;
  1643. *pbDel = nSz & 0x0001;
  1644. return n;
  1645. }
  1646. /*
  1647. ** Fts5SegIter.iLeafOffset currently points to the first byte of a
  1648. ** position-list size field. Read the value of the field and store it
  1649. ** in the following variables:
  1650. **
  1651. ** Fts5SegIter.nPos
  1652. ** Fts5SegIter.bDel
  1653. **
  1654. ** Leave Fts5SegIter.iLeafOffset pointing to the first byte of the
  1655. ** position list content (if any).
  1656. */
  1657. static void fts5SegIterLoadNPos(Fts5Index *p, Fts5SegIter *pIter){
  1658. if( p->rc==SQLITE_OK ){
  1659. int iOff = pIter->iLeafOffset; /* Offset to read at */
  1660. ASSERT_SZLEAF_OK(pIter->pLeaf);
  1661. if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
  1662. int iEod = MIN(pIter->iEndofDoclist, pIter->pLeaf->szLeaf);
  1663. pIter->bDel = 0;
  1664. pIter->nPos = 1;
  1665. if( iOff<iEod && pIter->pLeaf->p[iOff]==0 ){
  1666. pIter->bDel = 1;
  1667. iOff++;
  1668. if( iOff<iEod && pIter->pLeaf->p[iOff]==0 ){
  1669. pIter->nPos = 1;
  1670. iOff++;
  1671. }else{
  1672. pIter->nPos = 0;
  1673. }
  1674. }
  1675. }else{
  1676. int nSz;
  1677. fts5FastGetVarint32(pIter->pLeaf->p, iOff, nSz);
  1678. pIter->bDel = (nSz & 0x0001);
  1679. pIter->nPos = nSz>>1;
  1680. assert_nc( pIter->nPos>=0 );
  1681. }
  1682. pIter->iLeafOffset = iOff;
  1683. }
  1684. }
  1685. static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
  1686. u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
  1687. i64 iOff = pIter->iLeafOffset;
  1688. ASSERT_SZLEAF_OK(pIter->pLeaf);
  1689. while( iOff>=pIter->pLeaf->szLeaf ){
  1690. fts5SegIterNextPage(p, pIter);
  1691. if( pIter->pLeaf==0 ){
  1692. if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
  1693. return;
  1694. }
  1695. iOff = 4;
  1696. a = pIter->pLeaf->p;
  1697. }
  1698. iOff += sqlite3Fts5GetVarint(&a[iOff], (u64*)&pIter->iRowid);
  1699. pIter->iLeafOffset = iOff;
  1700. }
  1701. /*
  1702. ** Fts5SegIter.iLeafOffset currently points to the first byte of the
  1703. ** "nSuffix" field of a term. Function parameter nKeep contains the value
  1704. ** of the "nPrefix" field (if there was one - it is passed 0 if this is
  1705. ** the first term in the segment).
  1706. **
  1707. ** This function populates:
  1708. **
  1709. ** Fts5SegIter.term
  1710. ** Fts5SegIter.rowid
  1711. **
  1712. ** accordingly and leaves (Fts5SegIter.iLeafOffset) set to the content of
  1713. ** the first position list. The position list belonging to document
  1714. ** (Fts5SegIter.iRowid).
  1715. */
  1716. static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){
  1717. u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
  1718. i64 iOff = pIter->iLeafOffset; /* Offset to read at */
  1719. int nNew; /* Bytes of new data */
  1720. iOff += fts5GetVarint32(&a[iOff], nNew);
  1721. if( iOff+nNew>pIter->pLeaf->szLeaf || nKeep>pIter->term.n || nNew==0 ){
  1722. p->rc = FTS5_CORRUPT;
  1723. return;
  1724. }
  1725. pIter->term.n = nKeep;
  1726. fts5BufferAppendBlob(&p->rc, &pIter->term, nNew, &a[iOff]);
  1727. assert( pIter->term.n<=pIter->term.nSpace );
  1728. iOff += nNew;
  1729. pIter->iTermLeafOffset = iOff;
  1730. pIter->iTermLeafPgno = pIter->iLeafPgno;
  1731. pIter->iLeafOffset = iOff;
  1732. if( pIter->iPgidxOff>=pIter->pLeaf->nn ){
  1733. pIter->iEndofDoclist = pIter->pLeaf->nn+1;
  1734. }else{
  1735. int nExtra;
  1736. pIter->iPgidxOff += fts5GetVarint32(&a[pIter->iPgidxOff], nExtra);
  1737. pIter->iEndofDoclist += nExtra;
  1738. }
  1739. fts5SegIterLoadRowid(p, pIter);
  1740. }
  1741. static void fts5SegIterNext(Fts5Index*, Fts5SegIter*, int*);
  1742. static void fts5SegIterNext_Reverse(Fts5Index*, Fts5SegIter*, int*);
  1743. static void fts5SegIterNext_None(Fts5Index*, Fts5SegIter*, int*);
  1744. static void fts5SegIterSetNext(Fts5Index *p, Fts5SegIter *pIter){
  1745. if( pIter->flags & FTS5_SEGITER_REVERSE ){
  1746. pIter->xNext = fts5SegIterNext_Reverse;
  1747. }else if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
  1748. pIter->xNext = fts5SegIterNext_None;
  1749. }else{
  1750. pIter->xNext = fts5SegIterNext;
  1751. }
  1752. }
  1753. /*
  1754. ** Allocate a tombstone hash page array object (pIter->pTombArray) for
  1755. ** the iterator passed as the second argument. If an OOM error occurs,
  1756. ** leave an error in the Fts5Index object.
  1757. */
  1758. static void fts5SegIterAllocTombstone(Fts5Index *p, Fts5SegIter *pIter){
  1759. const int nTomb = pIter->pSeg->nPgTombstone;
  1760. if( nTomb>0 ){
  1761. int nByte = nTomb * sizeof(Fts5Data*) + sizeof(Fts5TombstoneArray);
  1762. Fts5TombstoneArray *pNew;
  1763. pNew = (Fts5TombstoneArray*)sqlite3Fts5MallocZero(&p->rc, nByte);
  1764. if( pNew ){
  1765. pNew->nTombstone = nTomb;
  1766. pNew->nRef = 1;
  1767. pIter->pTombArray = pNew;
  1768. }
  1769. }
  1770. }
  1771. /*
  1772. ** Initialize the iterator object pIter to iterate through the entries in
  1773. ** segment pSeg. The iterator is left pointing to the first entry when
  1774. ** this function returns.
  1775. **
  1776. ** If an error occurs, Fts5Index.rc is set to an appropriate error code. If
  1777. ** an error has already occurred when this function is called, it is a no-op.
  1778. */
  1779. static void fts5SegIterInit(
  1780. Fts5Index *p, /* FTS index object */
  1781. Fts5StructureSegment *pSeg, /* Description of segment */
  1782. Fts5SegIter *pIter /* Object to populate */
  1783. ){
  1784. if( pSeg->pgnoFirst==0 ){
  1785. /* This happens if the segment is being used as an input to an incremental
  1786. ** merge and all data has already been "trimmed". See function
  1787. ** fts5TrimSegments() for details. In this case leave the iterator empty.
  1788. ** The caller will see the (pIter->pLeaf==0) and assume the iterator is
  1789. ** at EOF already. */
  1790. assert( pIter->pLeaf==0 );
  1791. return;
  1792. }
  1793. if( p->rc==SQLITE_OK ){
  1794. memset(pIter, 0, sizeof(*pIter));
  1795. fts5SegIterSetNext(p, pIter);
  1796. pIter->pSeg = pSeg;
  1797. pIter->iLeafPgno = pSeg->pgnoFirst-1;
  1798. do {
  1799. fts5SegIterNextPage(p, pIter);
  1800. }while( p->rc==SQLITE_OK && pIter->pLeaf && pIter->pLeaf->nn==4 );
  1801. }
  1802. if( p->rc==SQLITE_OK && pIter->pLeaf ){
  1803. pIter->iLeafOffset = 4;
  1804. assert( pIter->pLeaf!=0 );
  1805. assert_nc( pIter->pLeaf->nn>4 );
  1806. assert_nc( fts5LeafFirstTermOff(pIter->pLeaf)==4 );
  1807. pIter->iPgidxOff = pIter->pLeaf->szLeaf+1;
  1808. fts5SegIterLoadTerm(p, pIter, 0);
  1809. fts5SegIterLoadNPos(p, pIter);
  1810. fts5SegIterAllocTombstone(p, pIter);
  1811. }
  1812. }
  1813. /*
  1814. ** This function is only ever called on iterators created by calls to
  1815. ** Fts5IndexQuery() with the FTS5INDEX_QUERY_DESC flag set.
  1816. **
  1817. ** The iterator is in an unusual state when this function is called: the
  1818. ** Fts5SegIter.iLeafOffset variable is set to the offset of the start of
  1819. ** the position-list size field for the first relevant rowid on the page.
  1820. ** Fts5SegIter.rowid is set, but nPos and bDel are not.
  1821. **
  1822. ** This function advances the iterator so that it points to the last
  1823. ** relevant rowid on the page and, if necessary, initializes the
  1824. ** aRowidOffset[] and iRowidOffset variables. At this point the iterator
  1825. ** is in its regular state - Fts5SegIter.iLeafOffset points to the first
  1826. ** byte of the position list content associated with said rowid.
  1827. */
  1828. static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
  1829. int eDetail = p->pConfig->eDetail;
  1830. int n = pIter->pLeaf->szLeaf;
  1831. int i = pIter->iLeafOffset;
  1832. u8 *a = pIter->pLeaf->p;
  1833. int iRowidOffset = 0;
  1834. if( n>pIter->iEndofDoclist ){
  1835. n = pIter->iEndofDoclist;
  1836. }
  1837. ASSERT_SZLEAF_OK(pIter->pLeaf);
  1838. while( 1 ){
  1839. u64 iDelta = 0;
  1840. if( eDetail==FTS5_DETAIL_NONE ){
  1841. /* todo */
  1842. if( i<n && a[i]==0 ){
  1843. i++;
  1844. if( i<n && a[i]==0 ) i++;
  1845. }
  1846. }else{
  1847. int nPos;
  1848. int bDummy;
  1849. i += fts5GetPoslistSize(&a[i], &nPos, &bDummy);
  1850. i += nPos;
  1851. }
  1852. if( i>=n ) break;
  1853. i += fts5GetVarint(&a[i], &iDelta);
  1854. pIter->iRowid += iDelta;
  1855. /* If necessary, grow the pIter->aRowidOffset[] array. */
  1856. if( iRowidOffset>=pIter->nRowidOffset ){
  1857. int nNew = pIter->nRowidOffset + 8;
  1858. int *aNew = (int*)sqlite3_realloc64(pIter->aRowidOffset,nNew*sizeof(int));
  1859. if( aNew==0 ){
  1860. p->rc = SQLITE_NOMEM;
  1861. break;
  1862. }
  1863. pIter->aRowidOffset = aNew;
  1864. pIter->nRowidOffset = nNew;
  1865. }
  1866. pIter->aRowidOffset[iRowidOffset++] = pIter->iLeafOffset;
  1867. pIter->iLeafOffset = i;
  1868. }
  1869. pIter->iRowidOffset = iRowidOffset;
  1870. fts5SegIterLoadNPos(p, pIter);
  1871. }
  1872. /*
  1873. **
  1874. */
  1875. static void fts5SegIterReverseNewPage(Fts5Index *p, Fts5SegIter *pIter){
  1876. assert( pIter->flags & FTS5_SEGITER_REVERSE );
  1877. assert( pIter->flags & FTS5_SEGITER_ONETERM );
  1878. fts5DataRelease(pIter->pLeaf);
  1879. pIter->pLeaf = 0;
  1880. while( p->rc==SQLITE_OK && pIter->iLeafPgno>pIter->iTermLeafPgno ){
  1881. Fts5Data *pNew;
  1882. pIter->iLeafPgno--;
  1883. pNew = fts5DataRead(p, FTS5_SEGMENT_ROWID(
  1884. pIter->pSeg->iSegid, pIter->iLeafPgno
  1885. ));
  1886. if( pNew ){
  1887. /* iTermLeafOffset may be equal to szLeaf if the term is the last
  1888. ** thing on the page - i.e. the first rowid is on the following page.
  1889. ** In this case leave pIter->pLeaf==0, this iterator is at EOF. */
  1890. if( pIter->iLeafPgno==pIter->iTermLeafPgno ){
  1891. assert( pIter->pLeaf==0 );
  1892. if( pIter->iTermLeafOffset<pNew->szLeaf ){
  1893. pIter->pLeaf = pNew;
  1894. pIter->iLeafOffset = pIter->iTermLeafOffset;
  1895. }
  1896. }else{
  1897. int iRowidOff;
  1898. iRowidOff = fts5LeafFirstRowidOff(pNew);
  1899. if( iRowidOff ){
  1900. if( iRowidOff>=pNew->szLeaf ){
  1901. p->rc = FTS5_CORRUPT;
  1902. }else{
  1903. pIter->pLeaf = pNew;
  1904. pIter->iLeafOffset = iRowidOff;
  1905. }
  1906. }
  1907. }
  1908. if( pIter->pLeaf ){
  1909. u8 *a = &pIter->pLeaf->p[pIter->iLeafOffset];
  1910. pIter->iLeafOffset += fts5GetVarint(a, (u64*)&pIter->iRowid);
  1911. break;
  1912. }else{
  1913. fts5DataRelease(pNew);
  1914. }
  1915. }
  1916. }
  1917. if( pIter->pLeaf ){
  1918. pIter->iEndofDoclist = pIter->pLeaf->nn+1;
  1919. fts5SegIterReverseInitPage(p, pIter);
  1920. }
  1921. }
  1922. /*
  1923. ** Return true if the iterator passed as the second argument currently
  1924. ** points to a delete marker. A delete marker is an entry with a 0 byte
  1925. ** position-list.
  1926. */
  1927. static int fts5MultiIterIsEmpty(Fts5Index *p, Fts5Iter *pIter){
  1928. Fts5SegIter *pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst];
  1929. return (p->rc==SQLITE_OK && pSeg->pLeaf && pSeg->nPos==0);
  1930. }
  1931. /*
  1932. ** Advance iterator pIter to the next entry.
  1933. **
  1934. ** This version of fts5SegIterNext() is only used by reverse iterators.
  1935. */
  1936. static void fts5SegIterNext_Reverse(
  1937. Fts5Index *p, /* FTS5 backend object */
  1938. Fts5SegIter *pIter, /* Iterator to advance */
  1939. int *pbUnused /* Unused */
  1940. ){
  1941. assert( pIter->flags & FTS5_SEGITER_REVERSE );
  1942. assert( pIter->pNextLeaf==0 );
  1943. UNUSED_PARAM(pbUnused);
  1944. if( pIter->iRowidOffset>0 ){
  1945. u8 *a = pIter->pLeaf->p;
  1946. int iOff;
  1947. u64 iDelta;
  1948. pIter->iRowidOffset--;
  1949. pIter->iLeafOffset = pIter->aRowidOffset[pIter->iRowidOffset];
  1950. fts5SegIterLoadNPos(p, pIter);
  1951. iOff = pIter->iLeafOffset;
  1952. if( p->pConfig->eDetail!=FTS5_DETAIL_NONE ){
  1953. iOff += pIter->nPos;
  1954. }
  1955. fts5GetVarint(&a[iOff], &iDelta);
  1956. pIter->iRowid -= iDelta;
  1957. }else{
  1958. fts5SegIterReverseNewPage(p, pIter);
  1959. }
  1960. }
  1961. /*
  1962. ** Advance iterator pIter to the next entry.
  1963. **
  1964. ** This version of fts5SegIterNext() is only used if detail=none and the
  1965. ** iterator is not a reverse direction iterator.
  1966. */
  1967. static void fts5SegIterNext_None(
  1968. Fts5Index *p, /* FTS5 backend object */
  1969. Fts5SegIter *pIter, /* Iterator to advance */
  1970. int *pbNewTerm /* OUT: Set for new term */
  1971. ){
  1972. int iOff;
  1973. assert( p->rc==SQLITE_OK );
  1974. assert( (pIter->flags & FTS5_SEGITER_REVERSE)==0 );
  1975. assert( p->pConfig->eDetail==FTS5_DETAIL_NONE );
  1976. ASSERT_SZLEAF_OK(pIter->pLeaf);
  1977. iOff = pIter->iLeafOffset;
  1978. /* Next entry is on the next page */
  1979. while( pIter->pSeg && iOff>=pIter->pLeaf->szLeaf ){
  1980. fts5SegIterNextPage(p, pIter);
  1981. if( p->rc || pIter->pLeaf==0 ) return;
  1982. pIter->iRowid = 0;
  1983. iOff = 4;
  1984. }
  1985. if( iOff<pIter->iEndofDoclist ){
  1986. /* Next entry is on the current page */
  1987. u64 iDelta;
  1988. iOff += sqlite3Fts5GetVarint(&pIter->pLeaf->p[iOff], (u64*)&iDelta);
  1989. pIter->iLeafOffset = iOff;
  1990. pIter->iRowid += iDelta;
  1991. }else if( (pIter->flags & FTS5_SEGITER_ONETERM)==0 ){
  1992. if( pIter->pSeg ){
  1993. int nKeep = 0;
  1994. if( iOff!=fts5LeafFirstTermOff(pIter->pLeaf) ){
  1995. iOff += fts5GetVarint32(&pIter->pLeaf->p[iOff], nKeep);
  1996. }
  1997. pIter->iLeafOffset = iOff;
  1998. fts5SegIterLoadTerm(p, pIter, nKeep);
  1999. }else{
  2000. const u8 *pList = 0;
  2001. const char *zTerm = 0;
  2002. int nTerm = 0;
  2003. int nList;
  2004. sqlite3Fts5HashScanNext(p->pHash);
  2005. sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &nTerm, &pList, &nList);
  2006. if( pList==0 ) goto next_none_eof;
  2007. pIter->pLeaf->p = (u8*)pList;
  2008. pIter->pLeaf->nn = nList;
  2009. pIter->pLeaf->szLeaf = nList;
  2010. pIter->iEndofDoclist = nList;
  2011. sqlite3Fts5BufferSet(&p->rc,&pIter->term, nTerm, (u8*)zTerm);
  2012. pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid);
  2013. }
  2014. if( pbNewTerm ) *pbNewTerm = 1;
  2015. }else{
  2016. goto next_none_eof;
  2017. }
  2018. fts5SegIterLoadNPos(p, pIter);
  2019. return;
  2020. next_none_eof:
  2021. fts5DataRelease(pIter->pLeaf);
  2022. pIter->pLeaf = 0;
  2023. }
  2024. /*
  2025. ** Advance iterator pIter to the next entry.
  2026. **
  2027. ** If an error occurs, Fts5Index.rc is set to an appropriate error code. It
  2028. ** is not considered an error if the iterator reaches EOF. If an error has
  2029. ** already occurred when this function is called, it is a no-op.
  2030. */
  2031. static void fts5SegIterNext(
  2032. Fts5Index *p, /* FTS5 backend object */
  2033. Fts5SegIter *pIter, /* Iterator to advance */
  2034. int *pbNewTerm /* OUT: Set for new term */
  2035. ){
  2036. Fts5Data *pLeaf = pIter->pLeaf;
  2037. int iOff;
  2038. int bNewTerm = 0;
  2039. int nKeep = 0;
  2040. u8 *a;
  2041. int n;
  2042. assert( pbNewTerm==0 || *pbNewTerm==0 );
  2043. assert( p->pConfig->eDetail!=FTS5_DETAIL_NONE );
  2044. /* Search for the end of the position list within the current page. */
  2045. a = pLeaf->p;
  2046. n = pLeaf->szLeaf;
  2047. ASSERT_SZLEAF_OK(pLeaf);
  2048. iOff = pIter->iLeafOffset + pIter->nPos;
  2049. if( iOff<n ){
  2050. /* The next entry is on the current page. */
  2051. assert_nc( iOff<=pIter->iEndofDoclist );
  2052. if( iOff>=pIter->iEndofDoclist ){
  2053. bNewTerm = 1;
  2054. if( iOff!=fts5LeafFirstTermOff(pLeaf) ){
  2055. iOff += fts5GetVarint32(&a[iOff], nKeep);
  2056. }
  2057. }else{
  2058. u64 iDelta;
  2059. iOff += sqlite3Fts5GetVarint(&a[iOff], &iDelta);
  2060. pIter->iRowid += iDelta;
  2061. assert_nc( iDelta>0 );
  2062. }
  2063. pIter->iLeafOffset = iOff;
  2064. }else if( pIter->pSeg==0 ){
  2065. const u8 *pList = 0;
  2066. const char *zTerm = 0;
  2067. int nTerm = 0;
  2068. int nList = 0;
  2069. assert( (pIter->flags & FTS5_SEGITER_ONETERM) || pbNewTerm );
  2070. if( 0==(pIter->flags & FTS5_SEGITER_ONETERM) ){
  2071. sqlite3Fts5HashScanNext(p->pHash);
  2072. sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &nTerm, &pList, &nList);
  2073. }
  2074. if( pList==0 ){
  2075. fts5DataRelease(pIter->pLeaf);
  2076. pIter->pLeaf = 0;
  2077. }else{
  2078. pIter->pLeaf->p = (u8*)pList;
  2079. pIter->pLeaf->nn = nList;
  2080. pIter->pLeaf->szLeaf = nList;
  2081. pIter->iEndofDoclist = nList+1;
  2082. sqlite3Fts5BufferSet(&p->rc, &pIter->term, nTerm, (u8*)zTerm);
  2083. pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid);
  2084. *pbNewTerm = 1;
  2085. }
  2086. }else{
  2087. iOff = 0;
  2088. /* Next entry is not on the current page */
  2089. while( iOff==0 ){
  2090. fts5SegIterNextPage(p, pIter);
  2091. pLeaf = pIter->pLeaf;
  2092. if( pLeaf==0 ) break;
  2093. ASSERT_SZLEAF_OK(pLeaf);
  2094. if( (iOff = fts5LeafFirstRowidOff(pLeaf)) && iOff<pLeaf->szLeaf ){
  2095. iOff += sqlite3Fts5GetVarint(&pLeaf->p[iOff], (u64*)&pIter->iRowid);
  2096. pIter->iLeafOffset = iOff;
  2097. if( pLeaf->nn>pLeaf->szLeaf ){
  2098. pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32(
  2099. &pLeaf->p[pLeaf->szLeaf], pIter->iEndofDoclist
  2100. );
  2101. }
  2102. }
  2103. else if( pLeaf->nn>pLeaf->szLeaf ){
  2104. pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32(
  2105. &pLeaf->p[pLeaf->szLeaf], iOff
  2106. );
  2107. pIter->iLeafOffset = iOff;
  2108. pIter->iEndofDoclist = iOff;
  2109. bNewTerm = 1;
  2110. }
  2111. assert_nc( iOff<pLeaf->szLeaf );
  2112. if( iOff>pLeaf->szLeaf ){
  2113. p->rc = FTS5_CORRUPT;
  2114. return;
  2115. }
  2116. }
  2117. }
  2118. /* Check if the iterator is now at EOF. If so, return early. */
  2119. if( pIter->pLeaf ){
  2120. if( bNewTerm ){
  2121. if( pIter->flags & FTS5_SEGITER_ONETERM ){
  2122. fts5DataRelease(pIter->pLeaf);
  2123. pIter->pLeaf = 0;
  2124. }else{
  2125. fts5SegIterLoadTerm(p, pIter, nKeep);
  2126. fts5SegIterLoadNPos(p, pIter);
  2127. if( pbNewTerm ) *pbNewTerm = 1;
  2128. }
  2129. }else{
  2130. /* The following could be done by calling fts5SegIterLoadNPos(). But
  2131. ** this block is particularly performance critical, so equivalent
  2132. ** code is inlined. */
  2133. int nSz;
  2134. assert_nc( pIter->iLeafOffset<=pIter->pLeaf->nn );
  2135. fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz);
  2136. pIter->bDel = (nSz & 0x0001);
  2137. pIter->nPos = nSz>>1;
  2138. assert_nc( pIter->nPos>=0 );
  2139. }
  2140. }
  2141. }
  2142. #define SWAPVAL(T, a, b) { T tmp; tmp=a; a=b; b=tmp; }
  2143. #define fts5IndexSkipVarint(a, iOff) { \
  2144. int iEnd = iOff+9; \
  2145. while( (a[iOff++] & 0x80) && iOff<iEnd ); \
  2146. }
  2147. /*
  2148. ** Iterator pIter currently points to the first rowid in a doclist. This
  2149. ** function sets the iterator up so that iterates in reverse order through
  2150. ** the doclist.
  2151. */
  2152. static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){
  2153. Fts5DlidxIter *pDlidx = pIter->pDlidx;
  2154. Fts5Data *pLast = 0;
  2155. int pgnoLast = 0;
  2156. if( pDlidx && p->pConfig->iVersion==FTS5_CURRENT_VERSION ){
  2157. int iSegid = pIter->pSeg->iSegid;
  2158. pgnoLast = fts5DlidxIterPgno(pDlidx);
  2159. pLast = fts5LeafRead(p, FTS5_SEGMENT_ROWID(iSegid, pgnoLast));
  2160. }else{
  2161. Fts5Data *pLeaf = pIter->pLeaf; /* Current leaf data */
  2162. /* Currently, Fts5SegIter.iLeafOffset points to the first byte of
  2163. ** position-list content for the current rowid. Back it up so that it
  2164. ** points to the start of the position-list size field. */
  2165. int iPoslist;
  2166. if( pIter->iTermLeafPgno==pIter->iLeafPgno ){
  2167. iPoslist = pIter->iTermLeafOffset;
  2168. }else{
  2169. iPoslist = 4;
  2170. }
  2171. fts5IndexSkipVarint(pLeaf->p, iPoslist);
  2172. pIter->iLeafOffset = iPoslist;
  2173. /* If this condition is true then the largest rowid for the current
  2174. ** term may not be stored on the current page. So search forward to
  2175. ** see where said rowid really is. */
  2176. if( pIter->iEndofDoclist>=pLeaf->szLeaf ){
  2177. int pgno;
  2178. Fts5StructureSegment *pSeg = pIter->pSeg;
  2179. /* The last rowid in the doclist may not be on the current page. Search
  2180. ** forward to find the page containing the last rowid. */
  2181. for(pgno=pIter->iLeafPgno+1; !p->rc && pgno<=pSeg->pgnoLast; pgno++){
  2182. i64 iAbs = FTS5_SEGMENT_ROWID(pSeg->iSegid, pgno);
  2183. Fts5Data *pNew = fts5LeafRead(p, iAbs);
  2184. if( pNew ){
  2185. int iRowid, bTermless;
  2186. iRowid = fts5LeafFirstRowidOff(pNew);
  2187. bTermless = fts5LeafIsTermless(pNew);
  2188. if( iRowid ){
  2189. SWAPVAL(Fts5Data*, pNew, pLast);
  2190. pgnoLast = pgno;
  2191. }
  2192. fts5DataRelease(pNew);
  2193. if( bTermless==0 ) break;
  2194. }
  2195. }
  2196. }
  2197. }
  2198. /* If pLast is NULL at this point, then the last rowid for this doclist
  2199. ** lies on the page currently indicated by the iterator. In this case
  2200. ** pIter->iLeafOffset is already set to point to the position-list size
  2201. ** field associated with the first relevant rowid on the page.
  2202. **
  2203. ** Or, if pLast is non-NULL, then it is the page that contains the last
  2204. ** rowid. In this case configure the iterator so that it points to the
  2205. ** first rowid on this page.
  2206. */
  2207. if( pLast ){
  2208. int iOff;
  2209. fts5DataRelease(pIter->pLeaf);
  2210. pIter->pLeaf = pLast;
  2211. pIter->iLeafPgno = pgnoLast;
  2212. iOff = fts5LeafFirstRowidOff(pLast);
  2213. if( iOff>pLast->szLeaf ){
  2214. p->rc = FTS5_CORRUPT;
  2215. return;
  2216. }
  2217. iOff += fts5GetVarint(&pLast->p[iOff], (u64*)&pIter->iRowid);
  2218. pIter->iLeafOffset = iOff;
  2219. if( fts5LeafIsTermless(pLast) ){
  2220. pIter->iEndofDoclist = pLast->nn+1;
  2221. }else{
  2222. pIter->iEndofDoclist = fts5LeafFirstTermOff(pLast);
  2223. }
  2224. }
  2225. fts5SegIterReverseInitPage(p, pIter);
  2226. }
  2227. /*
  2228. ** Iterator pIter currently points to the first rowid of a doclist.
  2229. ** There is a doclist-index associated with the final term on the current
  2230. ** page. If the current term is the last term on the page, load the
  2231. ** doclist-index from disk and initialize an iterator at (pIter->pDlidx).
  2232. */
  2233. static void fts5SegIterLoadDlidx(Fts5Index *p, Fts5SegIter *pIter){
  2234. int iSeg = pIter->pSeg->iSegid;
  2235. int bRev = (pIter->flags & FTS5_SEGITER_REVERSE);
  2236. Fts5Data *pLeaf = pIter->pLeaf; /* Current leaf data */
  2237. assert( pIter->flags & FTS5_SEGITER_ONETERM );
  2238. assert( pIter->pDlidx==0 );
  2239. /* Check if the current doclist ends on this page. If it does, return
  2240. ** early without loading the doclist-index (as it belongs to a different
  2241. ** term. */
  2242. if( pIter->iTermLeafPgno==pIter->iLeafPgno
  2243. && pIter->iEndofDoclist<pLeaf->szLeaf
  2244. ){
  2245. return;
  2246. }
  2247. pIter->pDlidx = fts5DlidxIterInit(p, bRev, iSeg, pIter->iTermLeafPgno);
  2248. }
  2249. /*
  2250. ** The iterator object passed as the second argument currently contains
  2251. ** no valid values except for the Fts5SegIter.pLeaf member variable. This
  2252. ** function searches the leaf page for a term matching (pTerm/nTerm).
  2253. **
  2254. ** If the specified term is found on the page, then the iterator is left
  2255. ** pointing to it. If argument bGe is zero and the term is not found,
  2256. ** the iterator is left pointing at EOF.
  2257. **
  2258. ** If bGe is non-zero and the specified term is not found, then the
  2259. ** iterator is left pointing to the smallest term in the segment that
  2260. ** is larger than the specified term, even if this term is not on the
  2261. ** current page.
  2262. */
  2263. static void fts5LeafSeek(
  2264. Fts5Index *p, /* Leave any error code here */
  2265. int bGe, /* True for a >= search */
  2266. Fts5SegIter *pIter, /* Iterator to seek */
  2267. const u8 *pTerm, int nTerm /* Term to search for */
  2268. ){
  2269. u32 iOff;
  2270. const u8 *a = pIter->pLeaf->p;
  2271. u32 n = (u32)pIter->pLeaf->nn;
  2272. u32 nMatch = 0;
  2273. u32 nKeep = 0;
  2274. u32 nNew = 0;
  2275. u32 iTermOff;
  2276. u32 iPgidx; /* Current offset in pgidx */
  2277. int bEndOfPage = 0;
  2278. assert( p->rc==SQLITE_OK );
  2279. iPgidx = (u32)pIter->pLeaf->szLeaf;
  2280. iPgidx += fts5GetVarint32(&a[iPgidx], iTermOff);
  2281. iOff = iTermOff;
  2282. if( iOff>n ){
  2283. p->rc = FTS5_CORRUPT;
  2284. return;
  2285. }
  2286. while( 1 ){
  2287. /* Figure out how many new bytes are in this term */
  2288. fts5FastGetVarint32(a, iOff, nNew);
  2289. if( nKeep<nMatch ){
  2290. goto search_failed;
  2291. }
  2292. assert( nKeep>=nMatch );
  2293. if( nKeep==nMatch ){
  2294. u32 nCmp;
  2295. u32 i;
  2296. nCmp = (u32)MIN(nNew, nTerm-nMatch);
  2297. for(i=0; i<nCmp; i++){
  2298. if( a[iOff+i]!=pTerm[nMatch+i] ) break;
  2299. }
  2300. nMatch += i;
  2301. if( (u32)nTerm==nMatch ){
  2302. if( i==nNew ){
  2303. goto search_success;
  2304. }else{
  2305. goto search_failed;
  2306. }
  2307. }else if( i<nNew && a[iOff+i]>pTerm[nMatch] ){
  2308. goto search_failed;
  2309. }
  2310. }
  2311. if( iPgidx>=n ){
  2312. bEndOfPage = 1;
  2313. break;
  2314. }
  2315. iPgidx += fts5GetVarint32(&a[iPgidx], nKeep);
  2316. iTermOff += nKeep;
  2317. iOff = iTermOff;
  2318. if( iOff>=n ){
  2319. p->rc = FTS5_CORRUPT;
  2320. return;
  2321. }
  2322. /* Read the nKeep field of the next term. */
  2323. fts5FastGetVarint32(a, iOff, nKeep);
  2324. }
  2325. search_failed:
  2326. if( bGe==0 ){
  2327. fts5DataRelease(pIter->pLeaf);
  2328. pIter->pLeaf = 0;
  2329. return;
  2330. }else if( bEndOfPage ){
  2331. do {
  2332. fts5SegIterNextPage(p, pIter);
  2333. if( pIter->pLeaf==0 ) return;
  2334. a = pIter->pLeaf->p;
  2335. if( fts5LeafIsTermless(pIter->pLeaf)==0 ){
  2336. iPgidx = (u32)pIter->pLeaf->szLeaf;
  2337. iPgidx += fts5GetVarint32(&pIter->pLeaf->p[iPgidx], iOff);
  2338. if( iOff<4 || (i64)iOff>=pIter->pLeaf->szLeaf ){
  2339. p->rc = FTS5_CORRUPT;
  2340. return;
  2341. }else{
  2342. nKeep = 0;
  2343. iTermOff = iOff;
  2344. n = (u32)pIter->pLeaf->nn;
  2345. iOff += fts5GetVarint32(&a[iOff], nNew);
  2346. break;
  2347. }
  2348. }
  2349. }while( 1 );
  2350. }
  2351. search_success:
  2352. if( (i64)iOff+nNew>n || nNew<1 ){
  2353. p->rc = FTS5_CORRUPT;
  2354. return;
  2355. }
  2356. pIter->iLeafOffset = iOff + nNew;
  2357. pIter->iTermLeafOffset = pIter->iLeafOffset;
  2358. pIter->iTermLeafPgno = pIter->iLeafPgno;
  2359. fts5BufferSet(&p->rc, &pIter->term, nKeep, pTerm);
  2360. fts5BufferAppendBlob(&p->rc, &pIter->term, nNew, &a[iOff]);
  2361. if( iPgidx>=n ){
  2362. pIter->iEndofDoclist = pIter->pLeaf->nn+1;
  2363. }else{
  2364. int nExtra;
  2365. iPgidx += fts5GetVarint32(&a[iPgidx], nExtra);
  2366. pIter->iEndofDoclist = iTermOff + nExtra;
  2367. }
  2368. pIter->iPgidxOff = iPgidx;
  2369. fts5SegIterLoadRowid(p, pIter);
  2370. fts5SegIterLoadNPos(p, pIter);
  2371. }
  2372. static sqlite3_stmt *fts5IdxSelectStmt(Fts5Index *p){
  2373. if( p->pIdxSelect==0 ){
  2374. Fts5Config *pConfig = p->pConfig;
  2375. fts5IndexPrepareStmt(p, &p->pIdxSelect, sqlite3_mprintf(
  2376. "SELECT pgno FROM '%q'.'%q_idx' WHERE "
  2377. "segid=? AND term<=? ORDER BY term DESC LIMIT 1",
  2378. pConfig->zDb, pConfig->zName
  2379. ));
  2380. }
  2381. return p->pIdxSelect;
  2382. }
  2383. /*
  2384. ** Initialize the object pIter to point to term pTerm/nTerm within segment
  2385. ** pSeg. If there is no such term in the index, the iterator is set to EOF.
  2386. **
  2387. ** If an error occurs, Fts5Index.rc is set to an appropriate error code. If
  2388. ** an error has already occurred when this function is called, it is a no-op.
  2389. */
  2390. static void fts5SegIterSeekInit(
  2391. Fts5Index *p, /* FTS5 backend */
  2392. const u8 *pTerm, int nTerm, /* Term to seek to */
  2393. int flags, /* Mask of FTS5INDEX_XXX flags */
  2394. Fts5StructureSegment *pSeg, /* Description of segment */
  2395. Fts5SegIter *pIter /* Object to populate */
  2396. ){
  2397. int iPg = 1;
  2398. int bGe = (flags & FTS5INDEX_QUERY_SCAN);
  2399. int bDlidx = 0; /* True if there is a doclist-index */
  2400. sqlite3_stmt *pIdxSelect = 0;
  2401. assert( bGe==0 || (flags & FTS5INDEX_QUERY_DESC)==0 );
  2402. assert( pTerm && nTerm );
  2403. memset(pIter, 0, sizeof(*pIter));
  2404. pIter->pSeg = pSeg;
  2405. /* This block sets stack variable iPg to the leaf page number that may
  2406. ** contain term (pTerm/nTerm), if it is present in the segment. */
  2407. pIdxSelect = fts5IdxSelectStmt(p);
  2408. if( p->rc ) return;
  2409. sqlite3_bind_int(pIdxSelect, 1, pSeg->iSegid);
  2410. sqlite3_bind_blob(pIdxSelect, 2, pTerm, nTerm, SQLITE_STATIC);
  2411. if( SQLITE_ROW==sqlite3_step(pIdxSelect) ){
  2412. i64 val = sqlite3_column_int(pIdxSelect, 0);
  2413. iPg = (int)(val>>1);
  2414. bDlidx = (val & 0x0001);
  2415. }
  2416. p->rc = sqlite3_reset(pIdxSelect);
  2417. sqlite3_bind_null(pIdxSelect, 2);
  2418. if( iPg<pSeg->pgnoFirst ){
  2419. iPg = pSeg->pgnoFirst;
  2420. bDlidx = 0;
  2421. }
  2422. pIter->iLeafPgno = iPg - 1;
  2423. fts5SegIterNextPage(p, pIter);
  2424. if( pIter->pLeaf ){
  2425. fts5LeafSeek(p, bGe, pIter, pTerm, nTerm);
  2426. }
  2427. if( p->rc==SQLITE_OK && (bGe==0 || (flags & FTS5INDEX_QUERY_SCANONETERM)) ){
  2428. pIter->flags |= FTS5_SEGITER_ONETERM;
  2429. if( pIter->pLeaf ){
  2430. if( flags & FTS5INDEX_QUERY_DESC ){
  2431. pIter->flags |= FTS5_SEGITER_REVERSE;
  2432. }
  2433. if( bDlidx ){
  2434. fts5SegIterLoadDlidx(p, pIter);
  2435. }
  2436. if( flags & FTS5INDEX_QUERY_DESC ){
  2437. fts5SegIterReverse(p, pIter);
  2438. }
  2439. }
  2440. }
  2441. fts5SegIterSetNext(p, pIter);
  2442. if( 0==(flags & FTS5INDEX_QUERY_SCANONETERM) ){
  2443. fts5SegIterAllocTombstone(p, pIter);
  2444. }
  2445. /* Either:
  2446. **
  2447. ** 1) an error has occurred, or
  2448. ** 2) the iterator points to EOF, or
  2449. ** 3) the iterator points to an entry with term (pTerm/nTerm), or
  2450. ** 4) the FTS5INDEX_QUERY_SCAN flag was set and the iterator points
  2451. ** to an entry with a term greater than or equal to (pTerm/nTerm).
  2452. */
  2453. assert_nc( p->rc!=SQLITE_OK /* 1 */
  2454. || pIter->pLeaf==0 /* 2 */
  2455. || fts5BufferCompareBlob(&pIter->term, pTerm, nTerm)==0 /* 3 */
  2456. || (bGe && fts5BufferCompareBlob(&pIter->term, pTerm, nTerm)>0) /* 4 */
  2457. );
  2458. }
  2459. /*
  2460. ** SQL used by fts5SegIterNextInit() to find the page to open.
  2461. */
  2462. static sqlite3_stmt *fts5IdxNextStmt(Fts5Index *p){
  2463. if( p->pIdxNextSelect==0 ){
  2464. Fts5Config *pConfig = p->pConfig;
  2465. fts5IndexPrepareStmt(p, &p->pIdxNextSelect, sqlite3_mprintf(
  2466. "SELECT pgno FROM '%q'.'%q_idx' WHERE "
  2467. "segid=? AND term>? ORDER BY term ASC LIMIT 1",
  2468. pConfig->zDb, pConfig->zName
  2469. ));
  2470. }
  2471. return p->pIdxNextSelect;
  2472. }
  2473. /*
  2474. ** This is similar to fts5SegIterSeekInit(), except that it initializes
  2475. ** the segment iterator to point to the first term following the page
  2476. ** with pToken/nToken on it.
  2477. */
  2478. static void fts5SegIterNextInit(
  2479. Fts5Index *p,
  2480. const char *pTerm, int nTerm,
  2481. Fts5StructureSegment *pSeg, /* Description of segment */
  2482. Fts5SegIter *pIter /* Object to populate */
  2483. ){
  2484. int iPg = -1; /* Page of segment to open */
  2485. int bDlidx = 0;
  2486. sqlite3_stmt *pSel = 0; /* SELECT to find iPg */
  2487. pSel = fts5IdxNextStmt(p);
  2488. if( pSel ){
  2489. assert( p->rc==SQLITE_OK );
  2490. sqlite3_bind_int(pSel, 1, pSeg->iSegid);
  2491. sqlite3_bind_blob(pSel, 2, pTerm, nTerm, SQLITE_STATIC);
  2492. if( sqlite3_step(pSel)==SQLITE_ROW ){
  2493. i64 val = sqlite3_column_int64(pSel, 0);
  2494. iPg = (int)(val>>1);
  2495. bDlidx = (val & 0x0001);
  2496. }
  2497. p->rc = sqlite3_reset(pSel);
  2498. sqlite3_bind_null(pSel, 2);
  2499. if( p->rc ) return;
  2500. }
  2501. memset(pIter, 0, sizeof(*pIter));
  2502. pIter->pSeg = pSeg;
  2503. pIter->flags |= FTS5_SEGITER_ONETERM;
  2504. if( iPg>=0 ){
  2505. pIter->iLeafPgno = iPg - 1;
  2506. fts5SegIterNextPage(p, pIter);
  2507. fts5SegIterSetNext(p, pIter);
  2508. }
  2509. if( pIter->pLeaf ){
  2510. const u8 *a = pIter->pLeaf->p;
  2511. int iTermOff = 0;
  2512. pIter->iPgidxOff = pIter->pLeaf->szLeaf;
  2513. pIter->iPgidxOff += fts5GetVarint32(&a[pIter->iPgidxOff], iTermOff);
  2514. pIter->iLeafOffset = iTermOff;
  2515. fts5SegIterLoadTerm(p, pIter, 0);
  2516. fts5SegIterLoadNPos(p, pIter);
  2517. if( bDlidx ) fts5SegIterLoadDlidx(p, pIter);
  2518. assert( p->rc!=SQLITE_OK ||
  2519. fts5BufferCompareBlob(&pIter->term, (const u8*)pTerm, nTerm)>0
  2520. );
  2521. }
  2522. }
  2523. /*
  2524. ** Initialize the object pIter to point to term pTerm/nTerm within the
  2525. ** in-memory hash table. If there is no such term in the hash-table, the
  2526. ** iterator is set to EOF.
  2527. **
  2528. ** If an error occurs, Fts5Index.rc is set to an appropriate error code. If
  2529. ** an error has already occurred when this function is called, it is a no-op.
  2530. */
  2531. static void fts5SegIterHashInit(
  2532. Fts5Index *p, /* FTS5 backend */
  2533. const u8 *pTerm, int nTerm, /* Term to seek to */
  2534. int flags, /* Mask of FTS5INDEX_XXX flags */
  2535. Fts5SegIter *pIter /* Object to populate */
  2536. ){
  2537. int nList = 0;
  2538. const u8 *z = 0;
  2539. int n = 0;
  2540. Fts5Data *pLeaf = 0;
  2541. assert( p->pHash );
  2542. assert( p->rc==SQLITE_OK );
  2543. if( pTerm==0 || (flags & FTS5INDEX_QUERY_SCAN) ){
  2544. const u8 *pList = 0;
  2545. p->rc = sqlite3Fts5HashScanInit(p->pHash, (const char*)pTerm, nTerm);
  2546. sqlite3Fts5HashScanEntry(p->pHash, (const char**)&z, &n, &pList, &nList);
  2547. if( pList ){
  2548. pLeaf = fts5IdxMalloc(p, sizeof(Fts5Data));
  2549. if( pLeaf ){
  2550. pLeaf->p = (u8*)pList;
  2551. }
  2552. }
  2553. /* The call to sqlite3Fts5HashScanInit() causes the hash table to
  2554. ** fill the size field of all existing position lists. This means they
  2555. ** can no longer be appended to. Since the only scenario in which they
  2556. ** can be appended to is if the previous operation on this table was
  2557. ** a DELETE, by clearing the Fts5Index.bDelete flag we can avoid this
  2558. ** possibility altogether. */
  2559. p->bDelete = 0;
  2560. }else{
  2561. p->rc = sqlite3Fts5HashQuery(p->pHash, sizeof(Fts5Data),
  2562. (const char*)pTerm, nTerm, (void**)&pLeaf, &nList
  2563. );
  2564. if( pLeaf ){
  2565. pLeaf->p = (u8*)&pLeaf[1];
  2566. }
  2567. z = pTerm;
  2568. n = nTerm;
  2569. pIter->flags |= FTS5_SEGITER_ONETERM;
  2570. }
  2571. if( pLeaf ){
  2572. sqlite3Fts5BufferSet(&p->rc, &pIter->term, n, z);
  2573. pLeaf->nn = pLeaf->szLeaf = nList;
  2574. pIter->pLeaf = pLeaf;
  2575. pIter->iLeafOffset = fts5GetVarint(pLeaf->p, (u64*)&pIter->iRowid);
  2576. pIter->iEndofDoclist = pLeaf->nn;
  2577. if( flags & FTS5INDEX_QUERY_DESC ){
  2578. pIter->flags |= FTS5_SEGITER_REVERSE;
  2579. fts5SegIterReverseInitPage(p, pIter);
  2580. }else{
  2581. fts5SegIterLoadNPos(p, pIter);
  2582. }
  2583. }
  2584. fts5SegIterSetNext(p, pIter);
  2585. }
  2586. /*
  2587. ** Array ap[] contains n elements. Release each of these elements using
  2588. ** fts5DataRelease(). Then free the array itself using sqlite3_free().
  2589. */
  2590. static void fts5IndexFreeArray(Fts5Data **ap, int n){
  2591. if( ap ){
  2592. int ii;
  2593. for(ii=0; ii<n; ii++){
  2594. fts5DataRelease(ap[ii]);
  2595. }
  2596. sqlite3_free(ap);
  2597. }
  2598. }
  2599. /*
  2600. ** Decrement the ref-count of the object passed as the only argument. If it
  2601. ** reaches 0, free it and its contents.
  2602. */
  2603. static void fts5TombstoneArrayDelete(Fts5TombstoneArray *p){
  2604. if( p ){
  2605. p->nRef--;
  2606. if( p->nRef<=0 ){
  2607. int ii;
  2608. for(ii=0; ii<p->nTombstone; ii++){
  2609. fts5DataRelease(p->apTombstone[ii]);
  2610. }
  2611. sqlite3_free(p);
  2612. }
  2613. }
  2614. }
  2615. /*
  2616. ** Zero the iterator passed as the only argument.
  2617. */
  2618. static void fts5SegIterClear(Fts5SegIter *pIter){
  2619. fts5BufferFree(&pIter->term);
  2620. fts5DataRelease(pIter->pLeaf);
  2621. fts5DataRelease(pIter->pNextLeaf);
  2622. fts5TombstoneArrayDelete(pIter->pTombArray);
  2623. fts5DlidxIterFree(pIter->pDlidx);
  2624. sqlite3_free(pIter->aRowidOffset);
  2625. memset(pIter, 0, sizeof(Fts5SegIter));
  2626. }
  2627. #ifdef SQLITE_DEBUG
  2628. /*
  2629. ** This function is used as part of the big assert() procedure implemented by
  2630. ** fts5AssertMultiIterSetup(). It ensures that the result currently stored
  2631. ** in *pRes is the correct result of comparing the current positions of the
  2632. ** two iterators.
  2633. */
  2634. static void fts5AssertComparisonResult(
  2635. Fts5Iter *pIter,
  2636. Fts5SegIter *p1,
  2637. Fts5SegIter *p2,
  2638. Fts5CResult *pRes
  2639. ){
  2640. int i1 = p1 - pIter->aSeg;
  2641. int i2 = p2 - pIter->aSeg;
  2642. if( p1->pLeaf || p2->pLeaf ){
  2643. if( p1->pLeaf==0 ){
  2644. assert( pRes->iFirst==i2 );
  2645. }else if( p2->pLeaf==0 ){
  2646. assert( pRes->iFirst==i1 );
  2647. }else{
  2648. int nMin = MIN(p1->term.n, p2->term.n);
  2649. int res = fts5Memcmp(p1->term.p, p2->term.p, nMin);
  2650. if( res==0 ) res = p1->term.n - p2->term.n;
  2651. if( res==0 ){
  2652. assert( pRes->bTermEq==1 );
  2653. assert( p1->iRowid!=p2->iRowid );
  2654. res = ((p1->iRowid > p2->iRowid)==pIter->bRev) ? -1 : 1;
  2655. }else{
  2656. assert( pRes->bTermEq==0 );
  2657. }
  2658. if( res<0 ){
  2659. assert( pRes->iFirst==i1 );
  2660. }else{
  2661. assert( pRes->iFirst==i2 );
  2662. }
  2663. }
  2664. }
  2665. }
  2666. /*
  2667. ** This function is a no-op unless SQLITE_DEBUG is defined when this module
  2668. ** is compiled. In that case, this function is essentially an assert()
  2669. ** statement used to verify that the contents of the pIter->aFirst[] array
  2670. ** are correct.
  2671. */
  2672. static void fts5AssertMultiIterSetup(Fts5Index *p, Fts5Iter *pIter){
  2673. if( p->rc==SQLITE_OK ){
  2674. Fts5SegIter *pFirst = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
  2675. int i;
  2676. assert( (pFirst->pLeaf==0)==pIter->base.bEof );
  2677. /* Check that pIter->iSwitchRowid is set correctly. */
  2678. for(i=0; i<pIter->nSeg; i++){
  2679. Fts5SegIter *p1 = &pIter->aSeg[i];
  2680. assert( p1==pFirst
  2681. || p1->pLeaf==0
  2682. || fts5BufferCompare(&pFirst->term, &p1->term)
  2683. || p1->iRowid==pIter->iSwitchRowid
  2684. || (p1->iRowid<pIter->iSwitchRowid)==pIter->bRev
  2685. );
  2686. }
  2687. for(i=0; i<pIter->nSeg; i+=2){
  2688. Fts5SegIter *p1 = &pIter->aSeg[i];
  2689. Fts5SegIter *p2 = &pIter->aSeg[i+1];
  2690. Fts5CResult *pRes = &pIter->aFirst[(pIter->nSeg + i) / 2];
  2691. fts5AssertComparisonResult(pIter, p1, p2, pRes);
  2692. }
  2693. for(i=1; i<(pIter->nSeg / 2); i+=2){
  2694. Fts5SegIter *p1 = &pIter->aSeg[ pIter->aFirst[i*2].iFirst ];
  2695. Fts5SegIter *p2 = &pIter->aSeg[ pIter->aFirst[i*2+1].iFirst ];
  2696. Fts5CResult *pRes = &pIter->aFirst[i];
  2697. fts5AssertComparisonResult(pIter, p1, p2, pRes);
  2698. }
  2699. }
  2700. }
  2701. #else
  2702. # define fts5AssertMultiIterSetup(x,y)
  2703. #endif
  2704. /*
  2705. ** Do the comparison necessary to populate pIter->aFirst[iOut].
  2706. **
  2707. ** If the returned value is non-zero, then it is the index of an entry
  2708. ** in the pIter->aSeg[] array that is (a) not at EOF, and (b) pointing
  2709. ** to a key that is a duplicate of another, higher priority,
  2710. ** segment-iterator in the pSeg->aSeg[] array.
  2711. */
  2712. static int fts5MultiIterDoCompare(Fts5Iter *pIter, int iOut){
  2713. int i1; /* Index of left-hand Fts5SegIter */
  2714. int i2; /* Index of right-hand Fts5SegIter */
  2715. int iRes;
  2716. Fts5SegIter *p1; /* Left-hand Fts5SegIter */
  2717. Fts5SegIter *p2; /* Right-hand Fts5SegIter */
  2718. Fts5CResult *pRes = &pIter->aFirst[iOut];
  2719. assert( iOut<pIter->nSeg && iOut>0 );
  2720. assert( pIter->bRev==0 || pIter->bRev==1 );
  2721. if( iOut>=(pIter->nSeg/2) ){
  2722. i1 = (iOut - pIter->nSeg/2) * 2;
  2723. i2 = i1 + 1;
  2724. }else{
  2725. i1 = pIter->aFirst[iOut*2].iFirst;
  2726. i2 = pIter->aFirst[iOut*2+1].iFirst;
  2727. }
  2728. p1 = &pIter->aSeg[i1];
  2729. p2 = &pIter->aSeg[i2];
  2730. pRes->bTermEq = 0;
  2731. if( p1->pLeaf==0 ){ /* If p1 is at EOF */
  2732. iRes = i2;
  2733. }else if( p2->pLeaf==0 ){ /* If p2 is at EOF */
  2734. iRes = i1;
  2735. }else{
  2736. int res = fts5BufferCompare(&p1->term, &p2->term);
  2737. if( res==0 ){
  2738. assert_nc( i2>i1 );
  2739. assert_nc( i2!=0 );
  2740. pRes->bTermEq = 1;
  2741. if( p1->iRowid==p2->iRowid ){
  2742. return i2;
  2743. }
  2744. res = ((p1->iRowid > p2->iRowid)==pIter->bRev) ? -1 : +1;
  2745. }
  2746. assert( res!=0 );
  2747. if( res<0 ){
  2748. iRes = i1;
  2749. }else{
  2750. iRes = i2;
  2751. }
  2752. }
  2753. pRes->iFirst = (u16)iRes;
  2754. return 0;
  2755. }
  2756. /*
  2757. ** Move the seg-iter so that it points to the first rowid on page iLeafPgno.
  2758. ** It is an error if leaf iLeafPgno does not exist. Unless the db is
  2759. ** a 'secure-delete' db, if it contains no rowids then this is also an error.
  2760. */
  2761. static void fts5SegIterGotoPage(
  2762. Fts5Index *p, /* FTS5 backend object */
  2763. Fts5SegIter *pIter, /* Iterator to advance */
  2764. int iLeafPgno
  2765. ){
  2766. assert( iLeafPgno>pIter->iLeafPgno );
  2767. if( iLeafPgno>pIter->pSeg->pgnoLast ){
  2768. p->rc = FTS5_CORRUPT;
  2769. }else{
  2770. fts5DataRelease(pIter->pNextLeaf);
  2771. pIter->pNextLeaf = 0;
  2772. pIter->iLeafPgno = iLeafPgno-1;
  2773. while( p->rc==SQLITE_OK ){
  2774. int iOff;
  2775. fts5SegIterNextPage(p, pIter);
  2776. if( pIter->pLeaf==0 ) break;
  2777. iOff = fts5LeafFirstRowidOff(pIter->pLeaf);
  2778. if( iOff>0 ){
  2779. u8 *a = pIter->pLeaf->p;
  2780. int n = pIter->pLeaf->szLeaf;
  2781. if( iOff<4 || iOff>=n ){
  2782. p->rc = FTS5_CORRUPT;
  2783. }else{
  2784. iOff += fts5GetVarint(&a[iOff], (u64*)&pIter->iRowid);
  2785. pIter->iLeafOffset = iOff;
  2786. fts5SegIterLoadNPos(p, pIter);
  2787. }
  2788. break;
  2789. }
  2790. }
  2791. }
  2792. }
  2793. /*
  2794. ** Advance the iterator passed as the second argument until it is at or
  2795. ** past rowid iFrom. Regardless of the value of iFrom, the iterator is
  2796. ** always advanced at least once.
  2797. */
  2798. static void fts5SegIterNextFrom(
  2799. Fts5Index *p, /* FTS5 backend object */
  2800. Fts5SegIter *pIter, /* Iterator to advance */
  2801. i64 iMatch /* Advance iterator at least this far */
  2802. ){
  2803. int bRev = (pIter->flags & FTS5_SEGITER_REVERSE);
  2804. Fts5DlidxIter *pDlidx = pIter->pDlidx;
  2805. int iLeafPgno = pIter->iLeafPgno;
  2806. int bMove = 1;
  2807. assert( pIter->flags & FTS5_SEGITER_ONETERM );
  2808. assert( pIter->pDlidx );
  2809. assert( pIter->pLeaf );
  2810. if( bRev==0 ){
  2811. while( !fts5DlidxIterEof(p, pDlidx) && iMatch>fts5DlidxIterRowid(pDlidx) ){
  2812. iLeafPgno = fts5DlidxIterPgno(pDlidx);
  2813. fts5DlidxIterNext(p, pDlidx);
  2814. }
  2815. assert_nc( iLeafPgno>=pIter->iLeafPgno || p->rc );
  2816. if( iLeafPgno>pIter->iLeafPgno ){
  2817. fts5SegIterGotoPage(p, pIter, iLeafPgno);
  2818. bMove = 0;
  2819. }
  2820. }else{
  2821. assert( pIter->pNextLeaf==0 );
  2822. assert( iMatch<pIter->iRowid );
  2823. while( !fts5DlidxIterEof(p, pDlidx) && iMatch<fts5DlidxIterRowid(pDlidx) ){
  2824. fts5DlidxIterPrev(p, pDlidx);
  2825. }
  2826. iLeafPgno = fts5DlidxIterPgno(pDlidx);
  2827. assert( fts5DlidxIterEof(p, pDlidx) || iLeafPgno<=pIter->iLeafPgno );
  2828. if( iLeafPgno<pIter->iLeafPgno ){
  2829. pIter->iLeafPgno = iLeafPgno+1;
  2830. fts5SegIterReverseNewPage(p, pIter);
  2831. bMove = 0;
  2832. }
  2833. }
  2834. do{
  2835. if( bMove && p->rc==SQLITE_OK ) pIter->xNext(p, pIter, 0);
  2836. if( pIter->pLeaf==0 ) break;
  2837. if( bRev==0 && pIter->iRowid>=iMatch ) break;
  2838. if( bRev!=0 && pIter->iRowid<=iMatch ) break;
  2839. bMove = 1;
  2840. }while( p->rc==SQLITE_OK );
  2841. }
  2842. /*
  2843. ** Free the iterator object passed as the second argument.
  2844. */
  2845. static void fts5MultiIterFree(Fts5Iter *pIter){
  2846. if( pIter ){
  2847. int i;
  2848. for(i=0; i<pIter->nSeg; i++){
  2849. fts5SegIterClear(&pIter->aSeg[i]);
  2850. }
  2851. fts5BufferFree(&pIter->poslist);
  2852. sqlite3_free(pIter);
  2853. }
  2854. }
  2855. static void fts5MultiIterAdvanced(
  2856. Fts5Index *p, /* FTS5 backend to iterate within */
  2857. Fts5Iter *pIter, /* Iterator to update aFirst[] array for */
  2858. int iChanged, /* Index of sub-iterator just advanced */
  2859. int iMinset /* Minimum entry in aFirst[] to set */
  2860. ){
  2861. int i;
  2862. for(i=(pIter->nSeg+iChanged)/2; i>=iMinset && p->rc==SQLITE_OK; i=i/2){
  2863. int iEq;
  2864. if( (iEq = fts5MultiIterDoCompare(pIter, i)) ){
  2865. Fts5SegIter *pSeg = &pIter->aSeg[iEq];
  2866. assert( p->rc==SQLITE_OK );
  2867. pSeg->xNext(p, pSeg, 0);
  2868. i = pIter->nSeg + iEq;
  2869. }
  2870. }
  2871. }
  2872. /*
  2873. ** Sub-iterator iChanged of iterator pIter has just been advanced. It still
  2874. ** points to the same term though - just a different rowid. This function
  2875. ** attempts to update the contents of the pIter->aFirst[] accordingly.
  2876. ** If it does so successfully, 0 is returned. Otherwise 1.
  2877. **
  2878. ** If non-zero is returned, the caller should call fts5MultiIterAdvanced()
  2879. ** on the iterator instead. That function does the same as this one, except
  2880. ** that it deals with more complicated cases as well.
  2881. */
  2882. static int fts5MultiIterAdvanceRowid(
  2883. Fts5Iter *pIter, /* Iterator to update aFirst[] array for */
  2884. int iChanged, /* Index of sub-iterator just advanced */
  2885. Fts5SegIter **ppFirst
  2886. ){
  2887. Fts5SegIter *pNew = &pIter->aSeg[iChanged];
  2888. if( pNew->iRowid==pIter->iSwitchRowid
  2889. || (pNew->iRowid<pIter->iSwitchRowid)==pIter->bRev
  2890. ){
  2891. int i;
  2892. Fts5SegIter *pOther = &pIter->aSeg[iChanged ^ 0x0001];
  2893. pIter->iSwitchRowid = pIter->bRev ? SMALLEST_INT64 : LARGEST_INT64;
  2894. for(i=(pIter->nSeg+iChanged)/2; 1; i=i/2){
  2895. Fts5CResult *pRes = &pIter->aFirst[i];
  2896. assert( pNew->pLeaf );
  2897. assert( pRes->bTermEq==0 || pOther->pLeaf );
  2898. if( pRes->bTermEq ){
  2899. if( pNew->iRowid==pOther->iRowid ){
  2900. return 1;
  2901. }else if( (pOther->iRowid>pNew->iRowid)==pIter->bRev ){
  2902. pIter->iSwitchRowid = pOther->iRowid;
  2903. pNew = pOther;
  2904. }else if( (pOther->iRowid>pIter->iSwitchRowid)==pIter->bRev ){
  2905. pIter->iSwitchRowid = pOther->iRowid;
  2906. }
  2907. }
  2908. pRes->iFirst = (u16)(pNew - pIter->aSeg);
  2909. if( i==1 ) break;
  2910. pOther = &pIter->aSeg[ pIter->aFirst[i ^ 0x0001].iFirst ];
  2911. }
  2912. }
  2913. *ppFirst = pNew;
  2914. return 0;
  2915. }
  2916. /*
  2917. ** Set the pIter->bEof variable based on the state of the sub-iterators.
  2918. */
  2919. static void fts5MultiIterSetEof(Fts5Iter *pIter){
  2920. Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
  2921. pIter->base.bEof = pSeg->pLeaf==0;
  2922. pIter->iSwitchRowid = pSeg->iRowid;
  2923. }
  2924. /*
  2925. ** The argument to this macro must be an Fts5Data structure containing a
  2926. ** tombstone hash page. This macro returns the key-size of the hash-page.
  2927. */
  2928. #define TOMBSTONE_KEYSIZE(pPg) (pPg->p[0]==4 ? 4 : 8)
  2929. #define TOMBSTONE_NSLOT(pPg) \
  2930. ((pPg->nn > 16) ? ((pPg->nn-8) / TOMBSTONE_KEYSIZE(pPg)) : 1)
  2931. /*
  2932. ** Query a single tombstone hash table for rowid iRowid. Return true if
  2933. ** it is found or false otherwise. The tombstone hash table is one of
  2934. ** nHashTable tables.
  2935. */
  2936. static int fts5IndexTombstoneQuery(
  2937. Fts5Data *pHash, /* Hash table page to query */
  2938. int nHashTable, /* Number of pages attached to segment */
  2939. u64 iRowid /* Rowid to query hash for */
  2940. ){
  2941. const int szKey = TOMBSTONE_KEYSIZE(pHash);
  2942. const int nSlot = TOMBSTONE_NSLOT(pHash);
  2943. int iSlot = (iRowid / nHashTable) % nSlot;
  2944. int nCollide = nSlot;
  2945. if( iRowid==0 ){
  2946. return pHash->p[1];
  2947. }else if( szKey==4 ){
  2948. u32 *aSlot = (u32*)&pHash->p[8];
  2949. while( aSlot[iSlot] ){
  2950. if( fts5GetU32((u8*)&aSlot[iSlot])==iRowid ) return 1;
  2951. if( nCollide--==0 ) break;
  2952. iSlot = (iSlot+1)%nSlot;
  2953. }
  2954. }else{
  2955. u64 *aSlot = (u64*)&pHash->p[8];
  2956. while( aSlot[iSlot] ){
  2957. if( fts5GetU64((u8*)&aSlot[iSlot])==iRowid ) return 1;
  2958. if( nCollide--==0 ) break;
  2959. iSlot = (iSlot+1)%nSlot;
  2960. }
  2961. }
  2962. return 0;
  2963. }
  2964. /*
  2965. ** Return true if the iterator passed as the only argument points
  2966. ** to an segment entry for which there is a tombstone. Return false
  2967. ** if there is no tombstone or if the iterator is already at EOF.
  2968. */
  2969. static int fts5MultiIterIsDeleted(Fts5Iter *pIter){
  2970. int iFirst = pIter->aFirst[1].iFirst;
  2971. Fts5SegIter *pSeg = &pIter->aSeg[iFirst];
  2972. Fts5TombstoneArray *pArray = pSeg->pTombArray;
  2973. if( pSeg->pLeaf && pArray ){
  2974. /* Figure out which page the rowid might be present on. */
  2975. int iPg = ((u64)pSeg->iRowid) % pArray->nTombstone;
  2976. assert( iPg>=0 );
  2977. /* If tombstone hash page iPg has not yet been loaded from the
  2978. ** database, load it now. */
  2979. if( pArray->apTombstone[iPg]==0 ){
  2980. pArray->apTombstone[iPg] = fts5DataRead(pIter->pIndex,
  2981. FTS5_TOMBSTONE_ROWID(pSeg->pSeg->iSegid, iPg)
  2982. );
  2983. if( pArray->apTombstone[iPg]==0 ) return 0;
  2984. }
  2985. return fts5IndexTombstoneQuery(
  2986. pArray->apTombstone[iPg],
  2987. pArray->nTombstone,
  2988. pSeg->iRowid
  2989. );
  2990. }
  2991. return 0;
  2992. }
  2993. /*
  2994. ** Move the iterator to the next entry.
  2995. **
  2996. ** If an error occurs, an error code is left in Fts5Index.rc. It is not
  2997. ** considered an error if the iterator reaches EOF, or if it is already at
  2998. ** EOF when this function is called.
  2999. */
  3000. static void fts5MultiIterNext(
  3001. Fts5Index *p,
  3002. Fts5Iter *pIter,
  3003. int bFrom, /* True if argument iFrom is valid */
  3004. i64 iFrom /* Advance at least as far as this */
  3005. ){
  3006. int bUseFrom = bFrom;
  3007. assert( pIter->base.bEof==0 );
  3008. while( p->rc==SQLITE_OK ){
  3009. int iFirst = pIter->aFirst[1].iFirst;
  3010. int bNewTerm = 0;
  3011. Fts5SegIter *pSeg = &pIter->aSeg[iFirst];
  3012. assert( p->rc==SQLITE_OK );
  3013. if( bUseFrom && pSeg->pDlidx ){
  3014. fts5SegIterNextFrom(p, pSeg, iFrom);
  3015. }else{
  3016. pSeg->xNext(p, pSeg, &bNewTerm);
  3017. }
  3018. if( pSeg->pLeaf==0 || bNewTerm
  3019. || fts5MultiIterAdvanceRowid(pIter, iFirst, &pSeg)
  3020. ){
  3021. fts5MultiIterAdvanced(p, pIter, iFirst, 1);
  3022. fts5MultiIterSetEof(pIter);
  3023. pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst];
  3024. if( pSeg->pLeaf==0 ) return;
  3025. }
  3026. fts5AssertMultiIterSetup(p, pIter);
  3027. assert( pSeg==&pIter->aSeg[pIter->aFirst[1].iFirst] && pSeg->pLeaf );
  3028. if( (pIter->bSkipEmpty==0 || pSeg->nPos)
  3029. && 0==fts5MultiIterIsDeleted(pIter)
  3030. ){
  3031. pIter->xSetOutputs(pIter, pSeg);
  3032. return;
  3033. }
  3034. bUseFrom = 0;
  3035. }
  3036. }
  3037. static void fts5MultiIterNext2(
  3038. Fts5Index *p,
  3039. Fts5Iter *pIter,
  3040. int *pbNewTerm /* OUT: True if *might* be new term */
  3041. ){
  3042. assert( pIter->bSkipEmpty );
  3043. if( p->rc==SQLITE_OK ){
  3044. *pbNewTerm = 0;
  3045. do{
  3046. int iFirst = pIter->aFirst[1].iFirst;
  3047. Fts5SegIter *pSeg = &pIter->aSeg[iFirst];
  3048. int bNewTerm = 0;
  3049. assert( p->rc==SQLITE_OK );
  3050. pSeg->xNext(p, pSeg, &bNewTerm);
  3051. if( pSeg->pLeaf==0 || bNewTerm
  3052. || fts5MultiIterAdvanceRowid(pIter, iFirst, &pSeg)
  3053. ){
  3054. fts5MultiIterAdvanced(p, pIter, iFirst, 1);
  3055. fts5MultiIterSetEof(pIter);
  3056. *pbNewTerm = 1;
  3057. }
  3058. fts5AssertMultiIterSetup(p, pIter);
  3059. }while( (fts5MultiIterIsEmpty(p, pIter) || fts5MultiIterIsDeleted(pIter))
  3060. && (p->rc==SQLITE_OK)
  3061. );
  3062. }
  3063. }
  3064. static void fts5IterSetOutputs_Noop(Fts5Iter *pUnused1, Fts5SegIter *pUnused2){
  3065. UNUSED_PARAM2(pUnused1, pUnused2);
  3066. }
  3067. static Fts5Iter *fts5MultiIterAlloc(
  3068. Fts5Index *p, /* FTS5 backend to iterate within */
  3069. int nSeg
  3070. ){
  3071. Fts5Iter *pNew;
  3072. i64 nSlot; /* Power of two >= nSeg */
  3073. for(nSlot=2; nSlot<nSeg; nSlot=nSlot*2);
  3074. pNew = fts5IdxMalloc(p,
  3075. sizeof(Fts5Iter) + /* pNew */
  3076. sizeof(Fts5SegIter) * (nSlot-1) + /* pNew->aSeg[] */
  3077. sizeof(Fts5CResult) * nSlot /* pNew->aFirst[] */
  3078. );
  3079. if( pNew ){
  3080. pNew->nSeg = nSlot;
  3081. pNew->aFirst = (Fts5CResult*)&pNew->aSeg[nSlot];
  3082. pNew->pIndex = p;
  3083. pNew->xSetOutputs = fts5IterSetOutputs_Noop;
  3084. }
  3085. return pNew;
  3086. }
  3087. static void fts5PoslistCallback(
  3088. Fts5Index *pUnused,
  3089. void *pContext,
  3090. const u8 *pChunk, int nChunk
  3091. ){
  3092. UNUSED_PARAM(pUnused);
  3093. assert_nc( nChunk>=0 );
  3094. if( nChunk>0 ){
  3095. fts5BufferSafeAppendBlob((Fts5Buffer*)pContext, pChunk, nChunk);
  3096. }
  3097. }
  3098. typedef struct PoslistCallbackCtx PoslistCallbackCtx;
  3099. struct PoslistCallbackCtx {
  3100. Fts5Buffer *pBuf; /* Append to this buffer */
  3101. Fts5Colset *pColset; /* Restrict matches to this column */
  3102. int eState; /* See above */
  3103. };
  3104. typedef struct PoslistOffsetsCtx PoslistOffsetsCtx;
  3105. struct PoslistOffsetsCtx {
  3106. Fts5Buffer *pBuf; /* Append to this buffer */
  3107. Fts5Colset *pColset; /* Restrict matches to this column */
  3108. int iRead;
  3109. int iWrite;
  3110. };
  3111. /*
  3112. ** TODO: Make this more efficient!
  3113. */
  3114. static int fts5IndexColsetTest(Fts5Colset *pColset, int iCol){
  3115. int i;
  3116. for(i=0; i<pColset->nCol; i++){
  3117. if( pColset->aiCol[i]==iCol ) return 1;
  3118. }
  3119. return 0;
  3120. }
  3121. static void fts5PoslistOffsetsCallback(
  3122. Fts5Index *pUnused,
  3123. void *pContext,
  3124. const u8 *pChunk, int nChunk
  3125. ){
  3126. PoslistOffsetsCtx *pCtx = (PoslistOffsetsCtx*)pContext;
  3127. UNUSED_PARAM(pUnused);
  3128. assert_nc( nChunk>=0 );
  3129. if( nChunk>0 ){
  3130. int i = 0;
  3131. while( i<nChunk ){
  3132. int iVal;
  3133. i += fts5GetVarint32(&pChunk[i], iVal);
  3134. iVal += pCtx->iRead - 2;
  3135. pCtx->iRead = iVal;
  3136. if( fts5IndexColsetTest(pCtx->pColset, iVal) ){
  3137. fts5BufferSafeAppendVarint(pCtx->pBuf, iVal + 2 - pCtx->iWrite);
  3138. pCtx->iWrite = iVal;
  3139. }
  3140. }
  3141. }
  3142. }
  3143. static void fts5PoslistFilterCallback(
  3144. Fts5Index *pUnused,
  3145. void *pContext,
  3146. const u8 *pChunk, int nChunk
  3147. ){
  3148. PoslistCallbackCtx *pCtx = (PoslistCallbackCtx*)pContext;
  3149. UNUSED_PARAM(pUnused);
  3150. assert_nc( nChunk>=0 );
  3151. if( nChunk>0 ){
  3152. /* Search through to find the first varint with value 1. This is the
  3153. ** start of the next columns hits. */
  3154. int i = 0;
  3155. int iStart = 0;
  3156. if( pCtx->eState==2 ){
  3157. int iCol;
  3158. fts5FastGetVarint32(pChunk, i, iCol);
  3159. if( fts5IndexColsetTest(pCtx->pColset, iCol) ){
  3160. pCtx->eState = 1;
  3161. fts5BufferSafeAppendVarint(pCtx->pBuf, 1);
  3162. }else{
  3163. pCtx->eState = 0;
  3164. }
  3165. }
  3166. do {
  3167. while( i<nChunk && pChunk[i]!=0x01 ){
  3168. while( pChunk[i] & 0x80 ) i++;
  3169. i++;
  3170. }
  3171. if( pCtx->eState ){
  3172. fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart);
  3173. }
  3174. if( i<nChunk ){
  3175. int iCol;
  3176. iStart = i;
  3177. i++;
  3178. if( i>=nChunk ){
  3179. pCtx->eState = 2;
  3180. }else{
  3181. fts5FastGetVarint32(pChunk, i, iCol);
  3182. pCtx->eState = fts5IndexColsetTest(pCtx->pColset, iCol);
  3183. if( pCtx->eState ){
  3184. fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart);
  3185. iStart = i;
  3186. }
  3187. }
  3188. }
  3189. }while( i<nChunk );
  3190. }
  3191. }
  3192. static void fts5ChunkIterate(
  3193. Fts5Index *p, /* Index object */
  3194. Fts5SegIter *pSeg, /* Poslist of this iterator */
  3195. void *pCtx, /* Context pointer for xChunk callback */
  3196. void (*xChunk)(Fts5Index*, void*, const u8*, int)
  3197. ){
  3198. int nRem = pSeg->nPos; /* Number of bytes still to come */
  3199. Fts5Data *pData = 0;
  3200. u8 *pChunk = &pSeg->pLeaf->p[pSeg->iLeafOffset];
  3201. int nChunk = MIN(nRem, pSeg->pLeaf->szLeaf - pSeg->iLeafOffset);
  3202. int pgno = pSeg->iLeafPgno;
  3203. int pgnoSave = 0;
  3204. /* This function does not work with detail=none databases. */
  3205. assert( p->pConfig->eDetail!=FTS5_DETAIL_NONE );
  3206. if( (pSeg->flags & FTS5_SEGITER_REVERSE)==0 ){
  3207. pgnoSave = pgno+1;
  3208. }
  3209. while( 1 ){
  3210. xChunk(p, pCtx, pChunk, nChunk);
  3211. nRem -= nChunk;
  3212. fts5DataRelease(pData);
  3213. if( nRem<=0 ){
  3214. break;
  3215. }else if( pSeg->pSeg==0 ){
  3216. p->rc = FTS5_CORRUPT;
  3217. return;
  3218. }else{
  3219. pgno++;
  3220. pData = fts5LeafRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno));
  3221. if( pData==0 ) break;
  3222. pChunk = &pData->p[4];
  3223. nChunk = MIN(nRem, pData->szLeaf - 4);
  3224. if( pgno==pgnoSave ){
  3225. assert( pSeg->pNextLeaf==0 );
  3226. pSeg->pNextLeaf = pData;
  3227. pData = 0;
  3228. }
  3229. }
  3230. }
  3231. }
  3232. /*
  3233. ** Iterator pIter currently points to a valid entry (not EOF). This
  3234. ** function appends the position list data for the current entry to
  3235. ** buffer pBuf. It does not make a copy of the position-list size
  3236. ** field.
  3237. */
  3238. static void fts5SegiterPoslist(
  3239. Fts5Index *p,
  3240. Fts5SegIter *pSeg,
  3241. Fts5Colset *pColset,
  3242. Fts5Buffer *pBuf
  3243. ){
  3244. assert( pBuf!=0 );
  3245. assert( pSeg!=0 );
  3246. if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos+FTS5_DATA_ZERO_PADDING) ){
  3247. assert( pBuf->p!=0 );
  3248. assert( pBuf->nSpace >= pBuf->n+pSeg->nPos+FTS5_DATA_ZERO_PADDING );
  3249. memset(&pBuf->p[pBuf->n+pSeg->nPos], 0, FTS5_DATA_ZERO_PADDING);
  3250. if( pColset==0 ){
  3251. fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback);
  3252. }else{
  3253. if( p->pConfig->eDetail==FTS5_DETAIL_FULL ){
  3254. PoslistCallbackCtx sCtx;
  3255. sCtx.pBuf = pBuf;
  3256. sCtx.pColset = pColset;
  3257. sCtx.eState = fts5IndexColsetTest(pColset, 0);
  3258. assert( sCtx.eState==0 || sCtx.eState==1 );
  3259. fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback);
  3260. }else{
  3261. PoslistOffsetsCtx sCtx;
  3262. memset(&sCtx, 0, sizeof(sCtx));
  3263. sCtx.pBuf = pBuf;
  3264. sCtx.pColset = pColset;
  3265. fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistOffsetsCallback);
  3266. }
  3267. }
  3268. }
  3269. }
  3270. /*
  3271. ** Parameter pPos points to a buffer containing a position list, size nPos.
  3272. ** This function filters it according to pColset (which must be non-NULL)
  3273. ** and sets pIter->base.pData/nData to point to the new position list.
  3274. ** If memory is required for the new position list, use buffer pIter->poslist.
  3275. ** Or, if the new position list is a contiguous subset of the input, set
  3276. ** pIter->base.pData/nData to point directly to it.
  3277. **
  3278. ** This function is a no-op if *pRc is other than SQLITE_OK when it is
  3279. ** called. If an OOM error is encountered, *pRc is set to SQLITE_NOMEM
  3280. ** before returning.
  3281. */
  3282. static void fts5IndexExtractColset(
  3283. int *pRc,
  3284. Fts5Colset *pColset, /* Colset to filter on */
  3285. const u8 *pPos, int nPos, /* Position list */
  3286. Fts5Iter *pIter
  3287. ){
  3288. if( *pRc==SQLITE_OK ){
  3289. const u8 *p = pPos;
  3290. const u8 *aCopy = p;
  3291. const u8 *pEnd = &p[nPos]; /* One byte past end of position list */
  3292. int i = 0;
  3293. int iCurrent = 0;
  3294. if( pColset->nCol>1 && sqlite3Fts5BufferSize(pRc, &pIter->poslist, nPos) ){
  3295. return;
  3296. }
  3297. while( 1 ){
  3298. while( pColset->aiCol[i]<iCurrent ){
  3299. i++;
  3300. if( i==pColset->nCol ){
  3301. pIter->base.pData = pIter->poslist.p;
  3302. pIter->base.nData = pIter->poslist.n;
  3303. return;
  3304. }
  3305. }
  3306. /* Advance pointer p until it points to pEnd or an 0x01 byte that is
  3307. ** not part of a varint */
  3308. while( p<pEnd && *p!=0x01 ){
  3309. while( *p++ & 0x80 );
  3310. }
  3311. if( pColset->aiCol[i]==iCurrent ){
  3312. if( pColset->nCol==1 ){
  3313. pIter->base.pData = aCopy;
  3314. pIter->base.nData = p-aCopy;
  3315. return;
  3316. }
  3317. fts5BufferSafeAppendBlob(&pIter->poslist, aCopy, p-aCopy);
  3318. }
  3319. if( p>=pEnd ){
  3320. pIter->base.pData = pIter->poslist.p;
  3321. pIter->base.nData = pIter->poslist.n;
  3322. return;
  3323. }
  3324. aCopy = p++;
  3325. iCurrent = *p++;
  3326. if( iCurrent & 0x80 ){
  3327. p--;
  3328. p += fts5GetVarint32(p, iCurrent);
  3329. }
  3330. }
  3331. }
  3332. }
  3333. /*
  3334. ** xSetOutputs callback used by detail=none tables.
  3335. */
  3336. static void fts5IterSetOutputs_None(Fts5Iter *pIter, Fts5SegIter *pSeg){
  3337. assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_NONE );
  3338. pIter->base.iRowid = pSeg->iRowid;
  3339. pIter->base.nData = pSeg->nPos;
  3340. }
  3341. /*
  3342. ** xSetOutputs callback used by detail=full and detail=col tables when no
  3343. ** column filters are specified.
  3344. */
  3345. static void fts5IterSetOutputs_Nocolset(Fts5Iter *pIter, Fts5SegIter *pSeg){
  3346. pIter->base.iRowid = pSeg->iRowid;
  3347. pIter->base.nData = pSeg->nPos;
  3348. assert( pIter->pIndex->pConfig->eDetail!=FTS5_DETAIL_NONE );
  3349. assert( pIter->pColset==0 );
  3350. if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){
  3351. /* All data is stored on the current page. Populate the output
  3352. ** variables to point into the body of the page object. */
  3353. pIter->base.pData = &pSeg->pLeaf->p[pSeg->iLeafOffset];
  3354. }else{
  3355. /* The data is distributed over two or more pages. Copy it into the
  3356. ** Fts5Iter.poslist buffer and then set the output pointer to point
  3357. ** to this buffer. */
  3358. fts5BufferZero(&pIter->poslist);
  3359. fts5SegiterPoslist(pIter->pIndex, pSeg, 0, &pIter->poslist);
  3360. pIter->base.pData = pIter->poslist.p;
  3361. }
  3362. }
  3363. /*
  3364. ** xSetOutputs callback used when the Fts5Colset object has nCol==0 (match
  3365. ** against no columns at all).
  3366. */
  3367. static void fts5IterSetOutputs_ZeroColset(Fts5Iter *pIter, Fts5SegIter *pSeg){
  3368. UNUSED_PARAM(pSeg);
  3369. pIter->base.nData = 0;
  3370. }
  3371. /*
  3372. ** xSetOutputs callback used by detail=col when there is a column filter
  3373. ** and there are 100 or more columns. Also called as a fallback from
  3374. ** fts5IterSetOutputs_Col100 if the column-list spans more than one page.
  3375. */
  3376. static void fts5IterSetOutputs_Col(Fts5Iter *pIter, Fts5SegIter *pSeg){
  3377. fts5BufferZero(&pIter->poslist);
  3378. fts5SegiterPoslist(pIter->pIndex, pSeg, pIter->pColset, &pIter->poslist);
  3379. pIter->base.iRowid = pSeg->iRowid;
  3380. pIter->base.pData = pIter->poslist.p;
  3381. pIter->base.nData = pIter->poslist.n;
  3382. }
  3383. /*
  3384. ** xSetOutputs callback used when:
  3385. **
  3386. ** * detail=col,
  3387. ** * there is a column filter, and
  3388. ** * the table contains 100 or fewer columns.
  3389. **
  3390. ** The last point is to ensure all column numbers are stored as
  3391. ** single-byte varints.
  3392. */
  3393. static void fts5IterSetOutputs_Col100(Fts5Iter *pIter, Fts5SegIter *pSeg){
  3394. assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS );
  3395. assert( pIter->pColset );
  3396. if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf ){
  3397. fts5IterSetOutputs_Col(pIter, pSeg);
  3398. }else{
  3399. u8 *a = (u8*)&pSeg->pLeaf->p[pSeg->iLeafOffset];
  3400. u8 *pEnd = (u8*)&a[pSeg->nPos];
  3401. int iPrev = 0;
  3402. int *aiCol = pIter->pColset->aiCol;
  3403. int *aiColEnd = &aiCol[pIter->pColset->nCol];
  3404. u8 *aOut = pIter->poslist.p;
  3405. int iPrevOut = 0;
  3406. pIter->base.iRowid = pSeg->iRowid;
  3407. while( a<pEnd ){
  3408. iPrev += (int)a++[0] - 2;
  3409. while( *aiCol<iPrev ){
  3410. aiCol++;
  3411. if( aiCol==aiColEnd ) goto setoutputs_col_out;
  3412. }
  3413. if( *aiCol==iPrev ){
  3414. *aOut++ = (u8)((iPrev - iPrevOut) + 2);
  3415. iPrevOut = iPrev;
  3416. }
  3417. }
  3418. setoutputs_col_out:
  3419. pIter->base.pData = pIter->poslist.p;
  3420. pIter->base.nData = aOut - pIter->poslist.p;
  3421. }
  3422. }
  3423. /*
  3424. ** xSetOutputs callback used by detail=full when there is a column filter.
  3425. */
  3426. static void fts5IterSetOutputs_Full(Fts5Iter *pIter, Fts5SegIter *pSeg){
  3427. Fts5Colset *pColset = pIter->pColset;
  3428. pIter->base.iRowid = pSeg->iRowid;
  3429. assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_FULL );
  3430. assert( pColset );
  3431. if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){
  3432. /* All data is stored on the current page. Populate the output
  3433. ** variables to point into the body of the page object. */
  3434. const u8 *a = &pSeg->pLeaf->p[pSeg->iLeafOffset];
  3435. int *pRc = &pIter->pIndex->rc;
  3436. fts5BufferZero(&pIter->poslist);
  3437. fts5IndexExtractColset(pRc, pColset, a, pSeg->nPos, pIter);
  3438. }else{
  3439. /* The data is distributed over two or more pages. Copy it into the
  3440. ** Fts5Iter.poslist buffer and then set the output pointer to point
  3441. ** to this buffer. */
  3442. fts5BufferZero(&pIter->poslist);
  3443. fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist);
  3444. pIter->base.pData = pIter->poslist.p;
  3445. pIter->base.nData = pIter->poslist.n;
  3446. }
  3447. }
  3448. static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){
  3449. assert( pIter!=0 || (*pRc)!=SQLITE_OK );
  3450. if( *pRc==SQLITE_OK ){
  3451. Fts5Config *pConfig = pIter->pIndex->pConfig;
  3452. if( pConfig->eDetail==FTS5_DETAIL_NONE ){
  3453. pIter->xSetOutputs = fts5IterSetOutputs_None;
  3454. }
  3455. else if( pIter->pColset==0 ){
  3456. pIter->xSetOutputs = fts5IterSetOutputs_Nocolset;
  3457. }
  3458. else if( pIter->pColset->nCol==0 ){
  3459. pIter->xSetOutputs = fts5IterSetOutputs_ZeroColset;
  3460. }
  3461. else if( pConfig->eDetail==FTS5_DETAIL_FULL ){
  3462. pIter->xSetOutputs = fts5IterSetOutputs_Full;
  3463. }
  3464. else{
  3465. assert( pConfig->eDetail==FTS5_DETAIL_COLUMNS );
  3466. if( pConfig->nCol<=100 ){
  3467. pIter->xSetOutputs = fts5IterSetOutputs_Col100;
  3468. sqlite3Fts5BufferSize(pRc, &pIter->poslist, pConfig->nCol);
  3469. }else{
  3470. pIter->xSetOutputs = fts5IterSetOutputs_Col;
  3471. }
  3472. }
  3473. }
  3474. }
  3475. /*
  3476. ** All the component segment-iterators of pIter have been set up. This
  3477. ** functions finishes setup for iterator pIter itself.
  3478. */
  3479. static void fts5MultiIterFinishSetup(Fts5Index *p, Fts5Iter *pIter){
  3480. int iIter;
  3481. for(iIter=pIter->nSeg-1; iIter>0; iIter--){
  3482. int iEq;
  3483. if( (iEq = fts5MultiIterDoCompare(pIter, iIter)) ){
  3484. Fts5SegIter *pSeg = &pIter->aSeg[iEq];
  3485. if( p->rc==SQLITE_OK ) pSeg->xNext(p, pSeg, 0);
  3486. fts5MultiIterAdvanced(p, pIter, iEq, iIter);
  3487. }
  3488. }
  3489. fts5MultiIterSetEof(pIter);
  3490. fts5AssertMultiIterSetup(p, pIter);
  3491. if( (pIter->bSkipEmpty && fts5MultiIterIsEmpty(p, pIter))
  3492. || fts5MultiIterIsDeleted(pIter)
  3493. ){
  3494. fts5MultiIterNext(p, pIter, 0, 0);
  3495. }else if( pIter->base.bEof==0 ){
  3496. Fts5SegIter *pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst];
  3497. pIter->xSetOutputs(pIter, pSeg);
  3498. }
  3499. }
  3500. /*
  3501. ** Allocate a new Fts5Iter object.
  3502. **
  3503. ** The new object will be used to iterate through data in structure pStruct.
  3504. ** If iLevel is -ve, then all data in all segments is merged. Or, if iLevel
  3505. ** is zero or greater, data from the first nSegment segments on level iLevel
  3506. ** is merged.
  3507. **
  3508. ** The iterator initially points to the first term/rowid entry in the
  3509. ** iterated data.
  3510. */
  3511. static void fts5MultiIterNew(
  3512. Fts5Index *p, /* FTS5 backend to iterate within */
  3513. Fts5Structure *pStruct, /* Structure of specific index */
  3514. int flags, /* FTS5INDEX_QUERY_XXX flags */
  3515. Fts5Colset *pColset, /* Colset to filter on (or NULL) */
  3516. const u8 *pTerm, int nTerm, /* Term to seek to (or NULL/0) */
  3517. int iLevel, /* Level to iterate (-1 for all) */
  3518. int nSegment, /* Number of segments to merge (iLevel>=0) */
  3519. Fts5Iter **ppOut /* New object */
  3520. ){
  3521. int nSeg = 0; /* Number of segment-iters in use */
  3522. int iIter = 0; /* */
  3523. int iSeg; /* Used to iterate through segments */
  3524. Fts5StructureLevel *pLvl;
  3525. Fts5Iter *pNew;
  3526. assert( (pTerm==0 && nTerm==0) || iLevel<0 );
  3527. /* Allocate space for the new multi-seg-iterator. */
  3528. if( p->rc==SQLITE_OK ){
  3529. if( iLevel<0 ){
  3530. assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) );
  3531. nSeg = pStruct->nSegment;
  3532. nSeg += (p->pHash && 0==(flags & FTS5INDEX_QUERY_SKIPHASH));
  3533. }else{
  3534. nSeg = MIN(pStruct->aLevel[iLevel].nSeg, nSegment);
  3535. }
  3536. }
  3537. *ppOut = pNew = fts5MultiIterAlloc(p, nSeg);
  3538. if( pNew==0 ){
  3539. assert( p->rc!=SQLITE_OK );
  3540. goto fts5MultiIterNew_post_check;
  3541. }
  3542. pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC));
  3543. pNew->bSkipEmpty = (0!=(flags & FTS5INDEX_QUERY_SKIPEMPTY));
  3544. pNew->pColset = pColset;
  3545. if( (flags & FTS5INDEX_QUERY_NOOUTPUT)==0 ){
  3546. fts5IterSetOutputCb(&p->rc, pNew);
  3547. }
  3548. /* Initialize each of the component segment iterators. */
  3549. if( p->rc==SQLITE_OK ){
  3550. if( iLevel<0 ){
  3551. Fts5StructureLevel *pEnd = &pStruct->aLevel[pStruct->nLevel];
  3552. if( p->pHash && 0==(flags & FTS5INDEX_QUERY_SKIPHASH) ){
  3553. /* Add a segment iterator for the current contents of the hash table. */
  3554. Fts5SegIter *pIter = &pNew->aSeg[iIter++];
  3555. fts5SegIterHashInit(p, pTerm, nTerm, flags, pIter);
  3556. }
  3557. for(pLvl=&pStruct->aLevel[0]; pLvl<pEnd; pLvl++){
  3558. for(iSeg=pLvl->nSeg-1; iSeg>=0; iSeg--){
  3559. Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg];
  3560. Fts5SegIter *pIter = &pNew->aSeg[iIter++];
  3561. if( pTerm==0 ){
  3562. fts5SegIterInit(p, pSeg, pIter);
  3563. }else{
  3564. fts5SegIterSeekInit(p, pTerm, nTerm, flags, pSeg, pIter);
  3565. }
  3566. }
  3567. }
  3568. }else{
  3569. pLvl = &pStruct->aLevel[iLevel];
  3570. for(iSeg=nSeg-1; iSeg>=0; iSeg--){
  3571. fts5SegIterInit(p, &pLvl->aSeg[iSeg], &pNew->aSeg[iIter++]);
  3572. }
  3573. }
  3574. assert( iIter==nSeg );
  3575. }
  3576. /* If the above was successful, each component iterator now points
  3577. ** to the first entry in its segment. In this case initialize the
  3578. ** aFirst[] array. Or, if an error has occurred, free the iterator
  3579. ** object and set the output variable to NULL. */
  3580. if( p->rc==SQLITE_OK ){
  3581. fts5MultiIterFinishSetup(p, pNew);
  3582. }else{
  3583. fts5MultiIterFree(pNew);
  3584. *ppOut = 0;
  3585. }
  3586. fts5MultiIterNew_post_check:
  3587. assert( (*ppOut)!=0 || p->rc!=SQLITE_OK );
  3588. return;
  3589. }
  3590. /*
  3591. ** Create an Fts5Iter that iterates through the doclist provided
  3592. ** as the second argument.
  3593. */
  3594. static void fts5MultiIterNew2(
  3595. Fts5Index *p, /* FTS5 backend to iterate within */
  3596. Fts5Data *pData, /* Doclist to iterate through */
  3597. int bDesc, /* True for descending rowid order */
  3598. Fts5Iter **ppOut /* New object */
  3599. ){
  3600. Fts5Iter *pNew;
  3601. pNew = fts5MultiIterAlloc(p, 2);
  3602. if( pNew ){
  3603. Fts5SegIter *pIter = &pNew->aSeg[1];
  3604. pIter->flags = FTS5_SEGITER_ONETERM;
  3605. if( pData->szLeaf>0 ){
  3606. pIter->pLeaf = pData;
  3607. pIter->iLeafOffset = fts5GetVarint(pData->p, (u64*)&pIter->iRowid);
  3608. pIter->iEndofDoclist = pData->nn;
  3609. pNew->aFirst[1].iFirst = 1;
  3610. if( bDesc ){
  3611. pNew->bRev = 1;
  3612. pIter->flags |= FTS5_SEGITER_REVERSE;
  3613. fts5SegIterReverseInitPage(p, pIter);
  3614. }else{
  3615. fts5SegIterLoadNPos(p, pIter);
  3616. }
  3617. pData = 0;
  3618. }else{
  3619. pNew->base.bEof = 1;
  3620. }
  3621. fts5SegIterSetNext(p, pIter);
  3622. *ppOut = pNew;
  3623. }
  3624. fts5DataRelease(pData);
  3625. }
  3626. /*
  3627. ** Return true if the iterator is at EOF or if an error has occurred.
  3628. ** False otherwise.
  3629. */
  3630. static int fts5MultiIterEof(Fts5Index *p, Fts5Iter *pIter){
  3631. assert( pIter!=0 || p->rc!=SQLITE_OK );
  3632. assert( p->rc!=SQLITE_OK
  3633. || (pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf==0)==pIter->base.bEof
  3634. );
  3635. return (p->rc || pIter->base.bEof);
  3636. }
  3637. /*
  3638. ** Return the rowid of the entry that the iterator currently points
  3639. ** to. If the iterator points to EOF when this function is called the
  3640. ** results are undefined.
  3641. */
  3642. static i64 fts5MultiIterRowid(Fts5Iter *pIter){
  3643. assert( pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf );
  3644. return pIter->aSeg[ pIter->aFirst[1].iFirst ].iRowid;
  3645. }
  3646. /*
  3647. ** Move the iterator to the next entry at or following iMatch.
  3648. */
  3649. static void fts5MultiIterNextFrom(
  3650. Fts5Index *p,
  3651. Fts5Iter *pIter,
  3652. i64 iMatch
  3653. ){
  3654. while( 1 ){
  3655. i64 iRowid;
  3656. fts5MultiIterNext(p, pIter, 1, iMatch);
  3657. if( fts5MultiIterEof(p, pIter) ) break;
  3658. iRowid = fts5MultiIterRowid(pIter);
  3659. if( pIter->bRev==0 && iRowid>=iMatch ) break;
  3660. if( pIter->bRev!=0 && iRowid<=iMatch ) break;
  3661. }
  3662. }
  3663. /*
  3664. ** Return a pointer to a buffer containing the term associated with the
  3665. ** entry that the iterator currently points to.
  3666. */
  3667. static const u8 *fts5MultiIterTerm(Fts5Iter *pIter, int *pn){
  3668. Fts5SegIter *p = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
  3669. *pn = p->term.n;
  3670. return p->term.p;
  3671. }
  3672. /*
  3673. ** Allocate a new segment-id for the structure pStruct. The new segment
  3674. ** id must be between 1 and 65335 inclusive, and must not be used by
  3675. ** any currently existing segment. If a free segment id cannot be found,
  3676. ** SQLITE_FULL is returned.
  3677. **
  3678. ** If an error has already occurred, this function is a no-op. 0 is
  3679. ** returned in this case.
  3680. */
  3681. static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){
  3682. int iSegid = 0;
  3683. if( p->rc==SQLITE_OK ){
  3684. if( pStruct->nSegment>=FTS5_MAX_SEGMENT ){
  3685. p->rc = SQLITE_FULL;
  3686. }else{
  3687. /* FTS5_MAX_SEGMENT is currently defined as 2000. So the following
  3688. ** array is 63 elements, or 252 bytes, in size. */
  3689. u32 aUsed[(FTS5_MAX_SEGMENT+31) / 32];
  3690. int iLvl, iSeg;
  3691. int i;
  3692. u32 mask;
  3693. memset(aUsed, 0, sizeof(aUsed));
  3694. for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
  3695. for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
  3696. int iId = pStruct->aLevel[iLvl].aSeg[iSeg].iSegid;
  3697. if( iId<=FTS5_MAX_SEGMENT && iId>0 ){
  3698. aUsed[(iId-1) / 32] |= (u32)1 << ((iId-1) % 32);
  3699. }
  3700. }
  3701. }
  3702. for(i=0; aUsed[i]==0xFFFFFFFF; i++);
  3703. mask = aUsed[i];
  3704. for(iSegid=0; mask & ((u32)1 << iSegid); iSegid++);
  3705. iSegid += 1 + i*32;
  3706. #ifdef SQLITE_DEBUG
  3707. for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
  3708. for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
  3709. assert_nc( iSegid!=pStruct->aLevel[iLvl].aSeg[iSeg].iSegid );
  3710. }
  3711. }
  3712. assert_nc( iSegid>0 && iSegid<=FTS5_MAX_SEGMENT );
  3713. {
  3714. sqlite3_stmt *pIdxSelect = fts5IdxSelectStmt(p);
  3715. if( p->rc==SQLITE_OK ){
  3716. u8 aBlob[2] = {0xff, 0xff};
  3717. sqlite3_bind_int(pIdxSelect, 1, iSegid);
  3718. sqlite3_bind_blob(pIdxSelect, 2, aBlob, 2, SQLITE_STATIC);
  3719. assert_nc( sqlite3_step(pIdxSelect)!=SQLITE_ROW );
  3720. p->rc = sqlite3_reset(pIdxSelect);
  3721. sqlite3_bind_null(pIdxSelect, 2);
  3722. }
  3723. }
  3724. #endif
  3725. }
  3726. }
  3727. return iSegid;
  3728. }
  3729. /*
  3730. ** Discard all data currently cached in the hash-tables.
  3731. */
  3732. static void fts5IndexDiscardData(Fts5Index *p){
  3733. assert( p->pHash || p->nPendingData==0 );
  3734. if( p->pHash ){
  3735. sqlite3Fts5HashClear(p->pHash);
  3736. p->nPendingData = 0;
  3737. p->nPendingRow = 0;
  3738. p->flushRc = SQLITE_OK;
  3739. }
  3740. p->nContentlessDelete = 0;
  3741. }
  3742. /*
  3743. ** Return the size of the prefix, in bytes, that buffer
  3744. ** (pNew/<length-unknown>) shares with buffer (pOld/nOld).
  3745. **
  3746. ** Buffer (pNew/<length-unknown>) is guaranteed to be greater
  3747. ** than buffer (pOld/nOld).
  3748. */
  3749. static int fts5PrefixCompress(int nOld, const u8 *pOld, const u8 *pNew){
  3750. int i;
  3751. for(i=0; i<nOld; i++){
  3752. if( pOld[i]!=pNew[i] ) break;
  3753. }
  3754. return i;
  3755. }
  3756. static void fts5WriteDlidxClear(
  3757. Fts5Index *p,
  3758. Fts5SegWriter *pWriter,
  3759. int bFlush /* If true, write dlidx to disk */
  3760. ){
  3761. int i;
  3762. assert( bFlush==0 || (pWriter->nDlidx>0 && pWriter->aDlidx[0].buf.n>0) );
  3763. for(i=0; i<pWriter->nDlidx; i++){
  3764. Fts5DlidxWriter *pDlidx = &pWriter->aDlidx[i];
  3765. if( pDlidx->buf.n==0 ) break;
  3766. if( bFlush ){
  3767. assert( pDlidx->pgno!=0 );
  3768. fts5DataWrite(p,
  3769. FTS5_DLIDX_ROWID(pWriter->iSegid, i, pDlidx->pgno),
  3770. pDlidx->buf.p, pDlidx->buf.n
  3771. );
  3772. }
  3773. sqlite3Fts5BufferZero(&pDlidx->buf);
  3774. pDlidx->bPrevValid = 0;
  3775. }
  3776. }
  3777. /*
  3778. ** Grow the pWriter->aDlidx[] array to at least nLvl elements in size.
  3779. ** Any new array elements are zeroed before returning.
  3780. */
  3781. static int fts5WriteDlidxGrow(
  3782. Fts5Index *p,
  3783. Fts5SegWriter *pWriter,
  3784. int nLvl
  3785. ){
  3786. if( p->rc==SQLITE_OK && nLvl>=pWriter->nDlidx ){
  3787. Fts5DlidxWriter *aDlidx = (Fts5DlidxWriter*)sqlite3_realloc64(
  3788. pWriter->aDlidx, sizeof(Fts5DlidxWriter) * nLvl
  3789. );
  3790. if( aDlidx==0 ){
  3791. p->rc = SQLITE_NOMEM;
  3792. }else{
  3793. size_t nByte = sizeof(Fts5DlidxWriter) * (nLvl - pWriter->nDlidx);
  3794. memset(&aDlidx[pWriter->nDlidx], 0, nByte);
  3795. pWriter->aDlidx = aDlidx;
  3796. pWriter->nDlidx = nLvl;
  3797. }
  3798. }
  3799. return p->rc;
  3800. }
  3801. /*
  3802. ** If the current doclist-index accumulating in pWriter->aDlidx[] is large
  3803. ** enough, flush it to disk and return 1. Otherwise discard it and return
  3804. ** zero.
  3805. */
  3806. static int fts5WriteFlushDlidx(Fts5Index *p, Fts5SegWriter *pWriter){
  3807. int bFlag = 0;
  3808. /* If there were FTS5_MIN_DLIDX_SIZE or more empty leaf pages written
  3809. ** to the database, also write the doclist-index to disk. */
  3810. if( pWriter->aDlidx[0].buf.n>0 && pWriter->nEmpty>=FTS5_MIN_DLIDX_SIZE ){
  3811. bFlag = 1;
  3812. }
  3813. fts5WriteDlidxClear(p, pWriter, bFlag);
  3814. pWriter->nEmpty = 0;
  3815. return bFlag;
  3816. }
  3817. /*
  3818. ** This function is called whenever processing of the doclist for the
  3819. ** last term on leaf page (pWriter->iBtPage) is completed.
  3820. **
  3821. ** The doclist-index for that term is currently stored in-memory within the
  3822. ** Fts5SegWriter.aDlidx[] array. If it is large enough, this function
  3823. ** writes it out to disk. Or, if it is too small to bother with, discards
  3824. ** it.
  3825. **
  3826. ** Fts5SegWriter.btterm currently contains the first term on page iBtPage.
  3827. */
  3828. static void fts5WriteFlushBtree(Fts5Index *p, Fts5SegWriter *pWriter){
  3829. int bFlag;
  3830. assert( pWriter->iBtPage || pWriter->nEmpty==0 );
  3831. if( pWriter->iBtPage==0 ) return;
  3832. bFlag = fts5WriteFlushDlidx(p, pWriter);
  3833. if( p->rc==SQLITE_OK ){
  3834. const char *z = (pWriter->btterm.n>0?(const char*)pWriter->btterm.p:"");
  3835. /* The following was already done in fts5WriteInit(): */
  3836. /* sqlite3_bind_int(p->pIdxWriter, 1, pWriter->iSegid); */
  3837. sqlite3_bind_blob(p->pIdxWriter, 2, z, pWriter->btterm.n, SQLITE_STATIC);
  3838. sqlite3_bind_int64(p->pIdxWriter, 3, bFlag + ((i64)pWriter->iBtPage<<1));
  3839. sqlite3_step(p->pIdxWriter);
  3840. p->rc = sqlite3_reset(p->pIdxWriter);
  3841. sqlite3_bind_null(p->pIdxWriter, 2);
  3842. }
  3843. pWriter->iBtPage = 0;
  3844. }
  3845. /*
  3846. ** This is called once for each leaf page except the first that contains
  3847. ** at least one term. Argument (nTerm/pTerm) is the split-key - a term that
  3848. ** is larger than all terms written to earlier leaves, and equal to or
  3849. ** smaller than the first term on the new leaf.
  3850. **
  3851. ** If an error occurs, an error code is left in Fts5Index.rc. If an error
  3852. ** has already occurred when this function is called, it is a no-op.
  3853. */
  3854. static void fts5WriteBtreeTerm(
  3855. Fts5Index *p, /* FTS5 backend object */
  3856. Fts5SegWriter *pWriter, /* Writer object */
  3857. int nTerm, const u8 *pTerm /* First term on new page */
  3858. ){
  3859. fts5WriteFlushBtree(p, pWriter);
  3860. if( p->rc==SQLITE_OK ){
  3861. fts5BufferSet(&p->rc, &pWriter->btterm, nTerm, pTerm);
  3862. pWriter->iBtPage = pWriter->writer.pgno;
  3863. }
  3864. }
  3865. /*
  3866. ** This function is called when flushing a leaf page that contains no
  3867. ** terms at all to disk.
  3868. */
  3869. static void fts5WriteBtreeNoTerm(
  3870. Fts5Index *p, /* FTS5 backend object */
  3871. Fts5SegWriter *pWriter /* Writer object */
  3872. ){
  3873. /* If there were no rowids on the leaf page either and the doclist-index
  3874. ** has already been started, append an 0x00 byte to it. */
  3875. if( pWriter->bFirstRowidInPage && pWriter->aDlidx[0].buf.n>0 ){
  3876. Fts5DlidxWriter *pDlidx = &pWriter->aDlidx[0];
  3877. assert( pDlidx->bPrevValid );
  3878. sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx->buf, 0);
  3879. }
  3880. /* Increment the "number of sequential leaves without a term" counter. */
  3881. pWriter->nEmpty++;
  3882. }
  3883. static i64 fts5DlidxExtractFirstRowid(Fts5Buffer *pBuf){
  3884. i64 iRowid;
  3885. int iOff;
  3886. iOff = 1 + fts5GetVarint(&pBuf->p[1], (u64*)&iRowid);
  3887. fts5GetVarint(&pBuf->p[iOff], (u64*)&iRowid);
  3888. return iRowid;
  3889. }
  3890. /*
  3891. ** Rowid iRowid has just been appended to the current leaf page. It is the
  3892. ** first on the page. This function appends an appropriate entry to the current
  3893. ** doclist-index.
  3894. */
  3895. static void fts5WriteDlidxAppend(
  3896. Fts5Index *p,
  3897. Fts5SegWriter *pWriter,
  3898. i64 iRowid
  3899. ){
  3900. int i;
  3901. int bDone = 0;
  3902. for(i=0; p->rc==SQLITE_OK && bDone==0; i++){
  3903. i64 iVal;
  3904. Fts5DlidxWriter *pDlidx = &pWriter->aDlidx[i];
  3905. if( pDlidx->buf.n>=p->pConfig->pgsz ){
  3906. /* The current doclist-index page is full. Write it to disk and push
  3907. ** a copy of iRowid (which will become the first rowid on the next
  3908. ** doclist-index leaf page) up into the next level of the b-tree
  3909. ** hierarchy. If the node being flushed is currently the root node,
  3910. ** also push its first rowid upwards. */
  3911. pDlidx->buf.p[0] = 0x01; /* Not the root node */
  3912. fts5DataWrite(p,
  3913. FTS5_DLIDX_ROWID(pWriter->iSegid, i, pDlidx->pgno),
  3914. pDlidx->buf.p, pDlidx->buf.n
  3915. );
  3916. fts5WriteDlidxGrow(p, pWriter, i+2);
  3917. pDlidx = &pWriter->aDlidx[i];
  3918. if( p->rc==SQLITE_OK && pDlidx[1].buf.n==0 ){
  3919. i64 iFirst = fts5DlidxExtractFirstRowid(&pDlidx->buf);
  3920. /* This was the root node. Push its first rowid up to the new root. */
  3921. pDlidx[1].pgno = pDlidx->pgno;
  3922. sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx[1].buf, 0);
  3923. sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx[1].buf, pDlidx->pgno);
  3924. sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx[1].buf, iFirst);
  3925. pDlidx[1].bPrevValid = 1;
  3926. pDlidx[1].iPrev = iFirst;
  3927. }
  3928. sqlite3Fts5BufferZero(&pDlidx->buf);
  3929. pDlidx->bPrevValid = 0;
  3930. pDlidx->pgno++;
  3931. }else{
  3932. bDone = 1;
  3933. }
  3934. if( pDlidx->bPrevValid ){
  3935. iVal = (u64)iRowid - (u64)pDlidx->iPrev;
  3936. }else{
  3937. i64 iPgno = (i==0 ? pWriter->writer.pgno : pDlidx[-1].pgno);
  3938. assert( pDlidx->buf.n==0 );
  3939. sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx->buf, !bDone);
  3940. sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx->buf, iPgno);
  3941. iVal = iRowid;
  3942. }
  3943. sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx->buf, iVal);
  3944. pDlidx->bPrevValid = 1;
  3945. pDlidx->iPrev = iRowid;
  3946. }
  3947. }
  3948. static void fts5WriteFlushLeaf(Fts5Index *p, Fts5SegWriter *pWriter){
  3949. static const u8 zero[] = { 0x00, 0x00, 0x00, 0x00 };
  3950. Fts5PageWriter *pPage = &pWriter->writer;
  3951. i64 iRowid;
  3952. assert( (pPage->pgidx.n==0)==(pWriter->bFirstTermInPage) );
  3953. /* Set the szLeaf header field. */
  3954. assert( 0==fts5GetU16(&pPage->buf.p[2]) );
  3955. fts5PutU16(&pPage->buf.p[2], (u16)pPage->buf.n);
  3956. if( pWriter->bFirstTermInPage ){
  3957. /* No term was written to this page. */
  3958. assert( pPage->pgidx.n==0 );
  3959. fts5WriteBtreeNoTerm(p, pWriter);
  3960. }else{
  3961. /* Append the pgidx to the page buffer. Set the szLeaf header field. */
  3962. fts5BufferAppendBlob(&p->rc, &pPage->buf, pPage->pgidx.n, pPage->pgidx.p);
  3963. }
  3964. /* Write the page out to disk */
  3965. iRowid = FTS5_SEGMENT_ROWID(pWriter->iSegid, pPage->pgno);
  3966. fts5DataWrite(p, iRowid, pPage->buf.p, pPage->buf.n);
  3967. /* Initialize the next page. */
  3968. fts5BufferZero(&pPage->buf);
  3969. fts5BufferZero(&pPage->pgidx);
  3970. fts5BufferAppendBlob(&p->rc, &pPage->buf, 4, zero);
  3971. pPage->iPrevPgidx = 0;
  3972. pPage->pgno++;
  3973. /* Increase the leaves written counter */
  3974. pWriter->nLeafWritten++;
  3975. /* The new leaf holds no terms or rowids */
  3976. pWriter->bFirstTermInPage = 1;
  3977. pWriter->bFirstRowidInPage = 1;
  3978. }
  3979. /*
  3980. ** Append term pTerm/nTerm to the segment being written by the writer passed
  3981. ** as the second argument.
  3982. **
  3983. ** If an error occurs, set the Fts5Index.rc error code. If an error has
  3984. ** already occurred, this function is a no-op.
  3985. */
  3986. static void fts5WriteAppendTerm(
  3987. Fts5Index *p,
  3988. Fts5SegWriter *pWriter,
  3989. int nTerm, const u8 *pTerm
  3990. ){
  3991. int nPrefix; /* Bytes of prefix compression for term */
  3992. Fts5PageWriter *pPage = &pWriter->writer;
  3993. Fts5Buffer *pPgidx = &pWriter->writer.pgidx;
  3994. int nMin = MIN(pPage->term.n, nTerm);
  3995. assert( p->rc==SQLITE_OK );
  3996. assert( pPage->buf.n>=4 );
  3997. assert( pPage->buf.n>4 || pWriter->bFirstTermInPage );
  3998. /* If the current leaf page is full, flush it to disk. */
  3999. if( (pPage->buf.n + pPgidx->n + nTerm + 2)>=p->pConfig->pgsz ){
  4000. if( pPage->buf.n>4 ){
  4001. fts5WriteFlushLeaf(p, pWriter);
  4002. if( p->rc!=SQLITE_OK ) return;
  4003. }
  4004. fts5BufferGrow(&p->rc, &pPage->buf, nTerm+FTS5_DATA_PADDING);
  4005. }
  4006. /* TODO1: Updating pgidx here. */
  4007. pPgidx->n += sqlite3Fts5PutVarint(
  4008. &pPgidx->p[pPgidx->n], pPage->buf.n - pPage->iPrevPgidx
  4009. );
  4010. pPage->iPrevPgidx = pPage->buf.n;
  4011. #if 0
  4012. fts5PutU16(&pPgidx->p[pPgidx->n], pPage->buf.n);
  4013. pPgidx->n += 2;
  4014. #endif
  4015. if( pWriter->bFirstTermInPage ){
  4016. nPrefix = 0;
  4017. if( pPage->pgno!=1 ){
  4018. /* This is the first term on a leaf that is not the leftmost leaf in
  4019. ** the segment b-tree. In this case it is necessary to add a term to
  4020. ** the b-tree hierarchy that is (a) larger than the largest term
  4021. ** already written to the segment and (b) smaller than or equal to
  4022. ** this term. In other words, a prefix of (pTerm/nTerm) that is one
  4023. ** byte longer than the longest prefix (pTerm/nTerm) shares with the
  4024. ** previous term.
  4025. **
  4026. ** Usually, the previous term is available in pPage->term. The exception
  4027. ** is if this is the first term written in an incremental-merge step.
  4028. ** In this case the previous term is not available, so just write a
  4029. ** copy of (pTerm/nTerm) into the parent node. This is slightly
  4030. ** inefficient, but still correct. */
  4031. int n = nTerm;
  4032. if( pPage->term.n ){
  4033. n = 1 + fts5PrefixCompress(nMin, pPage->term.p, pTerm);
  4034. }
  4035. fts5WriteBtreeTerm(p, pWriter, n, pTerm);
  4036. if( p->rc!=SQLITE_OK ) return;
  4037. pPage = &pWriter->writer;
  4038. }
  4039. }else{
  4040. nPrefix = fts5PrefixCompress(nMin, pPage->term.p, pTerm);
  4041. fts5BufferAppendVarint(&p->rc, &pPage->buf, nPrefix);
  4042. }
  4043. /* Append the number of bytes of new data, then the term data itself
  4044. ** to the page. */
  4045. fts5BufferAppendVarint(&p->rc, &pPage->buf, nTerm - nPrefix);
  4046. fts5BufferAppendBlob(&p->rc, &pPage->buf, nTerm - nPrefix, &pTerm[nPrefix]);
  4047. /* Update the Fts5PageWriter.term field. */
  4048. fts5BufferSet(&p->rc, &pPage->term, nTerm, pTerm);
  4049. pWriter->bFirstTermInPage = 0;
  4050. pWriter->bFirstRowidInPage = 0;
  4051. pWriter->bFirstRowidInDoclist = 1;
  4052. assert( p->rc || (pWriter->nDlidx>0 && pWriter->aDlidx[0].buf.n==0) );
  4053. pWriter->aDlidx[0].pgno = pPage->pgno;
  4054. }
  4055. /*
  4056. ** Append a rowid and position-list size field to the writers output.
  4057. */
  4058. static void fts5WriteAppendRowid(
  4059. Fts5Index *p,
  4060. Fts5SegWriter *pWriter,
  4061. i64 iRowid
  4062. ){
  4063. if( p->rc==SQLITE_OK ){
  4064. Fts5PageWriter *pPage = &pWriter->writer;
  4065. if( (pPage->buf.n + pPage->pgidx.n)>=p->pConfig->pgsz ){
  4066. fts5WriteFlushLeaf(p, pWriter);
  4067. }
  4068. /* If this is to be the first rowid written to the page, set the
  4069. ** rowid-pointer in the page-header. Also append a value to the dlidx
  4070. ** buffer, in case a doclist-index is required. */
  4071. if( pWriter->bFirstRowidInPage ){
  4072. fts5PutU16(pPage->buf.p, (u16)pPage->buf.n);
  4073. fts5WriteDlidxAppend(p, pWriter, iRowid);
  4074. }
  4075. /* Write the rowid. */
  4076. if( pWriter->bFirstRowidInDoclist || pWriter->bFirstRowidInPage ){
  4077. fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid);
  4078. }else{
  4079. assert_nc( p->rc || iRowid>pWriter->iPrevRowid );
  4080. fts5BufferAppendVarint(&p->rc, &pPage->buf,
  4081. (u64)iRowid - (u64)pWriter->iPrevRowid
  4082. );
  4083. }
  4084. pWriter->iPrevRowid = iRowid;
  4085. pWriter->bFirstRowidInDoclist = 0;
  4086. pWriter->bFirstRowidInPage = 0;
  4087. }
  4088. }
  4089. static void fts5WriteAppendPoslistData(
  4090. Fts5Index *p,
  4091. Fts5SegWriter *pWriter,
  4092. const u8 *aData,
  4093. int nData
  4094. ){
  4095. Fts5PageWriter *pPage = &pWriter->writer;
  4096. const u8 *a = aData;
  4097. int n = nData;
  4098. assert( p->pConfig->pgsz>0 || p->rc!=SQLITE_OK );
  4099. while( p->rc==SQLITE_OK
  4100. && (pPage->buf.n + pPage->pgidx.n + n)>=p->pConfig->pgsz
  4101. ){
  4102. int nReq = p->pConfig->pgsz - pPage->buf.n - pPage->pgidx.n;
  4103. int nCopy = 0;
  4104. while( nCopy<nReq ){
  4105. i64 dummy;
  4106. nCopy += fts5GetVarint(&a[nCopy], (u64*)&dummy);
  4107. }
  4108. fts5BufferAppendBlob(&p->rc, &pPage->buf, nCopy, a);
  4109. a += nCopy;
  4110. n -= nCopy;
  4111. fts5WriteFlushLeaf(p, pWriter);
  4112. }
  4113. if( n>0 ){
  4114. fts5BufferAppendBlob(&p->rc, &pPage->buf, n, a);
  4115. }
  4116. }
  4117. /*
  4118. ** Flush any data cached by the writer object to the database. Free any
  4119. ** allocations associated with the writer.
  4120. */
  4121. static void fts5WriteFinish(
  4122. Fts5Index *p,
  4123. Fts5SegWriter *pWriter, /* Writer object */
  4124. int *pnLeaf /* OUT: Number of leaf pages in b-tree */
  4125. ){
  4126. int i;
  4127. Fts5PageWriter *pLeaf = &pWriter->writer;
  4128. if( p->rc==SQLITE_OK ){
  4129. assert( pLeaf->pgno>=1 );
  4130. if( pLeaf->buf.n>4 ){
  4131. fts5WriteFlushLeaf(p, pWriter);
  4132. }
  4133. *pnLeaf = pLeaf->pgno-1;
  4134. if( pLeaf->pgno>1 ){
  4135. fts5WriteFlushBtree(p, pWriter);
  4136. }
  4137. }
  4138. fts5BufferFree(&pLeaf->term);
  4139. fts5BufferFree(&pLeaf->buf);
  4140. fts5BufferFree(&pLeaf->pgidx);
  4141. fts5BufferFree(&pWriter->btterm);
  4142. for(i=0; i<pWriter->nDlidx; i++){
  4143. sqlite3Fts5BufferFree(&pWriter->aDlidx[i].buf);
  4144. }
  4145. sqlite3_free(pWriter->aDlidx);
  4146. }
  4147. static void fts5WriteInit(
  4148. Fts5Index *p,
  4149. Fts5SegWriter *pWriter,
  4150. int iSegid
  4151. ){
  4152. const int nBuffer = p->pConfig->pgsz + FTS5_DATA_PADDING;
  4153. memset(pWriter, 0, sizeof(Fts5SegWriter));
  4154. pWriter->iSegid = iSegid;
  4155. fts5WriteDlidxGrow(p, pWriter, 1);
  4156. pWriter->writer.pgno = 1;
  4157. pWriter->bFirstTermInPage = 1;
  4158. pWriter->iBtPage = 1;
  4159. assert( pWriter->writer.buf.n==0 );
  4160. assert( pWriter->writer.pgidx.n==0 );
  4161. /* Grow the two buffers to pgsz + padding bytes in size. */
  4162. sqlite3Fts5BufferSize(&p->rc, &pWriter->writer.pgidx, nBuffer);
  4163. sqlite3Fts5BufferSize(&p->rc, &pWriter->writer.buf, nBuffer);
  4164. if( p->pIdxWriter==0 ){
  4165. Fts5Config *pConfig = p->pConfig;
  4166. fts5IndexPrepareStmt(p, &p->pIdxWriter, sqlite3_mprintf(
  4167. "INSERT INTO '%q'.'%q_idx'(segid,term,pgno) VALUES(?,?,?)",
  4168. pConfig->zDb, pConfig->zName
  4169. ));
  4170. }
  4171. if( p->rc==SQLITE_OK ){
  4172. /* Initialize the 4-byte leaf-page header to 0x00. */
  4173. memset(pWriter->writer.buf.p, 0, 4);
  4174. pWriter->writer.buf.n = 4;
  4175. /* Bind the current output segment id to the index-writer. This is an
  4176. ** optimization over binding the same value over and over as rows are
  4177. ** inserted into %_idx by the current writer. */
  4178. sqlite3_bind_int(p->pIdxWriter, 1, pWriter->iSegid);
  4179. }
  4180. }
  4181. /*
  4182. ** Iterator pIter was used to iterate through the input segments of on an
  4183. ** incremental merge operation. This function is called if the incremental
  4184. ** merge step has finished but the input has not been completely exhausted.
  4185. */
  4186. static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){
  4187. int i;
  4188. Fts5Buffer buf;
  4189. memset(&buf, 0, sizeof(Fts5Buffer));
  4190. for(i=0; i<pIter->nSeg && p->rc==SQLITE_OK; i++){
  4191. Fts5SegIter *pSeg = &pIter->aSeg[i];
  4192. if( pSeg->pSeg==0 ){
  4193. /* no-op */
  4194. }else if( pSeg->pLeaf==0 ){
  4195. /* All keys from this input segment have been transfered to the output.
  4196. ** Set both the first and last page-numbers to 0 to indicate that the
  4197. ** segment is now empty. */
  4198. pSeg->pSeg->pgnoLast = 0;
  4199. pSeg->pSeg->pgnoFirst = 0;
  4200. }else{
  4201. int iOff = pSeg->iTermLeafOffset; /* Offset on new first leaf page */
  4202. i64 iLeafRowid;
  4203. Fts5Data *pData;
  4204. int iId = pSeg->pSeg->iSegid;
  4205. u8 aHdr[4] = {0x00, 0x00, 0x00, 0x00};
  4206. iLeafRowid = FTS5_SEGMENT_ROWID(iId, pSeg->iTermLeafPgno);
  4207. pData = fts5LeafRead(p, iLeafRowid);
  4208. if( pData ){
  4209. if( iOff>pData->szLeaf ){
  4210. /* This can occur if the pages that the segments occupy overlap - if
  4211. ** a single page has been assigned to more than one segment. In
  4212. ** this case a prior iteration of this loop may have corrupted the
  4213. ** segment currently being trimmed. */
  4214. p->rc = FTS5_CORRUPT;
  4215. }else{
  4216. fts5BufferZero(&buf);
  4217. fts5BufferGrow(&p->rc, &buf, pData->nn);
  4218. fts5BufferAppendBlob(&p->rc, &buf, sizeof(aHdr), aHdr);
  4219. fts5BufferAppendVarint(&p->rc, &buf, pSeg->term.n);
  4220. fts5BufferAppendBlob(&p->rc, &buf, pSeg->term.n, pSeg->term.p);
  4221. fts5BufferAppendBlob(&p->rc, &buf,pData->szLeaf-iOff,&pData->p[iOff]);
  4222. if( p->rc==SQLITE_OK ){
  4223. /* Set the szLeaf field */
  4224. fts5PutU16(&buf.p[2], (u16)buf.n);
  4225. }
  4226. /* Set up the new page-index array */
  4227. fts5BufferAppendVarint(&p->rc, &buf, 4);
  4228. if( pSeg->iLeafPgno==pSeg->iTermLeafPgno
  4229. && pSeg->iEndofDoclist<pData->szLeaf
  4230. && pSeg->iPgidxOff<=pData->nn
  4231. ){
  4232. int nDiff = pData->szLeaf - pSeg->iEndofDoclist;
  4233. fts5BufferAppendVarint(&p->rc, &buf, buf.n - 1 - nDiff - 4);
  4234. fts5BufferAppendBlob(&p->rc, &buf,
  4235. pData->nn - pSeg->iPgidxOff, &pData->p[pSeg->iPgidxOff]
  4236. );
  4237. }
  4238. pSeg->pSeg->pgnoFirst = pSeg->iTermLeafPgno;
  4239. fts5DataDelete(p, FTS5_SEGMENT_ROWID(iId, 1), iLeafRowid);
  4240. fts5DataWrite(p, iLeafRowid, buf.p, buf.n);
  4241. }
  4242. fts5DataRelease(pData);
  4243. }
  4244. }
  4245. }
  4246. fts5BufferFree(&buf);
  4247. }
  4248. static void fts5MergeChunkCallback(
  4249. Fts5Index *p,
  4250. void *pCtx,
  4251. const u8 *pChunk, int nChunk
  4252. ){
  4253. Fts5SegWriter *pWriter = (Fts5SegWriter*)pCtx;
  4254. fts5WriteAppendPoslistData(p, pWriter, pChunk, nChunk);
  4255. }
  4256. /*
  4257. **
  4258. */
  4259. static void fts5IndexMergeLevel(
  4260. Fts5Index *p, /* FTS5 backend object */
  4261. Fts5Structure **ppStruct, /* IN/OUT: Stucture of index */
  4262. int iLvl, /* Level to read input from */
  4263. int *pnRem /* Write up to this many output leaves */
  4264. ){
  4265. Fts5Structure *pStruct = *ppStruct;
  4266. Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl];
  4267. Fts5StructureLevel *pLvlOut;
  4268. Fts5Iter *pIter = 0; /* Iterator to read input data */
  4269. int nRem = pnRem ? *pnRem : 0; /* Output leaf pages left to write */
  4270. int nInput; /* Number of input segments */
  4271. Fts5SegWriter writer; /* Writer object */
  4272. Fts5StructureSegment *pSeg; /* Output segment */
  4273. Fts5Buffer term;
  4274. int bOldest; /* True if the output segment is the oldest */
  4275. int eDetail = p->pConfig->eDetail;
  4276. const int flags = FTS5INDEX_QUERY_NOOUTPUT;
  4277. int bTermWritten = 0; /* True if current term already output */
  4278. assert( iLvl<pStruct->nLevel );
  4279. assert( pLvl->nMerge<=pLvl->nSeg );
  4280. memset(&writer, 0, sizeof(Fts5SegWriter));
  4281. memset(&term, 0, sizeof(Fts5Buffer));
  4282. if( pLvl->nMerge ){
  4283. pLvlOut = &pStruct->aLevel[iLvl+1];
  4284. assert( pLvlOut->nSeg>0 );
  4285. nInput = pLvl->nMerge;
  4286. pSeg = &pLvlOut->aSeg[pLvlOut->nSeg-1];
  4287. fts5WriteInit(p, &writer, pSeg->iSegid);
  4288. writer.writer.pgno = pSeg->pgnoLast+1;
  4289. writer.iBtPage = 0;
  4290. }else{
  4291. int iSegid = fts5AllocateSegid(p, pStruct);
  4292. /* Extend the Fts5Structure object as required to ensure the output
  4293. ** segment exists. */
  4294. if( iLvl==pStruct->nLevel-1 ){
  4295. fts5StructureAddLevel(&p->rc, ppStruct);
  4296. pStruct = *ppStruct;
  4297. }
  4298. fts5StructureExtendLevel(&p->rc, pStruct, iLvl+1, 1, 0);
  4299. if( p->rc ) return;
  4300. pLvl = &pStruct->aLevel[iLvl];
  4301. pLvlOut = &pStruct->aLevel[iLvl+1];
  4302. fts5WriteInit(p, &writer, iSegid);
  4303. /* Add the new segment to the output level */
  4304. pSeg = &pLvlOut->aSeg[pLvlOut->nSeg];
  4305. pLvlOut->nSeg++;
  4306. pSeg->pgnoFirst = 1;
  4307. pSeg->iSegid = iSegid;
  4308. pStruct->nSegment++;
  4309. /* Read input from all segments in the input level */
  4310. nInput = pLvl->nSeg;
  4311. /* Set the range of origins that will go into the output segment. */
  4312. if( pStruct->nOriginCntr>0 ){
  4313. pSeg->iOrigin1 = pLvl->aSeg[0].iOrigin1;
  4314. pSeg->iOrigin2 = pLvl->aSeg[pLvl->nSeg-1].iOrigin2;
  4315. }
  4316. }
  4317. bOldest = (pLvlOut->nSeg==1 && pStruct->nLevel==iLvl+2);
  4318. assert( iLvl>=0 );
  4319. for(fts5MultiIterNew(p, pStruct, flags, 0, 0, 0, iLvl, nInput, &pIter);
  4320. fts5MultiIterEof(p, pIter)==0;
  4321. fts5MultiIterNext(p, pIter, 0, 0)
  4322. ){
  4323. Fts5SegIter *pSegIter = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
  4324. int nPos; /* position-list size field value */
  4325. int nTerm;
  4326. const u8 *pTerm;
  4327. pTerm = fts5MultiIterTerm(pIter, &nTerm);
  4328. if( nTerm!=term.n || fts5Memcmp(pTerm, term.p, nTerm) ){
  4329. if( pnRem && writer.nLeafWritten>nRem ){
  4330. break;
  4331. }
  4332. fts5BufferSet(&p->rc, &term, nTerm, pTerm);
  4333. bTermWritten =0;
  4334. }
  4335. /* Check for key annihilation. */
  4336. if( pSegIter->nPos==0 && (bOldest || pSegIter->bDel==0) ) continue;
  4337. if( p->rc==SQLITE_OK && bTermWritten==0 ){
  4338. /* This is a new term. Append a term to the output segment. */
  4339. fts5WriteAppendTerm(p, &writer, nTerm, pTerm);
  4340. bTermWritten = 1;
  4341. }
  4342. /* Append the rowid to the output */
  4343. /* WRITEPOSLISTSIZE */
  4344. fts5WriteAppendRowid(p, &writer, fts5MultiIterRowid(pIter));
  4345. if( eDetail==FTS5_DETAIL_NONE ){
  4346. if( pSegIter->bDel ){
  4347. fts5BufferAppendVarint(&p->rc, &writer.writer.buf, 0);
  4348. if( pSegIter->nPos>0 ){
  4349. fts5BufferAppendVarint(&p->rc, &writer.writer.buf, 0);
  4350. }
  4351. }
  4352. }else{
  4353. /* Append the position-list data to the output */
  4354. nPos = pSegIter->nPos*2 + pSegIter->bDel;
  4355. fts5BufferAppendVarint(&p->rc, &writer.writer.buf, nPos);
  4356. fts5ChunkIterate(p, pSegIter, (void*)&writer, fts5MergeChunkCallback);
  4357. }
  4358. }
  4359. /* Flush the last leaf page to disk. Set the output segment b-tree height
  4360. ** and last leaf page number at the same time. */
  4361. fts5WriteFinish(p, &writer, &pSeg->pgnoLast);
  4362. assert( pIter!=0 || p->rc!=SQLITE_OK );
  4363. if( fts5MultiIterEof(p, pIter) ){
  4364. int i;
  4365. /* Remove the redundant segments from the %_data table */
  4366. assert( pSeg->nEntry==0 );
  4367. for(i=0; i<nInput; i++){
  4368. Fts5StructureSegment *pOld = &pLvl->aSeg[i];
  4369. pSeg->nEntry += (pOld->nEntry - pOld->nEntryTombstone);
  4370. fts5DataRemoveSegment(p, pOld);
  4371. }
  4372. /* Remove the redundant segments from the input level */
  4373. if( pLvl->nSeg!=nInput ){
  4374. int nMove = (pLvl->nSeg - nInput) * sizeof(Fts5StructureSegment);
  4375. memmove(pLvl->aSeg, &pLvl->aSeg[nInput], nMove);
  4376. }
  4377. pStruct->nSegment -= nInput;
  4378. pLvl->nSeg -= nInput;
  4379. pLvl->nMerge = 0;
  4380. if( pSeg->pgnoLast==0 ){
  4381. pLvlOut->nSeg--;
  4382. pStruct->nSegment--;
  4383. }
  4384. }else{
  4385. assert( pSeg->pgnoLast>0 );
  4386. fts5TrimSegments(p, pIter);
  4387. pLvl->nMerge = nInput;
  4388. }
  4389. fts5MultiIterFree(pIter);
  4390. fts5BufferFree(&term);
  4391. if( pnRem ) *pnRem -= writer.nLeafWritten;
  4392. }
  4393. /*
  4394. ** If this is not a contentless_delete=1 table, or if the 'deletemerge'
  4395. ** configuration option is set to 0, then this function always returns -1.
  4396. ** Otherwise, it searches the structure object passed as the second argument
  4397. ** for a level suitable for merging due to having a large number of
  4398. ** tombstones in the tombstone hash. If one is found, its index is returned.
  4399. ** Otherwise, if there is no suitable level, -1.
  4400. */
  4401. static int fts5IndexFindDeleteMerge(Fts5Index *p, Fts5Structure *pStruct){
  4402. Fts5Config *pConfig = p->pConfig;
  4403. int iRet = -1;
  4404. if( pConfig->bContentlessDelete && pConfig->nDeleteMerge>0 ){
  4405. int ii;
  4406. int nBest = 0;
  4407. for(ii=0; ii<pStruct->nLevel; ii++){
  4408. Fts5StructureLevel *pLvl = &pStruct->aLevel[ii];
  4409. i64 nEntry = 0;
  4410. i64 nTomb = 0;
  4411. int iSeg;
  4412. for(iSeg=0; iSeg<pLvl->nSeg; iSeg++){
  4413. nEntry += pLvl->aSeg[iSeg].nEntry;
  4414. nTomb += pLvl->aSeg[iSeg].nEntryTombstone;
  4415. }
  4416. assert_nc( nEntry>0 || pLvl->nSeg==0 );
  4417. if( nEntry>0 ){
  4418. int nPercent = (nTomb * 100) / nEntry;
  4419. if( nPercent>=pConfig->nDeleteMerge && nPercent>nBest ){
  4420. iRet = ii;
  4421. nBest = nPercent;
  4422. }
  4423. }
  4424. /* If pLvl is already the input level to an ongoing merge, look no
  4425. ** further for a merge candidate. The caller should be allowed to
  4426. ** continue merging from pLvl first. */
  4427. if( pLvl->nMerge ) break;
  4428. }
  4429. }
  4430. return iRet;
  4431. }
  4432. /*
  4433. ** Do up to nPg pages of automerge work on the index.
  4434. **
  4435. ** Return true if any changes were actually made, or false otherwise.
  4436. */
  4437. static int fts5IndexMerge(
  4438. Fts5Index *p, /* FTS5 backend object */
  4439. Fts5Structure **ppStruct, /* IN/OUT: Current structure of index */
  4440. int nPg, /* Pages of work to do */
  4441. int nMin /* Minimum number of segments to merge */
  4442. ){
  4443. int nRem = nPg;
  4444. int bRet = 0;
  4445. Fts5Structure *pStruct = *ppStruct;
  4446. while( nRem>0 && p->rc==SQLITE_OK ){
  4447. int iLvl; /* To iterate through levels */
  4448. int iBestLvl = 0; /* Level offering the most input segments */
  4449. int nBest = 0; /* Number of input segments on best level */
  4450. /* Set iBestLvl to the level to read input segments from. Or to -1 if
  4451. ** there is no level suitable to merge segments from. */
  4452. assert( pStruct->nLevel>0 );
  4453. for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
  4454. Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl];
  4455. if( pLvl->nMerge ){
  4456. if( pLvl->nMerge>nBest ){
  4457. iBestLvl = iLvl;
  4458. nBest = nMin;
  4459. }
  4460. break;
  4461. }
  4462. if( pLvl->nSeg>nBest ){
  4463. nBest = pLvl->nSeg;
  4464. iBestLvl = iLvl;
  4465. }
  4466. }
  4467. if( nBest<nMin ){
  4468. iBestLvl = fts5IndexFindDeleteMerge(p, pStruct);
  4469. }
  4470. if( iBestLvl<0 ) break;
  4471. bRet = 1;
  4472. fts5IndexMergeLevel(p, &pStruct, iBestLvl, &nRem);
  4473. if( p->rc==SQLITE_OK && pStruct->aLevel[iBestLvl].nMerge==0 ){
  4474. fts5StructurePromote(p, iBestLvl+1, pStruct);
  4475. }
  4476. if( nMin==1 ) nMin = 2;
  4477. }
  4478. *ppStruct = pStruct;
  4479. return bRet;
  4480. }
  4481. /*
  4482. ** A total of nLeaf leaf pages of data has just been flushed to a level-0
  4483. ** segment. This function updates the write-counter accordingly and, if
  4484. ** necessary, performs incremental merge work.
  4485. **
  4486. ** If an error occurs, set the Fts5Index.rc error code. If an error has
  4487. ** already occurred, this function is a no-op.
  4488. */
  4489. static void fts5IndexAutomerge(
  4490. Fts5Index *p, /* FTS5 backend object */
  4491. Fts5Structure **ppStruct, /* IN/OUT: Current structure of index */
  4492. int nLeaf /* Number of output leaves just written */
  4493. ){
  4494. if( p->rc==SQLITE_OK && p->pConfig->nAutomerge>0 && ALWAYS((*ppStruct)!=0) ){
  4495. Fts5Structure *pStruct = *ppStruct;
  4496. u64 nWrite; /* Initial value of write-counter */
  4497. int nWork; /* Number of work-quanta to perform */
  4498. int nRem; /* Number of leaf pages left to write */
  4499. /* Update the write-counter. While doing so, set nWork. */
  4500. nWrite = pStruct->nWriteCounter;
  4501. nWork = (int)(((nWrite + nLeaf) / p->nWorkUnit) - (nWrite / p->nWorkUnit));
  4502. pStruct->nWriteCounter += nLeaf;
  4503. nRem = (int)(p->nWorkUnit * nWork * pStruct->nLevel);
  4504. fts5IndexMerge(p, ppStruct, nRem, p->pConfig->nAutomerge);
  4505. }
  4506. }
  4507. static void fts5IndexCrisismerge(
  4508. Fts5Index *p, /* FTS5 backend object */
  4509. Fts5Structure **ppStruct /* IN/OUT: Current structure of index */
  4510. ){
  4511. const int nCrisis = p->pConfig->nCrisisMerge;
  4512. Fts5Structure *pStruct = *ppStruct;
  4513. if( pStruct && pStruct->nLevel>0 ){
  4514. int iLvl = 0;
  4515. while( p->rc==SQLITE_OK && pStruct->aLevel[iLvl].nSeg>=nCrisis ){
  4516. fts5IndexMergeLevel(p, &pStruct, iLvl, 0);
  4517. assert( p->rc!=SQLITE_OK || pStruct->nLevel>(iLvl+1) );
  4518. fts5StructurePromote(p, iLvl+1, pStruct);
  4519. iLvl++;
  4520. }
  4521. *ppStruct = pStruct;
  4522. }
  4523. }
  4524. static int fts5IndexReturn(Fts5Index *p){
  4525. int rc = p->rc;
  4526. p->rc = SQLITE_OK;
  4527. return rc;
  4528. }
  4529. typedef struct Fts5FlushCtx Fts5FlushCtx;
  4530. struct Fts5FlushCtx {
  4531. Fts5Index *pIdx;
  4532. Fts5SegWriter writer;
  4533. };
  4534. /*
  4535. ** Buffer aBuf[] contains a list of varints, all small enough to fit
  4536. ** in a 32-bit integer. Return the size of the largest prefix of this
  4537. ** list nMax bytes or less in size.
  4538. */
  4539. static int fts5PoslistPrefix(const u8 *aBuf, int nMax){
  4540. int ret;
  4541. u32 dummy;
  4542. ret = fts5GetVarint32(aBuf, dummy);
  4543. if( ret<nMax ){
  4544. while( 1 ){
  4545. int i = fts5GetVarint32(&aBuf[ret], dummy);
  4546. if( (ret + i) > nMax ) break;
  4547. ret += i;
  4548. }
  4549. }
  4550. return ret;
  4551. }
  4552. /*
  4553. ** Execute the SQL statement:
  4554. **
  4555. ** DELETE FROM %_idx WHERE (segid, (pgno/2)) = ($iSegid, $iPgno);
  4556. **
  4557. ** This is used when a secure-delete operation removes the last term
  4558. ** from a segment leaf page. In that case the %_idx entry is removed
  4559. ** too. This is done to ensure that if all instances of a token are
  4560. ** removed from an fts5 database in secure-delete mode, no trace of
  4561. ** the token itself remains in the database.
  4562. */
  4563. static void fts5SecureDeleteIdxEntry(
  4564. Fts5Index *p, /* FTS5 backend object */
  4565. int iSegid, /* Id of segment to delete entry for */
  4566. int iPgno /* Page number within segment */
  4567. ){
  4568. if( iPgno!=1 ){
  4569. assert( p->pConfig->iVersion==FTS5_CURRENT_VERSION_SECUREDELETE );
  4570. if( p->pDeleteFromIdx==0 ){
  4571. fts5IndexPrepareStmt(p, &p->pDeleteFromIdx, sqlite3_mprintf(
  4572. "DELETE FROM '%q'.'%q_idx' WHERE (segid, (pgno/2)) = (?1, ?2)",
  4573. p->pConfig->zDb, p->pConfig->zName
  4574. ));
  4575. }
  4576. if( p->rc==SQLITE_OK ){
  4577. sqlite3_bind_int(p->pDeleteFromIdx, 1, iSegid);
  4578. sqlite3_bind_int(p->pDeleteFromIdx, 2, iPgno);
  4579. sqlite3_step(p->pDeleteFromIdx);
  4580. p->rc = sqlite3_reset(p->pDeleteFromIdx);
  4581. }
  4582. }
  4583. }
  4584. /*
  4585. ** This is called when a secure-delete operation removes a position-list
  4586. ** that overflows onto segment page iPgno of segment pSeg. This function
  4587. ** rewrites node iPgno, and possibly one or more of its right-hand peers,
  4588. ** to remove this portion of the position list.
  4589. **
  4590. ** Output variable (*pbLastInDoclist) is set to true if the position-list
  4591. ** removed is followed by a new term or the end-of-segment, or false if
  4592. ** it is followed by another rowid/position list.
  4593. */
  4594. static void fts5SecureDeleteOverflow(
  4595. Fts5Index *p,
  4596. Fts5StructureSegment *pSeg,
  4597. int iPgno,
  4598. int *pbLastInDoclist
  4599. ){
  4600. const int bDetailNone = (p->pConfig->eDetail==FTS5_DETAIL_NONE);
  4601. int pgno;
  4602. Fts5Data *pLeaf = 0;
  4603. assert( iPgno!=1 );
  4604. *pbLastInDoclist = 1;
  4605. for(pgno=iPgno; p->rc==SQLITE_OK && pgno<=pSeg->pgnoLast; pgno++){
  4606. i64 iRowid = FTS5_SEGMENT_ROWID(pSeg->iSegid, pgno);
  4607. int iNext = 0;
  4608. u8 *aPg = 0;
  4609. pLeaf = fts5DataRead(p, iRowid);
  4610. if( pLeaf==0 ) break;
  4611. aPg = pLeaf->p;
  4612. iNext = fts5GetU16(&aPg[0]);
  4613. if( iNext!=0 ){
  4614. *pbLastInDoclist = 0;
  4615. }
  4616. if( iNext==0 && pLeaf->szLeaf!=pLeaf->nn ){
  4617. fts5GetVarint32(&aPg[pLeaf->szLeaf], iNext);
  4618. }
  4619. if( iNext==0 ){
  4620. /* The page contains no terms or rowids. Replace it with an empty
  4621. ** page and move on to the right-hand peer. */
  4622. const u8 aEmpty[] = {0x00, 0x00, 0x00, 0x04};
  4623. assert_nc( bDetailNone==0 || pLeaf->nn==4 );
  4624. if( bDetailNone==0 ) fts5DataWrite(p, iRowid, aEmpty, sizeof(aEmpty));
  4625. fts5DataRelease(pLeaf);
  4626. pLeaf = 0;
  4627. }else if( bDetailNone ){
  4628. break;
  4629. }else if( iNext>=pLeaf->szLeaf || pLeaf->nn<pLeaf->szLeaf || iNext<4 ){
  4630. p->rc = FTS5_CORRUPT;
  4631. break;
  4632. }else{
  4633. int nShift = iNext - 4;
  4634. int nPg;
  4635. int nIdx = 0;
  4636. u8 *aIdx = 0;
  4637. /* Unless the current page footer is 0 bytes in size (in which case
  4638. ** the new page footer will be as well), allocate and populate a
  4639. ** buffer containing the new page footer. Set stack variables aIdx
  4640. ** and nIdx accordingly. */
  4641. if( pLeaf->nn>pLeaf->szLeaf ){
  4642. int iFirst = 0;
  4643. int i1 = pLeaf->szLeaf;
  4644. int i2 = 0;
  4645. i1 += fts5GetVarint32(&aPg[i1], iFirst);
  4646. if( iFirst<iNext ){
  4647. p->rc = FTS5_CORRUPT;
  4648. break;
  4649. }
  4650. aIdx = sqlite3Fts5MallocZero(&p->rc, (pLeaf->nn-pLeaf->szLeaf)+2);
  4651. if( aIdx==0 ) break;
  4652. i2 = sqlite3Fts5PutVarint(aIdx, iFirst-nShift);
  4653. if( i1<pLeaf->nn ){
  4654. memcpy(&aIdx[i2], &aPg[i1], pLeaf->nn-i1);
  4655. i2 += (pLeaf->nn-i1);
  4656. }
  4657. nIdx = i2;
  4658. }
  4659. /* Modify the contents of buffer aPg[]. Set nPg to the new size
  4660. ** in bytes. The new page is always smaller than the old. */
  4661. nPg = pLeaf->szLeaf - nShift;
  4662. memmove(&aPg[4], &aPg[4+nShift], nPg-4);
  4663. fts5PutU16(&aPg[2], nPg);
  4664. if( fts5GetU16(&aPg[0]) ) fts5PutU16(&aPg[0], 4);
  4665. if( nIdx>0 ){
  4666. memcpy(&aPg[nPg], aIdx, nIdx);
  4667. nPg += nIdx;
  4668. }
  4669. sqlite3_free(aIdx);
  4670. /* Write the new page to disk and exit the loop */
  4671. assert( nPg>4 || fts5GetU16(aPg)==0 );
  4672. fts5DataWrite(p, iRowid, aPg, nPg);
  4673. break;
  4674. }
  4675. }
  4676. fts5DataRelease(pLeaf);
  4677. }
  4678. /*
  4679. ** Completely remove the entry that pSeg currently points to from
  4680. ** the database.
  4681. */
  4682. static void fts5DoSecureDelete(
  4683. Fts5Index *p,
  4684. Fts5SegIter *pSeg
  4685. ){
  4686. const int bDetailNone = (p->pConfig->eDetail==FTS5_DETAIL_NONE);
  4687. int iSegid = pSeg->pSeg->iSegid;
  4688. u8 *aPg = pSeg->pLeaf->p;
  4689. int nPg = pSeg->pLeaf->nn;
  4690. int iPgIdx = pSeg->pLeaf->szLeaf;
  4691. u64 iDelta = 0;
  4692. int iNextOff = 0;
  4693. int iOff = 0;
  4694. int nIdx = 0;
  4695. u8 *aIdx = 0;
  4696. int bLastInDoclist = 0;
  4697. int iIdx = 0;
  4698. int iStart = 0;
  4699. int iDelKeyOff = 0; /* Offset of deleted key, if any */
  4700. nIdx = nPg-iPgIdx;
  4701. aIdx = sqlite3Fts5MallocZero(&p->rc, nIdx+16);
  4702. if( p->rc ) return;
  4703. memcpy(aIdx, &aPg[iPgIdx], nIdx);
  4704. /* At this point segment iterator pSeg points to the entry
  4705. ** this function should remove from the b-tree segment.
  4706. **
  4707. ** In detail=full or detail=column mode, pSeg->iLeafOffset is the
  4708. ** offset of the first byte in the position-list for the entry to
  4709. ** remove. Immediately before this comes two varints that will also
  4710. ** need to be removed:
  4711. **
  4712. ** + the rowid or delta rowid value for the entry, and
  4713. ** + the size of the position list in bytes.
  4714. **
  4715. ** Or, in detail=none mode, there is a single varint prior to
  4716. ** pSeg->iLeafOffset - the rowid or delta rowid value.
  4717. **
  4718. ** This block sets the following variables:
  4719. **
  4720. ** iStart:
  4721. ** The offset of the first byte of the rowid or delta-rowid
  4722. ** value for the doclist entry being removed.
  4723. **
  4724. ** iDelta:
  4725. ** The value of the rowid or delta-rowid value for the doclist
  4726. ** entry being removed.
  4727. **
  4728. ** iNextOff:
  4729. ** The offset of the next entry following the position list
  4730. ** for the one being removed. If the position list for this
  4731. ** entry overflows onto the next leaf page, this value will be
  4732. ** greater than pLeaf->szLeaf.
  4733. */
  4734. {
  4735. int iSOP; /* Start-Of-Position-list */
  4736. if( pSeg->iLeafPgno==pSeg->iTermLeafPgno ){
  4737. iStart = pSeg->iTermLeafOffset;
  4738. }else{
  4739. iStart = fts5GetU16(&aPg[0]);
  4740. }
  4741. iSOP = iStart + fts5GetVarint(&aPg[iStart], &iDelta);
  4742. assert_nc( iSOP<=pSeg->iLeafOffset );
  4743. if( bDetailNone ){
  4744. while( iSOP<pSeg->iLeafOffset ){
  4745. if( aPg[iSOP]==0x00 ) iSOP++;
  4746. if( aPg[iSOP]==0x00 ) iSOP++;
  4747. iStart = iSOP;
  4748. iSOP = iStart + fts5GetVarint(&aPg[iStart], &iDelta);
  4749. }
  4750. iNextOff = iSOP;
  4751. if( iNextOff<pSeg->iEndofDoclist && aPg[iNextOff]==0x00 ) iNextOff++;
  4752. if( iNextOff<pSeg->iEndofDoclist && aPg[iNextOff]==0x00 ) iNextOff++;
  4753. }else{
  4754. int nPos = 0;
  4755. iSOP += fts5GetVarint32(&aPg[iSOP], nPos);
  4756. while( iSOP<pSeg->iLeafOffset ){
  4757. iStart = iSOP + (nPos/2);
  4758. iSOP = iStart + fts5GetVarint(&aPg[iStart], &iDelta);
  4759. iSOP += fts5GetVarint32(&aPg[iSOP], nPos);
  4760. }
  4761. assert_nc( iSOP==pSeg->iLeafOffset );
  4762. iNextOff = pSeg->iLeafOffset + pSeg->nPos;
  4763. }
  4764. }
  4765. iOff = iStart;
  4766. /* If the position-list for the entry being removed flows over past
  4767. ** the end of this page, delete the portion of the position-list on the
  4768. ** next page and beyond.
  4769. **
  4770. ** Set variable bLastInDoclist to true if this entry happens
  4771. ** to be the last rowid in the doclist for its term. */
  4772. if( iNextOff>=iPgIdx ){
  4773. int pgno = pSeg->iLeafPgno+1;
  4774. fts5SecureDeleteOverflow(p, pSeg->pSeg, pgno, &bLastInDoclist);
  4775. iNextOff = iPgIdx;
  4776. }
  4777. if( pSeg->bDel==0 ){
  4778. if( iNextOff!=iPgIdx ){
  4779. /* Loop through the page-footer. If iNextOff (offset of the
  4780. ** entry following the one we are removing) is equal to the
  4781. ** offset of a key on this page, then the entry is the last
  4782. ** in its doclist. */
  4783. int iKeyOff = 0;
  4784. for(iIdx=0; iIdx<nIdx; /* no-op */){
  4785. u32 iVal = 0;
  4786. iIdx += fts5GetVarint32(&aIdx[iIdx], iVal);
  4787. iKeyOff += iVal;
  4788. if( iKeyOff==iNextOff ){
  4789. bLastInDoclist = 1;
  4790. }
  4791. }
  4792. }
  4793. /* If this is (a) the first rowid on a page and (b) is not followed by
  4794. ** another position list on the same page, set the "first-rowid" field
  4795. ** of the header to 0. */
  4796. if( fts5GetU16(&aPg[0])==iStart && (bLastInDoclist || iNextOff==iPgIdx) ){
  4797. fts5PutU16(&aPg[0], 0);
  4798. }
  4799. }
  4800. if( pSeg->bDel ){
  4801. iOff += sqlite3Fts5PutVarint(&aPg[iOff], iDelta);
  4802. aPg[iOff++] = 0x01;
  4803. }else if( bLastInDoclist==0 ){
  4804. if( iNextOff!=iPgIdx ){
  4805. u64 iNextDelta = 0;
  4806. iNextOff += fts5GetVarint(&aPg[iNextOff], &iNextDelta);
  4807. iOff += sqlite3Fts5PutVarint(&aPg[iOff], iDelta + iNextDelta);
  4808. }
  4809. }else if(
  4810. pSeg->iLeafPgno==pSeg->iTermLeafPgno
  4811. && iStart==pSeg->iTermLeafOffset
  4812. ){
  4813. /* The entry being removed was the only position list in its
  4814. ** doclist. Therefore the term needs to be removed as well. */
  4815. int iKey = 0;
  4816. int iKeyOff = 0;
  4817. /* Set iKeyOff to the offset of the term that will be removed - the
  4818. ** last offset in the footer that is not greater than iStart. */
  4819. for(iIdx=0; iIdx<nIdx; iKey++){
  4820. u32 iVal = 0;
  4821. iIdx += fts5GetVarint32(&aIdx[iIdx], iVal);
  4822. if( (iKeyOff+iVal)>(u32)iStart ) break;
  4823. iKeyOff += iVal;
  4824. }
  4825. assert_nc( iKey>=1 );
  4826. /* Set iDelKeyOff to the value of the footer entry to remove from
  4827. ** the page. */
  4828. iDelKeyOff = iOff = iKeyOff;
  4829. if( iNextOff!=iPgIdx ){
  4830. /* This is the only position-list associated with the term, and there
  4831. ** is another term following it on this page. So the subsequent term
  4832. ** needs to be moved to replace the term associated with the entry
  4833. ** being removed. */
  4834. int nPrefix = 0;
  4835. int nSuffix = 0;
  4836. int nPrefix2 = 0;
  4837. int nSuffix2 = 0;
  4838. iDelKeyOff = iNextOff;
  4839. iNextOff += fts5GetVarint32(&aPg[iNextOff], nPrefix2);
  4840. iNextOff += fts5GetVarint32(&aPg[iNextOff], nSuffix2);
  4841. if( iKey!=1 ){
  4842. iKeyOff += fts5GetVarint32(&aPg[iKeyOff], nPrefix);
  4843. }
  4844. iKeyOff += fts5GetVarint32(&aPg[iKeyOff], nSuffix);
  4845. nPrefix = MIN(nPrefix, nPrefix2);
  4846. nSuffix = (nPrefix2 + nSuffix2) - nPrefix;
  4847. if( (iKeyOff+nSuffix)>iPgIdx || (iNextOff+nSuffix2)>iPgIdx ){
  4848. p->rc = FTS5_CORRUPT;
  4849. }else{
  4850. if( iKey!=1 ){
  4851. iOff += sqlite3Fts5PutVarint(&aPg[iOff], nPrefix);
  4852. }
  4853. iOff += sqlite3Fts5PutVarint(&aPg[iOff], nSuffix);
  4854. if( nPrefix2>pSeg->term.n ){
  4855. p->rc = FTS5_CORRUPT;
  4856. }else if( nPrefix2>nPrefix ){
  4857. memcpy(&aPg[iOff], &pSeg->term.p[nPrefix], nPrefix2-nPrefix);
  4858. iOff += (nPrefix2-nPrefix);
  4859. }
  4860. memmove(&aPg[iOff], &aPg[iNextOff], nSuffix2);
  4861. iOff += nSuffix2;
  4862. iNextOff += nSuffix2;
  4863. }
  4864. }
  4865. }else if( iStart==4 ){
  4866. int iPgno;
  4867. assert_nc( pSeg->iLeafPgno>pSeg->iTermLeafPgno );
  4868. /* The entry being removed may be the only position list in
  4869. ** its doclist. */
  4870. for(iPgno=pSeg->iLeafPgno-1; iPgno>pSeg->iTermLeafPgno; iPgno-- ){
  4871. Fts5Data *pPg = fts5DataRead(p, FTS5_SEGMENT_ROWID(iSegid, iPgno));
  4872. int bEmpty = (pPg && pPg->nn==4);
  4873. fts5DataRelease(pPg);
  4874. if( bEmpty==0 ) break;
  4875. }
  4876. if( iPgno==pSeg->iTermLeafPgno ){
  4877. i64 iId = FTS5_SEGMENT_ROWID(iSegid, pSeg->iTermLeafPgno);
  4878. Fts5Data *pTerm = fts5DataRead(p, iId);
  4879. if( pTerm && pTerm->szLeaf==pSeg->iTermLeafOffset ){
  4880. u8 *aTermIdx = &pTerm->p[pTerm->szLeaf];
  4881. int nTermIdx = pTerm->nn - pTerm->szLeaf;
  4882. int iTermIdx = 0;
  4883. int iTermOff = 0;
  4884. while( 1 ){
  4885. u32 iVal = 0;
  4886. int nByte = fts5GetVarint32(&aTermIdx[iTermIdx], iVal);
  4887. iTermOff += iVal;
  4888. if( (iTermIdx+nByte)>=nTermIdx ) break;
  4889. iTermIdx += nByte;
  4890. }
  4891. nTermIdx = iTermIdx;
  4892. memmove(&pTerm->p[iTermOff], &pTerm->p[pTerm->szLeaf], nTermIdx);
  4893. fts5PutU16(&pTerm->p[2], iTermOff);
  4894. fts5DataWrite(p, iId, pTerm->p, iTermOff+nTermIdx);
  4895. if( nTermIdx==0 ){
  4896. fts5SecureDeleteIdxEntry(p, iSegid, pSeg->iTermLeafPgno);
  4897. }
  4898. }
  4899. fts5DataRelease(pTerm);
  4900. }
  4901. }
  4902. /* Assuming no error has occurred, this block does final edits to the
  4903. ** leaf page before writing it back to disk. Input variables are:
  4904. **
  4905. ** nPg: Total initial size of leaf page.
  4906. ** iPgIdx: Initial offset of page footer.
  4907. **
  4908. ** iOff: Offset to move data to
  4909. ** iNextOff: Offset to move data from
  4910. */
  4911. if( p->rc==SQLITE_OK ){
  4912. const int nMove = nPg - iNextOff; /* Number of bytes to move */
  4913. int nShift = iNextOff - iOff; /* Distance to move them */
  4914. int iPrevKeyOut = 0;
  4915. int iKeyIn = 0;
  4916. memmove(&aPg[iOff], &aPg[iNextOff], nMove);
  4917. iPgIdx -= nShift;
  4918. nPg = iPgIdx;
  4919. fts5PutU16(&aPg[2], iPgIdx);
  4920. for(iIdx=0; iIdx<nIdx; /* no-op */){
  4921. u32 iVal = 0;
  4922. iIdx += fts5GetVarint32(&aIdx[iIdx], iVal);
  4923. iKeyIn += iVal;
  4924. if( iKeyIn!=iDelKeyOff ){
  4925. int iKeyOut = (iKeyIn - (iKeyIn>iOff ? nShift : 0));
  4926. nPg += sqlite3Fts5PutVarint(&aPg[nPg], iKeyOut - iPrevKeyOut);
  4927. iPrevKeyOut = iKeyOut;
  4928. }
  4929. }
  4930. if( iPgIdx==nPg && nIdx>0 && pSeg->iLeafPgno!=1 ){
  4931. fts5SecureDeleteIdxEntry(p, iSegid, pSeg->iLeafPgno);
  4932. }
  4933. assert_nc( nPg>4 || fts5GetU16(aPg)==0 );
  4934. fts5DataWrite(p, FTS5_SEGMENT_ROWID(iSegid,pSeg->iLeafPgno), aPg, nPg);
  4935. }
  4936. sqlite3_free(aIdx);
  4937. }
  4938. /*
  4939. ** This is called as part of flushing a delete to disk in 'secure-delete'
  4940. ** mode. It edits the segments within the database described by argument
  4941. ** pStruct to remove the entries for term zTerm, rowid iRowid.
  4942. */
  4943. static void fts5FlushSecureDelete(
  4944. Fts5Index *p,
  4945. Fts5Structure *pStruct,
  4946. const char *zTerm,
  4947. int nTerm,
  4948. i64 iRowid
  4949. ){
  4950. const int f = FTS5INDEX_QUERY_SKIPHASH;
  4951. Fts5Iter *pIter = 0; /* Used to find term instance */
  4952. fts5MultiIterNew(p, pStruct, f, 0, (const u8*)zTerm, nTerm, -1, 0, &pIter);
  4953. if( fts5MultiIterEof(p, pIter)==0 ){
  4954. i64 iThis = fts5MultiIterRowid(pIter);
  4955. if( iThis<iRowid ){
  4956. fts5MultiIterNextFrom(p, pIter, iRowid);
  4957. }
  4958. if( p->rc==SQLITE_OK
  4959. && fts5MultiIterEof(p, pIter)==0
  4960. && iRowid==fts5MultiIterRowid(pIter)
  4961. ){
  4962. Fts5SegIter *pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst];
  4963. fts5DoSecureDelete(p, pSeg);
  4964. }
  4965. }
  4966. fts5MultiIterFree(pIter);
  4967. }
  4968. /*
  4969. ** Flush the contents of in-memory hash table iHash to a new level-0
  4970. ** segment on disk. Also update the corresponding structure record.
  4971. **
  4972. ** If an error occurs, set the Fts5Index.rc error code. If an error has
  4973. ** already occurred, this function is a no-op.
  4974. */
  4975. static void fts5FlushOneHash(Fts5Index *p){
  4976. Fts5Hash *pHash = p->pHash;
  4977. Fts5Structure *pStruct;
  4978. int iSegid;
  4979. int pgnoLast = 0; /* Last leaf page number in segment */
  4980. /* Obtain a reference to the index structure and allocate a new segment-id
  4981. ** for the new level-0 segment. */
  4982. pStruct = fts5StructureRead(p);
  4983. fts5StructureInvalidate(p);
  4984. if( sqlite3Fts5HashIsEmpty(pHash)==0 ){
  4985. iSegid = fts5AllocateSegid(p, pStruct);
  4986. if( iSegid ){
  4987. const int pgsz = p->pConfig->pgsz;
  4988. int eDetail = p->pConfig->eDetail;
  4989. int bSecureDelete = p->pConfig->bSecureDelete;
  4990. Fts5StructureSegment *pSeg; /* New segment within pStruct */
  4991. Fts5Buffer *pBuf; /* Buffer in which to assemble leaf page */
  4992. Fts5Buffer *pPgidx; /* Buffer in which to assemble pgidx */
  4993. Fts5SegWriter writer;
  4994. fts5WriteInit(p, &writer, iSegid);
  4995. pBuf = &writer.writer.buf;
  4996. pPgidx = &writer.writer.pgidx;
  4997. /* fts5WriteInit() should have initialized the buffers to (most likely)
  4998. ** the maximum space required. */
  4999. assert( p->rc || pBuf->nSpace>=(pgsz + FTS5_DATA_PADDING) );
  5000. assert( p->rc || pPgidx->nSpace>=(pgsz + FTS5_DATA_PADDING) );
  5001. /* Begin scanning through hash table entries. This loop runs once for each
  5002. ** term/doclist currently stored within the hash table. */
  5003. if( p->rc==SQLITE_OK ){
  5004. p->rc = sqlite3Fts5HashScanInit(pHash, 0, 0);
  5005. }
  5006. while( p->rc==SQLITE_OK && 0==sqlite3Fts5HashScanEof(pHash) ){
  5007. const char *zTerm; /* Buffer containing term */
  5008. int nTerm; /* Size of zTerm in bytes */
  5009. const u8 *pDoclist; /* Pointer to doclist for this term */
  5010. int nDoclist; /* Size of doclist in bytes */
  5011. /* Get the term and doclist for this entry. */
  5012. sqlite3Fts5HashScanEntry(pHash, &zTerm, &nTerm, &pDoclist, &nDoclist);
  5013. if( bSecureDelete==0 ){
  5014. fts5WriteAppendTerm(p, &writer, nTerm, (const u8*)zTerm);
  5015. if( p->rc!=SQLITE_OK ) break;
  5016. assert( writer.bFirstRowidInPage==0 );
  5017. }
  5018. if( !bSecureDelete && pgsz>=(pBuf->n + pPgidx->n + nDoclist + 1) ){
  5019. /* The entire doclist will fit on the current leaf. */
  5020. fts5BufferSafeAppendBlob(pBuf, pDoclist, nDoclist);
  5021. }else{
  5022. int bTermWritten = !bSecureDelete;
  5023. i64 iRowid = 0;
  5024. i64 iPrev = 0;
  5025. int iOff = 0;
  5026. /* The entire doclist will not fit on this leaf. The following
  5027. ** loop iterates through the poslists that make up the current
  5028. ** doclist. */
  5029. while( p->rc==SQLITE_OK && iOff<nDoclist ){
  5030. u64 iDelta = 0;
  5031. iOff += fts5GetVarint(&pDoclist[iOff], &iDelta);
  5032. iRowid += iDelta;
  5033. /* If in secure delete mode, and if this entry in the poslist is
  5034. ** in fact a delete, then edit the existing segments directly
  5035. ** using fts5FlushSecureDelete(). */
  5036. if( bSecureDelete ){
  5037. if( eDetail==FTS5_DETAIL_NONE ){
  5038. if( iOff<nDoclist && pDoclist[iOff]==0x00 ){
  5039. fts5FlushSecureDelete(p, pStruct, zTerm, nTerm, iRowid);
  5040. iOff++;
  5041. if( iOff<nDoclist && pDoclist[iOff]==0x00 ){
  5042. iOff++;
  5043. nDoclist = 0;
  5044. }else{
  5045. continue;
  5046. }
  5047. }
  5048. }else if( (pDoclist[iOff] & 0x01) ){
  5049. fts5FlushSecureDelete(p, pStruct, zTerm, nTerm, iRowid);
  5050. if( p->rc!=SQLITE_OK || pDoclist[iOff]==0x01 ){
  5051. iOff++;
  5052. continue;
  5053. }
  5054. }
  5055. }
  5056. if( p->rc==SQLITE_OK && bTermWritten==0 ){
  5057. fts5WriteAppendTerm(p, &writer, nTerm, (const u8*)zTerm);
  5058. bTermWritten = 1;
  5059. assert( p->rc!=SQLITE_OK || writer.bFirstRowidInPage==0 );
  5060. }
  5061. if( writer.bFirstRowidInPage ){
  5062. fts5PutU16(&pBuf->p[0], (u16)pBuf->n); /* first rowid on page */
  5063. pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowid);
  5064. writer.bFirstRowidInPage = 0;
  5065. fts5WriteDlidxAppend(p, &writer, iRowid);
  5066. }else{
  5067. u64 iRowidDelta = (u64)iRowid - (u64)iPrev;
  5068. pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowidDelta);
  5069. }
  5070. if( p->rc!=SQLITE_OK ) break;
  5071. assert( pBuf->n<=pBuf->nSpace );
  5072. iPrev = iRowid;
  5073. if( eDetail==FTS5_DETAIL_NONE ){
  5074. if( iOff<nDoclist && pDoclist[iOff]==0 ){
  5075. pBuf->p[pBuf->n++] = 0;
  5076. iOff++;
  5077. if( iOff<nDoclist && pDoclist[iOff]==0 ){
  5078. pBuf->p[pBuf->n++] = 0;
  5079. iOff++;
  5080. }
  5081. }
  5082. if( (pBuf->n + pPgidx->n)>=pgsz ){
  5083. fts5WriteFlushLeaf(p, &writer);
  5084. }
  5085. }else{
  5086. int bDel = 0;
  5087. int nPos = 0;
  5088. int nCopy = fts5GetPoslistSize(&pDoclist[iOff], &nPos, &bDel);
  5089. if( bDel && bSecureDelete ){
  5090. fts5BufferAppendVarint(&p->rc, pBuf, nPos*2);
  5091. iOff += nCopy;
  5092. nCopy = nPos;
  5093. }else{
  5094. nCopy += nPos;
  5095. }
  5096. if( (pBuf->n + pPgidx->n + nCopy) <= pgsz ){
  5097. /* The entire poslist will fit on the current leaf. So copy
  5098. ** it in one go. */
  5099. fts5BufferSafeAppendBlob(pBuf, &pDoclist[iOff], nCopy);
  5100. }else{
  5101. /* The entire poslist will not fit on this leaf. So it needs
  5102. ** to be broken into sections. The only qualification being
  5103. ** that each varint must be stored contiguously. */
  5104. const u8 *pPoslist = &pDoclist[iOff];
  5105. int iPos = 0;
  5106. while( p->rc==SQLITE_OK ){
  5107. int nSpace = pgsz - pBuf->n - pPgidx->n;
  5108. int n = 0;
  5109. if( (nCopy - iPos)<=nSpace ){
  5110. n = nCopy - iPos;
  5111. }else{
  5112. n = fts5PoslistPrefix(&pPoslist[iPos], nSpace);
  5113. }
  5114. assert( n>0 );
  5115. fts5BufferSafeAppendBlob(pBuf, &pPoslist[iPos], n);
  5116. iPos += n;
  5117. if( (pBuf->n + pPgidx->n)>=pgsz ){
  5118. fts5WriteFlushLeaf(p, &writer);
  5119. }
  5120. if( iPos>=nCopy ) break;
  5121. }
  5122. }
  5123. iOff += nCopy;
  5124. }
  5125. }
  5126. }
  5127. /* TODO2: Doclist terminator written here. */
  5128. /* pBuf->p[pBuf->n++] = '\0'; */
  5129. assert( pBuf->n<=pBuf->nSpace );
  5130. if( p->rc==SQLITE_OK ) sqlite3Fts5HashScanNext(pHash);
  5131. }
  5132. fts5WriteFinish(p, &writer, &pgnoLast);
  5133. assert( p->rc!=SQLITE_OK || bSecureDelete || pgnoLast>0 );
  5134. if( pgnoLast>0 ){
  5135. /* Update the Fts5Structure. It is written back to the database by the
  5136. ** fts5StructureRelease() call below. */
  5137. if( pStruct->nLevel==0 ){
  5138. fts5StructureAddLevel(&p->rc, &pStruct);
  5139. }
  5140. fts5StructureExtendLevel(&p->rc, pStruct, 0, 1, 0);
  5141. if( p->rc==SQLITE_OK ){
  5142. pSeg = &pStruct->aLevel[0].aSeg[ pStruct->aLevel[0].nSeg++ ];
  5143. pSeg->iSegid = iSegid;
  5144. pSeg->pgnoFirst = 1;
  5145. pSeg->pgnoLast = pgnoLast;
  5146. if( pStruct->nOriginCntr>0 ){
  5147. pSeg->iOrigin1 = pStruct->nOriginCntr;
  5148. pSeg->iOrigin2 = pStruct->nOriginCntr;
  5149. pSeg->nEntry = p->nPendingRow;
  5150. pStruct->nOriginCntr++;
  5151. }
  5152. pStruct->nSegment++;
  5153. }
  5154. fts5StructurePromote(p, 0, pStruct);
  5155. }
  5156. }
  5157. }
  5158. fts5IndexAutomerge(p, &pStruct, pgnoLast + p->nContentlessDelete);
  5159. fts5IndexCrisismerge(p, &pStruct);
  5160. fts5StructureWrite(p, pStruct);
  5161. fts5StructureRelease(pStruct);
  5162. }
  5163. /*
  5164. ** Flush any data stored in the in-memory hash tables to the database.
  5165. */
  5166. static void fts5IndexFlush(Fts5Index *p){
  5167. /* Unless it is empty, flush the hash table to disk */
  5168. if( p->flushRc ){
  5169. p->rc = p->flushRc;
  5170. return;
  5171. }
  5172. if( p->nPendingData || p->nContentlessDelete ){
  5173. assert( p->pHash );
  5174. fts5FlushOneHash(p);
  5175. if( p->rc==SQLITE_OK ){
  5176. sqlite3Fts5HashClear(p->pHash);
  5177. p->nPendingData = 0;
  5178. p->nPendingRow = 0;
  5179. p->nContentlessDelete = 0;
  5180. }else if( p->nPendingData || p->nContentlessDelete ){
  5181. p->flushRc = p->rc;
  5182. }
  5183. }
  5184. }
  5185. static Fts5Structure *fts5IndexOptimizeStruct(
  5186. Fts5Index *p,
  5187. Fts5Structure *pStruct
  5188. ){
  5189. Fts5Structure *pNew = 0;
  5190. sqlite3_int64 nByte = sizeof(Fts5Structure);
  5191. int nSeg = pStruct->nSegment;
  5192. int i;
  5193. /* Figure out if this structure requires optimization. A structure does
  5194. ** not require optimization if either:
  5195. **
  5196. ** 1. it consists of fewer than two segments, or
  5197. ** 2. all segments are on the same level, or
  5198. ** 3. all segments except one are currently inputs to a merge operation.
  5199. **
  5200. ** In the first case, if there are no tombstone hash pages, return NULL. In
  5201. ** the second, increment the ref-count on *pStruct and return a copy of the
  5202. ** pointer to it.
  5203. */
  5204. if( nSeg==0 ) return 0;
  5205. for(i=0; i<pStruct->nLevel; i++){
  5206. int nThis = pStruct->aLevel[i].nSeg;
  5207. int nMerge = pStruct->aLevel[i].nMerge;
  5208. if( nThis>0 && (nThis==nSeg || (nThis==nSeg-1 && nMerge==nThis)) ){
  5209. if( nSeg==1 && nThis==1 && pStruct->aLevel[i].aSeg[0].nPgTombstone==0 ){
  5210. return 0;
  5211. }
  5212. fts5StructureRef(pStruct);
  5213. return pStruct;
  5214. }
  5215. assert( pStruct->aLevel[i].nMerge<=nThis );
  5216. }
  5217. nByte += (pStruct->nLevel+1) * sizeof(Fts5StructureLevel);
  5218. pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte);
  5219. if( pNew ){
  5220. Fts5StructureLevel *pLvl;
  5221. nByte = nSeg * sizeof(Fts5StructureSegment);
  5222. pNew->nLevel = MIN(pStruct->nLevel+1, FTS5_MAX_LEVEL);
  5223. pNew->nRef = 1;
  5224. pNew->nWriteCounter = pStruct->nWriteCounter;
  5225. pNew->nOriginCntr = pStruct->nOriginCntr;
  5226. pLvl = &pNew->aLevel[pNew->nLevel-1];
  5227. pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&p->rc, nByte);
  5228. if( pLvl->aSeg ){
  5229. int iLvl, iSeg;
  5230. int iSegOut = 0;
  5231. /* Iterate through all segments, from oldest to newest. Add them to
  5232. ** the new Fts5Level object so that pLvl->aSeg[0] is the oldest
  5233. ** segment in the data structure. */
  5234. for(iLvl=pStruct->nLevel-1; iLvl>=0; iLvl--){
  5235. for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
  5236. pLvl->aSeg[iSegOut] = pStruct->aLevel[iLvl].aSeg[iSeg];
  5237. iSegOut++;
  5238. }
  5239. }
  5240. pNew->nSegment = pLvl->nSeg = nSeg;
  5241. }else{
  5242. sqlite3_free(pNew);
  5243. pNew = 0;
  5244. }
  5245. }
  5246. return pNew;
  5247. }
  5248. int sqlite3Fts5IndexOptimize(Fts5Index *p){
  5249. Fts5Structure *pStruct;
  5250. Fts5Structure *pNew = 0;
  5251. assert( p->rc==SQLITE_OK );
  5252. fts5IndexFlush(p);
  5253. assert( p->rc!=SQLITE_OK || p->nContentlessDelete==0 );
  5254. pStruct = fts5StructureRead(p);
  5255. assert( p->rc!=SQLITE_OK || pStruct!=0 );
  5256. fts5StructureInvalidate(p);
  5257. if( pStruct ){
  5258. pNew = fts5IndexOptimizeStruct(p, pStruct);
  5259. }
  5260. fts5StructureRelease(pStruct);
  5261. assert( pNew==0 || pNew->nSegment>0 );
  5262. if( pNew ){
  5263. int iLvl;
  5264. for(iLvl=0; pNew->aLevel[iLvl].nSeg==0; iLvl++){}
  5265. while( p->rc==SQLITE_OK && pNew->aLevel[iLvl].nSeg>0 ){
  5266. int nRem = FTS5_OPT_WORK_UNIT;
  5267. fts5IndexMergeLevel(p, &pNew, iLvl, &nRem);
  5268. }
  5269. fts5StructureWrite(p, pNew);
  5270. fts5StructureRelease(pNew);
  5271. }
  5272. return fts5IndexReturn(p);
  5273. }
  5274. /*
  5275. ** This is called to implement the special "VALUES('merge', $nMerge)"
  5276. ** INSERT command.
  5277. */
  5278. int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge){
  5279. Fts5Structure *pStruct = 0;
  5280. fts5IndexFlush(p);
  5281. pStruct = fts5StructureRead(p);
  5282. if( pStruct ){
  5283. int nMin = p->pConfig->nUsermerge;
  5284. fts5StructureInvalidate(p);
  5285. if( nMerge<0 ){
  5286. Fts5Structure *pNew = fts5IndexOptimizeStruct(p, pStruct);
  5287. fts5StructureRelease(pStruct);
  5288. pStruct = pNew;
  5289. nMin = 1;
  5290. nMerge = nMerge*-1;
  5291. }
  5292. if( pStruct && pStruct->nLevel ){
  5293. if( fts5IndexMerge(p, &pStruct, nMerge, nMin) ){
  5294. fts5StructureWrite(p, pStruct);
  5295. }
  5296. }
  5297. fts5StructureRelease(pStruct);
  5298. }
  5299. return fts5IndexReturn(p);
  5300. }
  5301. static void fts5AppendRowid(
  5302. Fts5Index *p,
  5303. u64 iDelta,
  5304. Fts5Iter *pUnused,
  5305. Fts5Buffer *pBuf
  5306. ){
  5307. UNUSED_PARAM(pUnused);
  5308. fts5BufferAppendVarint(&p->rc, pBuf, iDelta);
  5309. }
  5310. static void fts5AppendPoslist(
  5311. Fts5Index *p,
  5312. u64 iDelta,
  5313. Fts5Iter *pMulti,
  5314. Fts5Buffer *pBuf
  5315. ){
  5316. int nData = pMulti->base.nData;
  5317. int nByte = nData + 9 + 9 + FTS5_DATA_ZERO_PADDING;
  5318. assert( nData>0 );
  5319. if( p->rc==SQLITE_OK && 0==fts5BufferGrow(&p->rc, pBuf, nByte) ){
  5320. fts5BufferSafeAppendVarint(pBuf, iDelta);
  5321. fts5BufferSafeAppendVarint(pBuf, nData*2);
  5322. fts5BufferSafeAppendBlob(pBuf, pMulti->base.pData, nData);
  5323. memset(&pBuf->p[pBuf->n], 0, FTS5_DATA_ZERO_PADDING);
  5324. }
  5325. }
  5326. static void fts5DoclistIterNext(Fts5DoclistIter *pIter){
  5327. u8 *p = pIter->aPoslist + pIter->nSize + pIter->nPoslist;
  5328. assert( pIter->aPoslist || (p==0 && pIter->aPoslist==0) );
  5329. if( p>=pIter->aEof ){
  5330. pIter->aPoslist = 0;
  5331. }else{
  5332. i64 iDelta;
  5333. p += fts5GetVarint(p, (u64*)&iDelta);
  5334. pIter->iRowid += iDelta;
  5335. /* Read position list size */
  5336. if( p[0] & 0x80 ){
  5337. int nPos;
  5338. pIter->nSize = fts5GetVarint32(p, nPos);
  5339. pIter->nPoslist = (nPos>>1);
  5340. }else{
  5341. pIter->nPoslist = ((int)(p[0])) >> 1;
  5342. pIter->nSize = 1;
  5343. }
  5344. pIter->aPoslist = p;
  5345. if( &pIter->aPoslist[pIter->nPoslist]>pIter->aEof ){
  5346. pIter->aPoslist = 0;
  5347. }
  5348. }
  5349. }
  5350. static void fts5DoclistIterInit(
  5351. Fts5Buffer *pBuf,
  5352. Fts5DoclistIter *pIter
  5353. ){
  5354. memset(pIter, 0, sizeof(*pIter));
  5355. if( pBuf->n>0 ){
  5356. pIter->aPoslist = pBuf->p;
  5357. pIter->aEof = &pBuf->p[pBuf->n];
  5358. fts5DoclistIterNext(pIter);
  5359. }
  5360. }
  5361. #if 0
  5362. /*
  5363. ** Append a doclist to buffer pBuf.
  5364. **
  5365. ** This function assumes that space within the buffer has already been
  5366. ** allocated.
  5367. */
  5368. static void fts5MergeAppendDocid(
  5369. Fts5Buffer *pBuf, /* Buffer to write to */
  5370. i64 *piLastRowid, /* IN/OUT: Previous rowid written (if any) */
  5371. i64 iRowid /* Rowid to append */
  5372. ){
  5373. assert( pBuf->n!=0 || (*piLastRowid)==0 );
  5374. fts5BufferSafeAppendVarint(pBuf, iRowid - *piLastRowid);
  5375. *piLastRowid = iRowid;
  5376. }
  5377. #endif
  5378. #define fts5MergeAppendDocid(pBuf, iLastRowid, iRowid) { \
  5379. assert( (pBuf)->n!=0 || (iLastRowid)==0 ); \
  5380. fts5BufferSafeAppendVarint((pBuf), (u64)(iRowid) - (u64)(iLastRowid)); \
  5381. (iLastRowid) = (iRowid); \
  5382. }
  5383. /*
  5384. ** Swap the contents of buffer *p1 with that of *p2.
  5385. */
  5386. static void fts5BufferSwap(Fts5Buffer *p1, Fts5Buffer *p2){
  5387. Fts5Buffer tmp = *p1;
  5388. *p1 = *p2;
  5389. *p2 = tmp;
  5390. }
  5391. static void fts5NextRowid(Fts5Buffer *pBuf, int *piOff, i64 *piRowid){
  5392. int i = *piOff;
  5393. if( i>=pBuf->n ){
  5394. *piOff = -1;
  5395. }else{
  5396. u64 iVal;
  5397. *piOff = i + sqlite3Fts5GetVarint(&pBuf->p[i], &iVal);
  5398. *piRowid += iVal;
  5399. }
  5400. }
  5401. /*
  5402. ** This is the equivalent of fts5MergePrefixLists() for detail=none mode.
  5403. ** In this case the buffers consist of a delta-encoded list of rowids only.
  5404. */
  5405. static void fts5MergeRowidLists(
  5406. Fts5Index *p, /* FTS5 backend object */
  5407. Fts5Buffer *p1, /* First list to merge */
  5408. int nBuf, /* Number of entries in apBuf[] */
  5409. Fts5Buffer *aBuf /* Array of other lists to merge into p1 */
  5410. ){
  5411. int i1 = 0;
  5412. int i2 = 0;
  5413. i64 iRowid1 = 0;
  5414. i64 iRowid2 = 0;
  5415. i64 iOut = 0;
  5416. Fts5Buffer *p2 = &aBuf[0];
  5417. Fts5Buffer out;
  5418. (void)nBuf;
  5419. memset(&out, 0, sizeof(out));
  5420. assert( nBuf==1 );
  5421. sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n);
  5422. if( p->rc ) return;
  5423. fts5NextRowid(p1, &i1, &iRowid1);
  5424. fts5NextRowid(p2, &i2, &iRowid2);
  5425. while( i1>=0 || i2>=0 ){
  5426. if( i1>=0 && (i2<0 || iRowid1<iRowid2) ){
  5427. assert( iOut==0 || iRowid1>iOut );
  5428. fts5BufferSafeAppendVarint(&out, iRowid1 - iOut);
  5429. iOut = iRowid1;
  5430. fts5NextRowid(p1, &i1, &iRowid1);
  5431. }else{
  5432. assert( iOut==0 || iRowid2>iOut );
  5433. fts5BufferSafeAppendVarint(&out, iRowid2 - iOut);
  5434. iOut = iRowid2;
  5435. if( i1>=0 && iRowid1==iRowid2 ){
  5436. fts5NextRowid(p1, &i1, &iRowid1);
  5437. }
  5438. fts5NextRowid(p2, &i2, &iRowid2);
  5439. }
  5440. }
  5441. fts5BufferSwap(&out, p1);
  5442. fts5BufferFree(&out);
  5443. }
  5444. typedef struct PrefixMerger PrefixMerger;
  5445. struct PrefixMerger {
  5446. Fts5DoclistIter iter; /* Doclist iterator */
  5447. i64 iPos; /* For iterating through a position list */
  5448. int iOff;
  5449. u8 *aPos;
  5450. PrefixMerger *pNext; /* Next in docid/poslist order */
  5451. };
  5452. static void fts5PrefixMergerInsertByRowid(
  5453. PrefixMerger **ppHead,
  5454. PrefixMerger *p
  5455. ){
  5456. if( p->iter.aPoslist ){
  5457. PrefixMerger **pp = ppHead;
  5458. while( *pp && p->iter.iRowid>(*pp)->iter.iRowid ){
  5459. pp = &(*pp)->pNext;
  5460. }
  5461. p->pNext = *pp;
  5462. *pp = p;
  5463. }
  5464. }
  5465. static void fts5PrefixMergerInsertByPosition(
  5466. PrefixMerger **ppHead,
  5467. PrefixMerger *p
  5468. ){
  5469. if( p->iPos>=0 ){
  5470. PrefixMerger **pp = ppHead;
  5471. while( *pp && p->iPos>(*pp)->iPos ){
  5472. pp = &(*pp)->pNext;
  5473. }
  5474. p->pNext = *pp;
  5475. *pp = p;
  5476. }
  5477. }
  5478. /*
  5479. ** Array aBuf[] contains nBuf doclists. These are all merged in with the
  5480. ** doclist in buffer p1.
  5481. */
  5482. static void fts5MergePrefixLists(
  5483. Fts5Index *p, /* FTS5 backend object */
  5484. Fts5Buffer *p1, /* First list to merge */
  5485. int nBuf, /* Number of buffers in array aBuf[] */
  5486. Fts5Buffer *aBuf /* Other lists to merge in */
  5487. ){
  5488. #define fts5PrefixMergerNextPosition(p) \
  5489. sqlite3Fts5PoslistNext64((p)->aPos,(p)->iter.nPoslist,&(p)->iOff,&(p)->iPos)
  5490. #define FTS5_MERGE_NLIST 16
  5491. PrefixMerger aMerger[FTS5_MERGE_NLIST];
  5492. PrefixMerger *pHead = 0;
  5493. int i;
  5494. int nOut = 0;
  5495. Fts5Buffer out = {0, 0, 0};
  5496. Fts5Buffer tmp = {0, 0, 0};
  5497. i64 iLastRowid = 0;
  5498. /* Initialize a doclist-iterator for each input buffer. Arrange them in
  5499. ** a linked-list starting at pHead in ascending order of rowid. Avoid
  5500. ** linking any iterators already at EOF into the linked list at all. */
  5501. assert( nBuf+1<=(int)(sizeof(aMerger)/sizeof(aMerger[0])) );
  5502. memset(aMerger, 0, sizeof(PrefixMerger)*(nBuf+1));
  5503. pHead = &aMerger[nBuf];
  5504. fts5DoclistIterInit(p1, &pHead->iter);
  5505. for(i=0; i<nBuf; i++){
  5506. fts5DoclistIterInit(&aBuf[i], &aMerger[i].iter);
  5507. fts5PrefixMergerInsertByRowid(&pHead, &aMerger[i]);
  5508. nOut += aBuf[i].n;
  5509. }
  5510. if( nOut==0 ) return;
  5511. nOut += p1->n + 9 + 10*nBuf;
  5512. /* The maximum size of the output is equal to the sum of the
  5513. ** input sizes + 1 varint (9 bytes). The extra varint is because if the
  5514. ** first rowid in one input is a large negative number, and the first in
  5515. ** the other a non-negative number, the delta for the non-negative
  5516. ** number will be larger on disk than the literal integer value
  5517. ** was.
  5518. **
  5519. ** Or, if the input position-lists are corrupt, then the output might
  5520. ** include up to (nBuf+1) extra 10-byte positions created by interpreting -1
  5521. ** (the value PoslistNext64() uses for EOF) as a position and appending
  5522. ** it to the output. This can happen at most once for each input
  5523. ** position-list, hence (nBuf+1) 10 byte paddings. */
  5524. if( sqlite3Fts5BufferSize(&p->rc, &out, nOut) ) return;
  5525. while( pHead ){
  5526. fts5MergeAppendDocid(&out, iLastRowid, pHead->iter.iRowid);
  5527. if( pHead->pNext && iLastRowid==pHead->pNext->iter.iRowid ){
  5528. /* Merge data from two or more poslists */
  5529. i64 iPrev = 0;
  5530. int nTmp = FTS5_DATA_ZERO_PADDING;
  5531. int nMerge = 0;
  5532. PrefixMerger *pSave = pHead;
  5533. PrefixMerger *pThis = 0;
  5534. int nTail = 0;
  5535. pHead = 0;
  5536. while( pSave && pSave->iter.iRowid==iLastRowid ){
  5537. PrefixMerger *pNext = pSave->pNext;
  5538. pSave->iOff = 0;
  5539. pSave->iPos = 0;
  5540. pSave->aPos = &pSave->iter.aPoslist[pSave->iter.nSize];
  5541. fts5PrefixMergerNextPosition(pSave);
  5542. nTmp += pSave->iter.nPoslist + 10;
  5543. nMerge++;
  5544. fts5PrefixMergerInsertByPosition(&pHead, pSave);
  5545. pSave = pNext;
  5546. }
  5547. if( pHead==0 || pHead->pNext==0 ){
  5548. p->rc = FTS5_CORRUPT;
  5549. break;
  5550. }
  5551. /* See the earlier comment in this function for an explanation of why
  5552. ** corrupt input position lists might cause the output to consume
  5553. ** at most nMerge*10 bytes of unexpected space. */
  5554. if( sqlite3Fts5BufferSize(&p->rc, &tmp, nTmp+nMerge*10) ){
  5555. break;
  5556. }
  5557. fts5BufferZero(&tmp);
  5558. pThis = pHead;
  5559. pHead = pThis->pNext;
  5560. sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pThis->iPos);
  5561. fts5PrefixMergerNextPosition(pThis);
  5562. fts5PrefixMergerInsertByPosition(&pHead, pThis);
  5563. while( pHead->pNext ){
  5564. pThis = pHead;
  5565. if( pThis->iPos!=iPrev ){
  5566. sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pThis->iPos);
  5567. }
  5568. fts5PrefixMergerNextPosition(pThis);
  5569. pHead = pThis->pNext;
  5570. fts5PrefixMergerInsertByPosition(&pHead, pThis);
  5571. }
  5572. if( pHead->iPos!=iPrev ){
  5573. sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pHead->iPos);
  5574. }
  5575. nTail = pHead->iter.nPoslist - pHead->iOff;
  5576. /* WRITEPOSLISTSIZE */
  5577. assert_nc( tmp.n+nTail<=nTmp );
  5578. assert( tmp.n+nTail<=nTmp+nMerge*10 );
  5579. if( tmp.n+nTail>nTmp-FTS5_DATA_ZERO_PADDING ){
  5580. if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
  5581. break;
  5582. }
  5583. fts5BufferSafeAppendVarint(&out, (tmp.n+nTail) * 2);
  5584. fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
  5585. if( nTail>0 ){
  5586. fts5BufferSafeAppendBlob(&out, &pHead->aPos[pHead->iOff], nTail);
  5587. }
  5588. pHead = pSave;
  5589. for(i=0; i<nBuf+1; i++){
  5590. PrefixMerger *pX = &aMerger[i];
  5591. if( pX->iter.aPoslist && pX->iter.iRowid==iLastRowid ){
  5592. fts5DoclistIterNext(&pX->iter);
  5593. fts5PrefixMergerInsertByRowid(&pHead, pX);
  5594. }
  5595. }
  5596. }else{
  5597. /* Copy poslist from pHead to output */
  5598. PrefixMerger *pThis = pHead;
  5599. Fts5DoclistIter *pI = &pThis->iter;
  5600. fts5BufferSafeAppendBlob(&out, pI->aPoslist, pI->nPoslist+pI->nSize);
  5601. fts5DoclistIterNext(pI);
  5602. pHead = pThis->pNext;
  5603. fts5PrefixMergerInsertByRowid(&pHead, pThis);
  5604. }
  5605. }
  5606. fts5BufferFree(p1);
  5607. fts5BufferFree(&tmp);
  5608. memset(&out.p[out.n], 0, FTS5_DATA_ZERO_PADDING);
  5609. *p1 = out;
  5610. }
  5611. /*
  5612. ** Iterate through a range of entries in the FTS index, invoking the xVisit
  5613. ** callback for each of them.
  5614. **
  5615. ** Parameter pToken points to an nToken buffer containing an FTS index term
  5616. ** (i.e. a document term with the preceding 1 byte index identifier -
  5617. ** FTS5_MAIN_PREFIX or similar). If bPrefix is true, then the call visits
  5618. ** all entries for terms that have pToken/nToken as a prefix. If bPrefix
  5619. ** is false, then only entries with pToken/nToken as the entire key are
  5620. ** visited.
  5621. **
  5622. ** If the current table is a tokendata=1 table, then if bPrefix is true then
  5623. ** each index term is treated separately. However, if bPrefix is false, then
  5624. ** all index terms corresponding to pToken/nToken are collapsed into a single
  5625. ** term before the callback is invoked.
  5626. **
  5627. ** The callback invoked for each entry visited is specified by paramter xVisit.
  5628. ** Each time it is invoked, it is passed a pointer to the Fts5Index object,
  5629. ** a copy of the 7th paramter to this function (pCtx) and a pointer to the
  5630. ** iterator that indicates the current entry. If the current entry is the
  5631. ** first with a new term (i.e. different from that of the previous entry,
  5632. ** including the very first term), then the final two parameters are passed
  5633. ** a pointer to the term and its size in bytes, respectively. If the current
  5634. ** entry is not the first associated with its term, these two parameters
  5635. ** are passed 0.
  5636. **
  5637. ** If parameter pColset is not NULL, then it is used to filter entries before
  5638. ** the callback is invoked.
  5639. */
  5640. static int fts5VisitEntries(
  5641. Fts5Index *p, /* Fts5 index object */
  5642. Fts5Colset *pColset, /* Columns filter to apply, or NULL */
  5643. u8 *pToken, /* Buffer containing token */
  5644. int nToken, /* Size of buffer pToken in bytes */
  5645. int bPrefix, /* True for a prefix scan */
  5646. void (*xVisit)(Fts5Index*, void *pCtx, Fts5Iter *pIter, const u8*, int),
  5647. void *pCtx /* Passed as second argument to xVisit() */
  5648. ){
  5649. const int flags = (bPrefix ? FTS5INDEX_QUERY_SCAN : 0)
  5650. | FTS5INDEX_QUERY_SKIPEMPTY
  5651. | FTS5INDEX_QUERY_NOOUTPUT;
  5652. Fts5Iter *p1 = 0; /* Iterator used to gather data from index */
  5653. int bNewTerm = 1;
  5654. Fts5Structure *pStruct = fts5StructureRead(p);
  5655. fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1);
  5656. fts5IterSetOutputCb(&p->rc, p1);
  5657. for( /* no-op */ ;
  5658. fts5MultiIterEof(p, p1)==0;
  5659. fts5MultiIterNext2(p, p1, &bNewTerm)
  5660. ){
  5661. Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
  5662. int nNew = 0;
  5663. const u8 *pNew = 0;
  5664. p1->xSetOutputs(p1, pSeg);
  5665. if( p->rc ) break;
  5666. if( bNewTerm ){
  5667. nNew = pSeg->term.n;
  5668. pNew = pSeg->term.p;
  5669. if( nNew<nToken || memcmp(pToken, pNew, nToken) ) break;
  5670. }
  5671. xVisit(p, pCtx, p1, pNew, nNew);
  5672. }
  5673. fts5MultiIterFree(p1);
  5674. fts5StructureRelease(pStruct);
  5675. return p->rc;
  5676. }
  5677. /*
  5678. ** Usually, a tokendata=1 iterator (struct Fts5TokenDataIter) accumulates an
  5679. ** array of these for each row it visits (so all iRowid fields are the same).
  5680. ** Or, for an iterator used by an "ORDER BY rank" query, it accumulates an
  5681. ** array of these for the entire query (in which case iRowid fields may take
  5682. ** a variety of values).
  5683. **
  5684. ** Each instance in the array indicates the iterator (and therefore term)
  5685. ** associated with position iPos of rowid iRowid. This is used by the
  5686. ** xInstToken() API.
  5687. **
  5688. ** iRowid:
  5689. ** Rowid for the current entry.
  5690. **
  5691. ** iPos:
  5692. ** Position of current entry within row. In the usual ((iCol<<32)+iOff)
  5693. ** format (e.g. see macros FTS5_POS2COLUMN() and FTS5_POS2OFFSET()).
  5694. **
  5695. ** iIter:
  5696. ** If the Fts5TokenDataIter iterator that the entry is part of is
  5697. ** actually an iterator (i.e. with nIter>0, not just a container for
  5698. ** Fts5TokenDataMap structures), then this variable is an index into
  5699. ** the apIter[] array. The corresponding term is that which the iterator
  5700. ** at apIter[iIter] currently points to.
  5701. **
  5702. ** Or, if the Fts5TokenDataIter iterator is just a container object
  5703. ** (nIter==0), then iIter is an index into the term.p[] buffer where
  5704. ** the term is stored.
  5705. **
  5706. ** nByte:
  5707. ** In the case where iIter is an index into term.p[], this variable
  5708. ** is the size of the term in bytes. If iIter is an index into apIter[],
  5709. ** this variable is unused.
  5710. */
  5711. struct Fts5TokenDataMap {
  5712. i64 iRowid; /* Row this token is located in */
  5713. i64 iPos; /* Position of token */
  5714. int iIter; /* Iterator token was read from */
  5715. int nByte; /* Length of token in bytes (or 0) */
  5716. };
  5717. /*
  5718. ** An object used to supplement Fts5Iter for tokendata=1 iterators.
  5719. **
  5720. ** This object serves two purposes. The first is as a container for an array
  5721. ** of Fts5TokenDataMap structures, which are used to find the token required
  5722. ** when the xInstToken() API is used. This is done by the nMapAlloc, nMap and
  5723. ** aMap[] variables.
  5724. */
  5725. struct Fts5TokenDataIter {
  5726. int nMapAlloc; /* Allocated size of aMap[] in entries */
  5727. int nMap; /* Number of valid entries in aMap[] */
  5728. Fts5TokenDataMap *aMap; /* Array of (rowid+pos -> token) mappings */
  5729. /* The following are used for prefix-queries only. */
  5730. Fts5Buffer terms;
  5731. /* The following are used for other full-token tokendata queries only. */
  5732. int nIter;
  5733. int nIterAlloc;
  5734. Fts5PoslistReader *aPoslistReader;
  5735. int *aPoslistToIter;
  5736. Fts5Iter *apIter[1];
  5737. };
  5738. /*
  5739. ** The two input arrays - a1[] and a2[] - are in sorted order. This function
  5740. ** merges the two arrays together and writes the result to output array
  5741. ** aOut[]. aOut[] is guaranteed to be large enough to hold the result.
  5742. **
  5743. ** Duplicate entries are copied into the output. So the size of the output
  5744. ** array is always (n1+n2) entries.
  5745. */
  5746. static void fts5TokendataMerge(
  5747. Fts5TokenDataMap *a1, int n1, /* Input array 1 */
  5748. Fts5TokenDataMap *a2, int n2, /* Input array 2 */
  5749. Fts5TokenDataMap *aOut /* Output array */
  5750. ){
  5751. int i1 = 0;
  5752. int i2 = 0;
  5753. assert( n1>=0 && n2>=0 );
  5754. while( i1<n1 || i2<n2 ){
  5755. Fts5TokenDataMap *pOut = &aOut[i1+i2];
  5756. if( i2>=n2 || (i1<n1 && (
  5757. a1[i1].iRowid<a2[i2].iRowid
  5758. || (a1[i1].iRowid==a2[i2].iRowid && a1[i1].iPos<=a2[i2].iPos)
  5759. ))){
  5760. memcpy(pOut, &a1[i1], sizeof(Fts5TokenDataMap));
  5761. i1++;
  5762. }else{
  5763. memcpy(pOut, &a2[i2], sizeof(Fts5TokenDataMap));
  5764. i2++;
  5765. }
  5766. }
  5767. }
  5768. /*
  5769. ** Append a mapping to the token-map belonging to object pT.
  5770. */
  5771. static void fts5TokendataIterAppendMap(
  5772. Fts5Index *p,
  5773. Fts5TokenDataIter *pT,
  5774. int iIter,
  5775. int nByte,
  5776. i64 iRowid,
  5777. i64 iPos
  5778. ){
  5779. if( p->rc==SQLITE_OK ){
  5780. if( pT->nMap==pT->nMapAlloc ){
  5781. int nNew = pT->nMapAlloc ? pT->nMapAlloc*2 : 64;
  5782. int nAlloc = nNew * sizeof(Fts5TokenDataMap);
  5783. Fts5TokenDataMap *aNew;
  5784. aNew = (Fts5TokenDataMap*)sqlite3_realloc(pT->aMap, nAlloc);
  5785. if( aNew==0 ){
  5786. p->rc = SQLITE_NOMEM;
  5787. return;
  5788. }
  5789. pT->aMap = aNew;
  5790. pT->nMapAlloc = nNew;
  5791. }
  5792. pT->aMap[pT->nMap].iRowid = iRowid;
  5793. pT->aMap[pT->nMap].iPos = iPos;
  5794. pT->aMap[pT->nMap].iIter = iIter;
  5795. pT->aMap[pT->nMap].nByte = nByte;
  5796. pT->nMap++;
  5797. }
  5798. }
  5799. /*
  5800. ** Sort the contents of the pT->aMap[] array.
  5801. **
  5802. ** The sorting algorithm requries a malloc(). If this fails, an error code
  5803. ** is left in Fts5Index.rc before returning.
  5804. */
  5805. static void fts5TokendataIterSortMap(Fts5Index *p, Fts5TokenDataIter *pT){
  5806. Fts5TokenDataMap *aTmp = 0;
  5807. int nByte = pT->nMap * sizeof(Fts5TokenDataMap);
  5808. aTmp = (Fts5TokenDataMap*)sqlite3Fts5MallocZero(&p->rc, nByte);
  5809. if( aTmp ){
  5810. Fts5TokenDataMap *a1 = pT->aMap;
  5811. Fts5TokenDataMap *a2 = aTmp;
  5812. i64 nHalf;
  5813. for(nHalf=1; nHalf<pT->nMap; nHalf=nHalf*2){
  5814. int i1;
  5815. for(i1=0; i1<pT->nMap; i1+=(nHalf*2)){
  5816. int n1 = MIN(nHalf, pT->nMap-i1);
  5817. int n2 = MIN(nHalf, pT->nMap-i1-n1);
  5818. fts5TokendataMerge(&a1[i1], n1, &a1[i1+n1], n2, &a2[i1]);
  5819. }
  5820. SWAPVAL(Fts5TokenDataMap*, a1, a2);
  5821. }
  5822. if( a1!=pT->aMap ){
  5823. memcpy(pT->aMap, a1, pT->nMap*sizeof(Fts5TokenDataMap));
  5824. }
  5825. sqlite3_free(aTmp);
  5826. #ifdef SQLITE_DEBUG
  5827. {
  5828. int ii;
  5829. for(ii=1; ii<pT->nMap; ii++){
  5830. Fts5TokenDataMap *p1 = &pT->aMap[ii-1];
  5831. Fts5TokenDataMap *p2 = &pT->aMap[ii];
  5832. assert( p1->iRowid<p2->iRowid
  5833. || (p1->iRowid==p2->iRowid && p1->iPos<=p2->iPos)
  5834. );
  5835. }
  5836. }
  5837. #endif
  5838. }
  5839. }
  5840. /*
  5841. ** Delete an Fts5TokenDataIter structure and its contents.
  5842. */
  5843. static void fts5TokendataIterDelete(Fts5TokenDataIter *pSet){
  5844. if( pSet ){
  5845. int ii;
  5846. for(ii=0; ii<pSet->nIter; ii++){
  5847. fts5MultiIterFree(pSet->apIter[ii]);
  5848. }
  5849. fts5BufferFree(&pSet->terms);
  5850. sqlite3_free(pSet->aPoslistReader);
  5851. sqlite3_free(pSet->aMap);
  5852. sqlite3_free(pSet);
  5853. }
  5854. }
  5855. /*
  5856. ** fts5VisitEntries() context object used by fts5SetupPrefixIterTokendata()
  5857. ** to pass data to prefixIterSetupTokendataCb().
  5858. */
  5859. typedef struct TokendataSetupCtx TokendataSetupCtx;
  5860. struct TokendataSetupCtx {
  5861. Fts5TokenDataIter *pT; /* Object being populated with mappings */
  5862. int iTermOff; /* Offset of current term in terms.p[] */
  5863. int nTermByte; /* Size of current term in bytes */
  5864. };
  5865. /*
  5866. ** fts5VisitEntries() callback used by fts5SetupPrefixIterTokendata(). This
  5867. ** callback adds an entry to the Fts5TokenDataIter.aMap[] array for each
  5868. ** position in the current position-list. It doesn't matter that some of
  5869. ** these may be out of order - they will be sorted later.
  5870. */
  5871. static void prefixIterSetupTokendataCb(
  5872. Fts5Index *p,
  5873. void *pCtx,
  5874. Fts5Iter *p1,
  5875. const u8 *pNew,
  5876. int nNew
  5877. ){
  5878. TokendataSetupCtx *pSetup = (TokendataSetupCtx*)pCtx;
  5879. int iPosOff = 0;
  5880. i64 iPos = 0;
  5881. if( pNew ){
  5882. pSetup->nTermByte = nNew-1;
  5883. pSetup->iTermOff = pSetup->pT->terms.n;
  5884. fts5BufferAppendBlob(&p->rc, &pSetup->pT->terms, nNew-1, pNew+1);
  5885. }
  5886. while( 0==sqlite3Fts5PoslistNext64(
  5887. p1->base.pData, p1->base.nData, &iPosOff, &iPos
  5888. ) ){
  5889. fts5TokendataIterAppendMap(p,
  5890. pSetup->pT, pSetup->iTermOff, pSetup->nTermByte, p1->base.iRowid, iPos
  5891. );
  5892. }
  5893. }
  5894. /*
  5895. ** Context object passed by fts5SetupPrefixIter() to fts5VisitEntries().
  5896. */
  5897. typedef struct PrefixSetupCtx PrefixSetupCtx;
  5898. struct PrefixSetupCtx {
  5899. void (*xMerge)(Fts5Index*, Fts5Buffer*, int, Fts5Buffer*);
  5900. void (*xAppend)(Fts5Index*, u64, Fts5Iter*, Fts5Buffer*);
  5901. i64 iLastRowid;
  5902. int nMerge;
  5903. Fts5Buffer *aBuf;
  5904. int nBuf;
  5905. Fts5Buffer doclist;
  5906. TokendataSetupCtx *pTokendata;
  5907. };
  5908. /*
  5909. ** fts5VisitEntries() callback used by fts5SetupPrefixIter()
  5910. */
  5911. static void prefixIterSetupCb(
  5912. Fts5Index *p,
  5913. void *pCtx,
  5914. Fts5Iter *p1,
  5915. const u8 *pNew,
  5916. int nNew
  5917. ){
  5918. PrefixSetupCtx *pSetup = (PrefixSetupCtx*)pCtx;
  5919. const int nMerge = pSetup->nMerge;
  5920. if( p1->base.nData>0 ){
  5921. if( p1->base.iRowid<=pSetup->iLastRowid && pSetup->doclist.n>0 ){
  5922. int i;
  5923. for(i=0; p->rc==SQLITE_OK && pSetup->doclist.n; i++){
  5924. int i1 = i*nMerge;
  5925. int iStore;
  5926. assert( i1+nMerge<=pSetup->nBuf );
  5927. for(iStore=i1; iStore<i1+nMerge; iStore++){
  5928. if( pSetup->aBuf[iStore].n==0 ){
  5929. fts5BufferSwap(&pSetup->doclist, &pSetup->aBuf[iStore]);
  5930. fts5BufferZero(&pSetup->doclist);
  5931. break;
  5932. }
  5933. }
  5934. if( iStore==i1+nMerge ){
  5935. pSetup->xMerge(p, &pSetup->doclist, nMerge, &pSetup->aBuf[i1]);
  5936. for(iStore=i1; iStore<i1+nMerge; iStore++){
  5937. fts5BufferZero(&pSetup->aBuf[iStore]);
  5938. }
  5939. }
  5940. }
  5941. pSetup->iLastRowid = 0;
  5942. }
  5943. pSetup->xAppend(
  5944. p, (u64)p1->base.iRowid-(u64)pSetup->iLastRowid, p1, &pSetup->doclist
  5945. );
  5946. pSetup->iLastRowid = p1->base.iRowid;
  5947. }
  5948. if( pSetup->pTokendata ){
  5949. prefixIterSetupTokendataCb(p, (void*)pSetup->pTokendata, p1, pNew, nNew);
  5950. }
  5951. }
  5952. static void fts5SetupPrefixIter(
  5953. Fts5Index *p, /* Index to read from */
  5954. int bDesc, /* True for "ORDER BY rowid DESC" */
  5955. int iIdx, /* Index to scan for data */
  5956. u8 *pToken, /* Buffer containing prefix to match */
  5957. int nToken, /* Size of buffer pToken in bytes */
  5958. Fts5Colset *pColset, /* Restrict matches to these columns */
  5959. Fts5Iter **ppIter /* OUT: New iterator */
  5960. ){
  5961. Fts5Structure *pStruct;
  5962. PrefixSetupCtx s;
  5963. TokendataSetupCtx s2;
  5964. memset(&s, 0, sizeof(s));
  5965. memset(&s2, 0, sizeof(s2));
  5966. s.nMerge = 1;
  5967. s.iLastRowid = 0;
  5968. s.nBuf = 32;
  5969. if( iIdx==0
  5970. && p->pConfig->eDetail==FTS5_DETAIL_FULL
  5971. && p->pConfig->bPrefixInsttoken
  5972. ){
  5973. s.pTokendata = &s2;
  5974. s2.pT = (Fts5TokenDataIter*)fts5IdxMalloc(p, sizeof(*s2.pT));
  5975. }
  5976. if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
  5977. s.xMerge = fts5MergeRowidLists;
  5978. s.xAppend = fts5AppendRowid;
  5979. }else{
  5980. s.nMerge = FTS5_MERGE_NLIST-1;
  5981. s.nBuf = s.nMerge*8; /* Sufficient to merge (16^8)==(2^32) lists */
  5982. s.xMerge = fts5MergePrefixLists;
  5983. s.xAppend = fts5AppendPoslist;
  5984. }
  5985. s.aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*s.nBuf);
  5986. pStruct = fts5StructureRead(p);
  5987. assert( p->rc!=SQLITE_OK || (s.aBuf && pStruct) );
  5988. if( p->rc==SQLITE_OK ){
  5989. void *pCtx = (void*)&s;
  5990. int i;
  5991. Fts5Data *pData;
  5992. /* If iIdx is non-zero, then it is the number of a prefix-index for
  5993. ** prefixes 1 character longer than the prefix being queried for. That
  5994. ** index contains all the doclists required, except for the one
  5995. ** corresponding to the prefix itself. That one is extracted from the
  5996. ** main term index here. */
  5997. if( iIdx!=0 ){
  5998. pToken[0] = FTS5_MAIN_PREFIX;
  5999. fts5VisitEntries(p, pColset, pToken, nToken, 0, prefixIterSetupCb, pCtx);
  6000. }
  6001. pToken[0] = FTS5_MAIN_PREFIX + iIdx;
  6002. fts5VisitEntries(p, pColset, pToken, nToken, 1, prefixIterSetupCb, pCtx);
  6003. assert( (s.nBuf%s.nMerge)==0 );
  6004. for(i=0; i<s.nBuf; i+=s.nMerge){
  6005. int iFree;
  6006. if( p->rc==SQLITE_OK ){
  6007. s.xMerge(p, &s.doclist, s.nMerge, &s.aBuf[i]);
  6008. }
  6009. for(iFree=i; iFree<i+s.nMerge; iFree++){
  6010. fts5BufferFree(&s.aBuf[iFree]);
  6011. }
  6012. }
  6013. pData = fts5IdxMalloc(p, sizeof(*pData)+s.doclist.n+FTS5_DATA_ZERO_PADDING);
  6014. if( pData ){
  6015. pData->p = (u8*)&pData[1];
  6016. pData->nn = pData->szLeaf = s.doclist.n;
  6017. if( s.doclist.n ) memcpy(pData->p, s.doclist.p, s.doclist.n);
  6018. fts5MultiIterNew2(p, pData, bDesc, ppIter);
  6019. }
  6020. if( p->rc==SQLITE_OK && s.pTokendata ){
  6021. fts5TokendataIterSortMap(p, s2.pT);
  6022. (*ppIter)->pTokenDataIter = s2.pT;
  6023. s2.pT = 0;
  6024. }
  6025. }
  6026. fts5TokendataIterDelete(s2.pT);
  6027. fts5BufferFree(&s.doclist);
  6028. fts5StructureRelease(pStruct);
  6029. sqlite3_free(s.aBuf);
  6030. }
  6031. /*
  6032. ** Indicate that all subsequent calls to sqlite3Fts5IndexWrite() pertain
  6033. ** to the document with rowid iRowid.
  6034. */
  6035. int sqlite3Fts5IndexBeginWrite(Fts5Index *p, int bDelete, i64 iRowid){
  6036. assert( p->rc==SQLITE_OK );
  6037. /* Allocate the hash table if it has not already been allocated */
  6038. if( p->pHash==0 ){
  6039. p->rc = sqlite3Fts5HashNew(p->pConfig, &p->pHash, &p->nPendingData);
  6040. }
  6041. /* Flush the hash table to disk if required */
  6042. if( iRowid<p->iWriteRowid
  6043. || (iRowid==p->iWriteRowid && p->bDelete==0)
  6044. || (p->nPendingData > p->pConfig->nHashSize)
  6045. ){
  6046. fts5IndexFlush(p);
  6047. }
  6048. p->iWriteRowid = iRowid;
  6049. p->bDelete = bDelete;
  6050. if( bDelete==0 ){
  6051. p->nPendingRow++;
  6052. }
  6053. return fts5IndexReturn(p);
  6054. }
  6055. /*
  6056. ** Commit data to disk.
  6057. */
  6058. int sqlite3Fts5IndexSync(Fts5Index *p){
  6059. assert( p->rc==SQLITE_OK );
  6060. fts5IndexFlush(p);
  6061. sqlite3Fts5IndexCloseReader(p);
  6062. return fts5IndexReturn(p);
  6063. }
  6064. /*
  6065. ** Discard any data stored in the in-memory hash tables. Do not write it
  6066. ** to the database. Additionally, assume that the contents of the %_data
  6067. ** table may have changed on disk. So any in-memory caches of %_data
  6068. ** records must be invalidated.
  6069. */
  6070. int sqlite3Fts5IndexRollback(Fts5Index *p){
  6071. sqlite3Fts5IndexCloseReader(p);
  6072. fts5IndexDiscardData(p);
  6073. fts5StructureInvalidate(p);
  6074. /* assert( p->rc==SQLITE_OK ); */
  6075. return SQLITE_OK;
  6076. }
  6077. /*
  6078. ** The %_data table is completely empty when this function is called. This
  6079. ** function populates it with the initial structure objects for each index,
  6080. ** and the initial version of the "averages" record (a zero-byte blob).
  6081. */
  6082. int sqlite3Fts5IndexReinit(Fts5Index *p){
  6083. Fts5Structure s;
  6084. fts5StructureInvalidate(p);
  6085. fts5IndexDiscardData(p);
  6086. memset(&s, 0, sizeof(Fts5Structure));
  6087. if( p->pConfig->bContentlessDelete ){
  6088. s.nOriginCntr = 1;
  6089. }
  6090. fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0);
  6091. fts5StructureWrite(p, &s);
  6092. return fts5IndexReturn(p);
  6093. }
  6094. /*
  6095. ** Open a new Fts5Index handle. If the bCreate argument is true, create
  6096. ** and initialize the underlying %_data table.
  6097. **
  6098. ** If successful, set *pp to point to the new object and return SQLITE_OK.
  6099. ** Otherwise, set *pp to NULL and return an SQLite error code.
  6100. */
  6101. int sqlite3Fts5IndexOpen(
  6102. Fts5Config *pConfig,
  6103. int bCreate,
  6104. Fts5Index **pp,
  6105. char **pzErr
  6106. ){
  6107. int rc = SQLITE_OK;
  6108. Fts5Index *p; /* New object */
  6109. *pp = p = (Fts5Index*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Index));
  6110. if( rc==SQLITE_OK ){
  6111. p->pConfig = pConfig;
  6112. p->nWorkUnit = FTS5_WORK_UNIT;
  6113. p->zDataTbl = sqlite3Fts5Mprintf(&rc, "%s_data", pConfig->zName);
  6114. if( p->zDataTbl && bCreate ){
  6115. rc = sqlite3Fts5CreateTable(
  6116. pConfig, "data", "id INTEGER PRIMARY KEY, block BLOB", 0, pzErr
  6117. );
  6118. if( rc==SQLITE_OK ){
  6119. rc = sqlite3Fts5CreateTable(pConfig, "idx",
  6120. "segid, term, pgno, PRIMARY KEY(segid, term)",
  6121. 1, pzErr
  6122. );
  6123. }
  6124. if( rc==SQLITE_OK ){
  6125. rc = sqlite3Fts5IndexReinit(p);
  6126. }
  6127. }
  6128. }
  6129. assert( rc!=SQLITE_OK || p->rc==SQLITE_OK );
  6130. if( rc ){
  6131. sqlite3Fts5IndexClose(p);
  6132. *pp = 0;
  6133. }
  6134. return rc;
  6135. }
  6136. /*
  6137. ** Close a handle opened by an earlier call to sqlite3Fts5IndexOpen().
  6138. */
  6139. int sqlite3Fts5IndexClose(Fts5Index *p){
  6140. int rc = SQLITE_OK;
  6141. if( p ){
  6142. assert( p->pReader==0 );
  6143. fts5StructureInvalidate(p);
  6144. sqlite3_finalize(p->pWriter);
  6145. sqlite3_finalize(p->pDeleter);
  6146. sqlite3_finalize(p->pIdxWriter);
  6147. sqlite3_finalize(p->pIdxDeleter);
  6148. sqlite3_finalize(p->pIdxSelect);
  6149. sqlite3_finalize(p->pIdxNextSelect);
  6150. sqlite3_finalize(p->pDataVersion);
  6151. sqlite3_finalize(p->pDeleteFromIdx);
  6152. sqlite3Fts5HashFree(p->pHash);
  6153. sqlite3_free(p->zDataTbl);
  6154. sqlite3_free(p);
  6155. }
  6156. return rc;
  6157. }
  6158. /*
  6159. ** Argument p points to a buffer containing utf-8 text that is n bytes in
  6160. ** size. Return the number of bytes in the nChar character prefix of the
  6161. ** buffer, or 0 if there are less than nChar characters in total.
  6162. */
  6163. int sqlite3Fts5IndexCharlenToBytelen(
  6164. const char *p,
  6165. int nByte,
  6166. int nChar
  6167. ){
  6168. int n = 0;
  6169. int i;
  6170. for(i=0; i<nChar; i++){
  6171. if( n>=nByte ) return 0; /* Input contains fewer than nChar chars */
  6172. if( (unsigned char)p[n++]>=0xc0 ){
  6173. if( n>=nByte ) return 0;
  6174. while( (p[n] & 0xc0)==0x80 ){
  6175. n++;
  6176. if( n>=nByte ){
  6177. if( i+1==nChar ) break;
  6178. return 0;
  6179. }
  6180. }
  6181. }
  6182. }
  6183. return n;
  6184. }
  6185. /*
  6186. ** pIn is a UTF-8 encoded string, nIn bytes in size. Return the number of
  6187. ** unicode characters in the string.
  6188. */
  6189. static int fts5IndexCharlen(const char *pIn, int nIn){
  6190. int nChar = 0;
  6191. int i = 0;
  6192. while( i<nIn ){
  6193. if( (unsigned char)pIn[i++]>=0xc0 ){
  6194. while( i<nIn && (pIn[i] & 0xc0)==0x80 ) i++;
  6195. }
  6196. nChar++;
  6197. }
  6198. return nChar;
  6199. }
  6200. /*
  6201. ** Insert or remove data to or from the index. Each time a document is
  6202. ** added to or removed from the index, this function is called one or more
  6203. ** times.
  6204. **
  6205. ** For an insert, it must be called once for each token in the new document.
  6206. ** If the operation is a delete, it must be called (at least) once for each
  6207. ** unique token in the document with an iCol value less than zero. The iPos
  6208. ** argument is ignored for a delete.
  6209. */
  6210. int sqlite3Fts5IndexWrite(
  6211. Fts5Index *p, /* Index to write to */
  6212. int iCol, /* Column token appears in (-ve -> delete) */
  6213. int iPos, /* Position of token within column */
  6214. const char *pToken, int nToken /* Token to add or remove to or from index */
  6215. ){
  6216. int i; /* Used to iterate through indexes */
  6217. int rc = SQLITE_OK; /* Return code */
  6218. Fts5Config *pConfig = p->pConfig;
  6219. assert( p->rc==SQLITE_OK );
  6220. assert( (iCol<0)==p->bDelete );
  6221. /* Add the entry to the main terms index. */
  6222. rc = sqlite3Fts5HashWrite(
  6223. p->pHash, p->iWriteRowid, iCol, iPos, FTS5_MAIN_PREFIX, pToken, nToken
  6224. );
  6225. for(i=0; i<pConfig->nPrefix && rc==SQLITE_OK; i++){
  6226. const int nChar = pConfig->aPrefix[i];
  6227. int nByte = sqlite3Fts5IndexCharlenToBytelen(pToken, nToken, nChar);
  6228. if( nByte ){
  6229. rc = sqlite3Fts5HashWrite(p->pHash,
  6230. p->iWriteRowid, iCol, iPos, (char)(FTS5_MAIN_PREFIX+i+1), pToken,
  6231. nByte
  6232. );
  6233. }
  6234. }
  6235. return rc;
  6236. }
  6237. /*
  6238. ** pToken points to a buffer of size nToken bytes containing a search
  6239. ** term, including the index number at the start, used on a tokendata=1
  6240. ** table. This function returns true if the term in buffer pBuf matches
  6241. ** token pToken/nToken.
  6242. */
  6243. static int fts5IsTokendataPrefix(
  6244. Fts5Buffer *pBuf,
  6245. const u8 *pToken,
  6246. int nToken
  6247. ){
  6248. return (
  6249. pBuf->n>=nToken
  6250. && 0==memcmp(pBuf->p, pToken, nToken)
  6251. && (pBuf->n==nToken || pBuf->p[nToken]==0x00)
  6252. );
  6253. }
  6254. /*
  6255. ** Ensure the segment-iterator passed as the only argument points to EOF.
  6256. */
  6257. static void fts5SegIterSetEOF(Fts5SegIter *pSeg){
  6258. fts5DataRelease(pSeg->pLeaf);
  6259. pSeg->pLeaf = 0;
  6260. }
  6261. /*
  6262. ** This function appends iterator pAppend to Fts5TokenDataIter pIn and
  6263. ** returns the result.
  6264. */
  6265. static Fts5TokenDataIter *fts5AppendTokendataIter(
  6266. Fts5Index *p, /* Index object (for error code) */
  6267. Fts5TokenDataIter *pIn, /* Current Fts5TokenDataIter struct */
  6268. Fts5Iter *pAppend /* Append this iterator */
  6269. ){
  6270. Fts5TokenDataIter *pRet = pIn;
  6271. if( p->rc==SQLITE_OK ){
  6272. if( pIn==0 || pIn->nIter==pIn->nIterAlloc ){
  6273. int nAlloc = pIn ? pIn->nIterAlloc*2 : 16;
  6274. int nByte = nAlloc * sizeof(Fts5Iter*) + sizeof(Fts5TokenDataIter);
  6275. Fts5TokenDataIter *pNew = (Fts5TokenDataIter*)sqlite3_realloc(pIn, nByte);
  6276. if( pNew==0 ){
  6277. p->rc = SQLITE_NOMEM;
  6278. }else{
  6279. if( pIn==0 ) memset(pNew, 0, nByte);
  6280. pRet = pNew;
  6281. pNew->nIterAlloc = nAlloc;
  6282. }
  6283. }
  6284. }
  6285. if( p->rc ){
  6286. sqlite3Fts5IterClose((Fts5IndexIter*)pAppend);
  6287. }else{
  6288. pRet->apIter[pRet->nIter++] = pAppend;
  6289. }
  6290. assert( pRet==0 || pRet->nIter<=pRet->nIterAlloc );
  6291. return pRet;
  6292. }
  6293. /*
  6294. ** The iterator passed as the only argument must be a tokendata=1 iterator
  6295. ** (pIter->pTokenDataIter!=0). This function sets the iterator output
  6296. ** variables (pIter->base.*) according to the contents of the current
  6297. ** row.
  6298. */
  6299. static void fts5IterSetOutputsTokendata(Fts5Iter *pIter){
  6300. int ii;
  6301. int nHit = 0;
  6302. i64 iRowid = SMALLEST_INT64;
  6303. int iMin = 0;
  6304. Fts5TokenDataIter *pT = pIter->pTokenDataIter;
  6305. pIter->base.nData = 0;
  6306. pIter->base.pData = 0;
  6307. for(ii=0; ii<pT->nIter; ii++){
  6308. Fts5Iter *p = pT->apIter[ii];
  6309. if( p->base.bEof==0 ){
  6310. if( nHit==0 || p->base.iRowid<iRowid ){
  6311. iRowid = p->base.iRowid;
  6312. nHit = 1;
  6313. pIter->base.pData = p->base.pData;
  6314. pIter->base.nData = p->base.nData;
  6315. iMin = ii;
  6316. }else if( p->base.iRowid==iRowid ){
  6317. nHit++;
  6318. }
  6319. }
  6320. }
  6321. if( nHit==0 ){
  6322. pIter->base.bEof = 1;
  6323. }else{
  6324. int eDetail = pIter->pIndex->pConfig->eDetail;
  6325. pIter->base.bEof = 0;
  6326. pIter->base.iRowid = iRowid;
  6327. if( nHit==1 && eDetail==FTS5_DETAIL_FULL ){
  6328. fts5TokendataIterAppendMap(pIter->pIndex, pT, iMin, 0, iRowid, -1);
  6329. }else
  6330. if( nHit>1 && eDetail!=FTS5_DETAIL_NONE ){
  6331. int nReader = 0;
  6332. int nByte = 0;
  6333. i64 iPrev = 0;
  6334. /* Allocate array of iterators if they are not already allocated. */
  6335. if( pT->aPoslistReader==0 ){
  6336. pT->aPoslistReader = (Fts5PoslistReader*)sqlite3Fts5MallocZero(
  6337. &pIter->pIndex->rc,
  6338. pT->nIter * (sizeof(Fts5PoslistReader) + sizeof(int))
  6339. );
  6340. if( pT->aPoslistReader==0 ) return;
  6341. pT->aPoslistToIter = (int*)&pT->aPoslistReader[pT->nIter];
  6342. }
  6343. /* Populate an iterator for each poslist that will be merged */
  6344. for(ii=0; ii<pT->nIter; ii++){
  6345. Fts5Iter *p = pT->apIter[ii];
  6346. if( iRowid==p->base.iRowid ){
  6347. pT->aPoslistToIter[nReader] = ii;
  6348. sqlite3Fts5PoslistReaderInit(
  6349. p->base.pData, p->base.nData, &pT->aPoslistReader[nReader++]
  6350. );
  6351. nByte += p->base.nData;
  6352. }
  6353. }
  6354. /* Ensure the output buffer is large enough */
  6355. if( fts5BufferGrow(&pIter->pIndex->rc, &pIter->poslist, nByte+nHit*10) ){
  6356. return;
  6357. }
  6358. /* Ensure the token-mapping is large enough */
  6359. if( eDetail==FTS5_DETAIL_FULL && pT->nMapAlloc<(pT->nMap + nByte) ){
  6360. int nNew = (pT->nMapAlloc + nByte) * 2;
  6361. Fts5TokenDataMap *aNew = (Fts5TokenDataMap*)sqlite3_realloc(
  6362. pT->aMap, nNew*sizeof(Fts5TokenDataMap)
  6363. );
  6364. if( aNew==0 ){
  6365. pIter->pIndex->rc = SQLITE_NOMEM;
  6366. return;
  6367. }
  6368. pT->aMap = aNew;
  6369. pT->nMapAlloc = nNew;
  6370. }
  6371. pIter->poslist.n = 0;
  6372. while( 1 ){
  6373. i64 iMinPos = LARGEST_INT64;
  6374. /* Find smallest position */
  6375. iMin = 0;
  6376. for(ii=0; ii<nReader; ii++){
  6377. Fts5PoslistReader *pReader = &pT->aPoslistReader[ii];
  6378. if( pReader->bEof==0 ){
  6379. if( pReader->iPos<iMinPos ){
  6380. iMinPos = pReader->iPos;
  6381. iMin = ii;
  6382. }
  6383. }
  6384. }
  6385. /* If all readers were at EOF, break out of the loop. */
  6386. if( iMinPos==LARGEST_INT64 ) break;
  6387. sqlite3Fts5PoslistSafeAppend(&pIter->poslist, &iPrev, iMinPos);
  6388. sqlite3Fts5PoslistReaderNext(&pT->aPoslistReader[iMin]);
  6389. if( eDetail==FTS5_DETAIL_FULL ){
  6390. pT->aMap[pT->nMap].iPos = iMinPos;
  6391. pT->aMap[pT->nMap].iIter = pT->aPoslistToIter[iMin];
  6392. pT->aMap[pT->nMap].iRowid = iRowid;
  6393. pT->nMap++;
  6394. }
  6395. }
  6396. pIter->base.pData = pIter->poslist.p;
  6397. pIter->base.nData = pIter->poslist.n;
  6398. }
  6399. }
  6400. }
  6401. /*
  6402. ** The iterator passed as the only argument must be a tokendata=1 iterator
  6403. ** (pIter->pTokenDataIter!=0). This function advances the iterator. If
  6404. ** argument bFrom is false, then the iterator is advanced to the next
  6405. ** entry. Or, if bFrom is true, it is advanced to the first entry with
  6406. ** a rowid of iFrom or greater.
  6407. */
  6408. static void fts5TokendataIterNext(Fts5Iter *pIter, int bFrom, i64 iFrom){
  6409. int ii;
  6410. Fts5TokenDataIter *pT = pIter->pTokenDataIter;
  6411. Fts5Index *pIndex = pIter->pIndex;
  6412. for(ii=0; ii<pT->nIter; ii++){
  6413. Fts5Iter *p = pT->apIter[ii];
  6414. if( p->base.bEof==0
  6415. && (p->base.iRowid==pIter->base.iRowid || (bFrom && p->base.iRowid<iFrom))
  6416. ){
  6417. fts5MultiIterNext(pIndex, p, bFrom, iFrom);
  6418. while( bFrom && p->base.bEof==0
  6419. && p->base.iRowid<iFrom
  6420. && pIndex->rc==SQLITE_OK
  6421. ){
  6422. fts5MultiIterNext(pIndex, p, 0, 0);
  6423. }
  6424. }
  6425. }
  6426. if( pIndex->rc==SQLITE_OK ){
  6427. fts5IterSetOutputsTokendata(pIter);
  6428. }
  6429. }
  6430. /*
  6431. ** If the segment-iterator passed as the first argument is at EOF, then
  6432. ** set pIter->term to a copy of buffer pTerm.
  6433. */
  6434. static void fts5TokendataSetTermIfEof(Fts5Iter *pIter, Fts5Buffer *pTerm){
  6435. if( pIter && pIter->aSeg[0].pLeaf==0 ){
  6436. fts5BufferSet(&pIter->pIndex->rc, &pIter->aSeg[0].term, pTerm->n, pTerm->p);
  6437. }
  6438. }
  6439. /*
  6440. ** This function sets up an iterator to use for a non-prefix query on a
  6441. ** tokendata=1 table.
  6442. */
  6443. static Fts5Iter *fts5SetupTokendataIter(
  6444. Fts5Index *p, /* FTS index to query */
  6445. const u8 *pToken, /* Buffer containing query term */
  6446. int nToken, /* Size of buffer pToken in bytes */
  6447. Fts5Colset *pColset /* Colset to filter on */
  6448. ){
  6449. Fts5Iter *pRet = 0;
  6450. Fts5TokenDataIter *pSet = 0;
  6451. Fts5Structure *pStruct = 0;
  6452. const int flags = FTS5INDEX_QUERY_SCANONETERM | FTS5INDEX_QUERY_SCAN;
  6453. Fts5Buffer bSeek = {0, 0, 0};
  6454. Fts5Buffer *pSmall = 0;
  6455. fts5IndexFlush(p);
  6456. pStruct = fts5StructureRead(p);
  6457. while( p->rc==SQLITE_OK ){
  6458. Fts5Iter *pPrev = pSet ? pSet->apIter[pSet->nIter-1] : 0;
  6459. Fts5Iter *pNew = 0;
  6460. Fts5SegIter *pNewIter = 0;
  6461. Fts5SegIter *pPrevIter = 0;
  6462. int iLvl, iSeg, ii;
  6463. pNew = fts5MultiIterAlloc(p, pStruct->nSegment);
  6464. if( pSmall ){
  6465. fts5BufferSet(&p->rc, &bSeek, pSmall->n, pSmall->p);
  6466. fts5BufferAppendBlob(&p->rc, &bSeek, 1, (const u8*)"\0");
  6467. }else{
  6468. fts5BufferSet(&p->rc, &bSeek, nToken, pToken);
  6469. }
  6470. if( p->rc ){
  6471. sqlite3Fts5IterClose((Fts5IndexIter*)pNew);
  6472. break;
  6473. }
  6474. pNewIter = &pNew->aSeg[0];
  6475. pPrevIter = (pPrev ? &pPrev->aSeg[0] : 0);
  6476. for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
  6477. for(iSeg=pStruct->aLevel[iLvl].nSeg-1; iSeg>=0; iSeg--){
  6478. Fts5StructureSegment *pSeg = &pStruct->aLevel[iLvl].aSeg[iSeg];
  6479. int bDone = 0;
  6480. if( pPrevIter ){
  6481. if( fts5BufferCompare(pSmall, &pPrevIter->term) ){
  6482. memcpy(pNewIter, pPrevIter, sizeof(Fts5SegIter));
  6483. memset(pPrevIter, 0, sizeof(Fts5SegIter));
  6484. bDone = 1;
  6485. }else if( pPrevIter->iEndofDoclist>pPrevIter->pLeaf->szLeaf ){
  6486. fts5SegIterNextInit(p,(const char*)bSeek.p,bSeek.n-1,pSeg,pNewIter);
  6487. bDone = 1;
  6488. }
  6489. }
  6490. if( bDone==0 ){
  6491. fts5SegIterSeekInit(p, bSeek.p, bSeek.n, flags, pSeg, pNewIter);
  6492. }
  6493. if( pPrevIter ){
  6494. if( pPrevIter->pTombArray ){
  6495. pNewIter->pTombArray = pPrevIter->pTombArray;
  6496. pNewIter->pTombArray->nRef++;
  6497. }
  6498. }else{
  6499. fts5SegIterAllocTombstone(p, pNewIter);
  6500. }
  6501. pNewIter++;
  6502. if( pPrevIter ) pPrevIter++;
  6503. if( p->rc ) break;
  6504. }
  6505. }
  6506. fts5TokendataSetTermIfEof(pPrev, pSmall);
  6507. pNew->bSkipEmpty = 1;
  6508. pNew->pColset = pColset;
  6509. fts5IterSetOutputCb(&p->rc, pNew);
  6510. /* Loop through all segments in the new iterator. Find the smallest
  6511. ** term that any segment-iterator points to. Iterator pNew will be
  6512. ** used for this term. Also, set any iterator that points to a term that
  6513. ** does not match pToken/nToken to point to EOF */
  6514. pSmall = 0;
  6515. for(ii=0; ii<pNew->nSeg; ii++){
  6516. Fts5SegIter *pII = &pNew->aSeg[ii];
  6517. if( 0==fts5IsTokendataPrefix(&pII->term, pToken, nToken) ){
  6518. fts5SegIterSetEOF(pII);
  6519. }
  6520. if( pII->pLeaf && (!pSmall || fts5BufferCompare(pSmall, &pII->term)>0) ){
  6521. pSmall = &pII->term;
  6522. }
  6523. }
  6524. /* If pSmall is still NULL at this point, then the new iterator does
  6525. ** not point to any terms that match the query. So delete it and break
  6526. ** out of the loop - all required iterators have been collected. */
  6527. if( pSmall==0 ){
  6528. sqlite3Fts5IterClose((Fts5IndexIter*)pNew);
  6529. break;
  6530. }
  6531. /* Append this iterator to the set and continue. */
  6532. pSet = fts5AppendTokendataIter(p, pSet, pNew);
  6533. }
  6534. if( p->rc==SQLITE_OK && pSet ){
  6535. int ii;
  6536. for(ii=0; ii<pSet->nIter; ii++){
  6537. Fts5Iter *pIter = pSet->apIter[ii];
  6538. int iSeg;
  6539. for(iSeg=0; iSeg<pIter->nSeg; iSeg++){
  6540. pIter->aSeg[iSeg].flags |= FTS5_SEGITER_ONETERM;
  6541. }
  6542. fts5MultiIterFinishSetup(p, pIter);
  6543. }
  6544. }
  6545. if( p->rc==SQLITE_OK ){
  6546. pRet = fts5MultiIterAlloc(p, 0);
  6547. }
  6548. if( pRet ){
  6549. pRet->nSeg = 0;
  6550. pRet->pTokenDataIter = pSet;
  6551. if( pSet ){
  6552. fts5IterSetOutputsTokendata(pRet);
  6553. }else{
  6554. pRet->base.bEof = 1;
  6555. }
  6556. }else{
  6557. fts5TokendataIterDelete(pSet);
  6558. }
  6559. fts5StructureRelease(pStruct);
  6560. fts5BufferFree(&bSeek);
  6561. return pRet;
  6562. }
  6563. /*
  6564. ** Open a new iterator to iterate though all rowid that match the
  6565. ** specified token or token prefix.
  6566. */
  6567. int sqlite3Fts5IndexQuery(
  6568. Fts5Index *p, /* FTS index to query */
  6569. const char *pToken, int nToken, /* Token (or prefix) to query for */
  6570. int flags, /* Mask of FTS5INDEX_QUERY_X flags */
  6571. Fts5Colset *pColset, /* Match these columns only */
  6572. Fts5IndexIter **ppIter /* OUT: New iterator object */
  6573. ){
  6574. Fts5Config *pConfig = p->pConfig;
  6575. Fts5Iter *pRet = 0;
  6576. Fts5Buffer buf = {0, 0, 0};
  6577. /* If the QUERY_SCAN flag is set, all other flags must be clear. */
  6578. assert( (flags & FTS5INDEX_QUERY_SCAN)==0 || flags==FTS5INDEX_QUERY_SCAN );
  6579. if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){
  6580. int iIdx = 0; /* Index to search */
  6581. int iPrefixIdx = 0; /* +1 prefix index */
  6582. int bTokendata = pConfig->bTokendata;
  6583. if( nToken>0 ) memcpy(&buf.p[1], pToken, nToken);
  6584. /* The NOTOKENDATA flag is set when each token in a tokendata=1 table
  6585. ** should be treated individually, instead of merging all those with
  6586. ** a common prefix into a single entry. This is used, for example, by
  6587. ** queries performed as part of an integrity-check, or by the fts5vocab
  6588. ** module. */
  6589. if( flags & (FTS5INDEX_QUERY_NOTOKENDATA|FTS5INDEX_QUERY_SCAN) ){
  6590. bTokendata = 0;
  6591. }
  6592. /* Figure out which index to search and set iIdx accordingly. If this
  6593. ** is a prefix query for which there is no prefix index, set iIdx to
  6594. ** greater than pConfig->nPrefix to indicate that the query will be
  6595. ** satisfied by scanning multiple terms in the main index.
  6596. **
  6597. ** If the QUERY_TEST_NOIDX flag was specified, then this must be a
  6598. ** prefix-query. Instead of using a prefix-index (if one exists),
  6599. ** evaluate the prefix query using the main FTS index. This is used
  6600. ** for internal sanity checking by the integrity-check in debug
  6601. ** mode only. */
  6602. #ifdef SQLITE_DEBUG
  6603. if( pConfig->bPrefixIndex==0 || (flags & FTS5INDEX_QUERY_TEST_NOIDX) ){
  6604. assert( flags & FTS5INDEX_QUERY_PREFIX );
  6605. iIdx = 1+pConfig->nPrefix;
  6606. }else
  6607. #endif
  6608. if( flags & FTS5INDEX_QUERY_PREFIX ){
  6609. int nChar = fts5IndexCharlen(pToken, nToken);
  6610. for(iIdx=1; iIdx<=pConfig->nPrefix; iIdx++){
  6611. int nIdxChar = pConfig->aPrefix[iIdx-1];
  6612. if( nIdxChar==nChar ) break;
  6613. if( nIdxChar==nChar+1 ) iPrefixIdx = iIdx;
  6614. }
  6615. }
  6616. if( bTokendata && iIdx==0 ){
  6617. buf.p[0] = FTS5_MAIN_PREFIX;
  6618. pRet = fts5SetupTokendataIter(p, buf.p, nToken+1, pColset);
  6619. }else if( iIdx<=pConfig->nPrefix ){
  6620. /* Straight index lookup */
  6621. Fts5Structure *pStruct = fts5StructureRead(p);
  6622. buf.p[0] = (u8)(FTS5_MAIN_PREFIX + iIdx);
  6623. if( pStruct ){
  6624. fts5MultiIterNew(p, pStruct, flags | FTS5INDEX_QUERY_SKIPEMPTY,
  6625. pColset, buf.p, nToken+1, -1, 0, &pRet
  6626. );
  6627. fts5StructureRelease(pStruct);
  6628. }
  6629. }else{
  6630. /* Scan multiple terms in the main index for a prefix query. */
  6631. int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0;
  6632. fts5SetupPrefixIter(p, bDesc, iPrefixIdx, buf.p, nToken+1, pColset,&pRet);
  6633. if( pRet==0 ){
  6634. assert( p->rc!=SQLITE_OK );
  6635. }else{
  6636. assert( pRet->pColset==0 );
  6637. fts5IterSetOutputCb(&p->rc, pRet);
  6638. if( p->rc==SQLITE_OK ){
  6639. Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst];
  6640. if( pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg);
  6641. }
  6642. }
  6643. }
  6644. if( p->rc ){
  6645. sqlite3Fts5IterClose((Fts5IndexIter*)pRet);
  6646. pRet = 0;
  6647. sqlite3Fts5IndexCloseReader(p);
  6648. }
  6649. *ppIter = (Fts5IndexIter*)pRet;
  6650. sqlite3Fts5BufferFree(&buf);
  6651. }
  6652. return fts5IndexReturn(p);
  6653. }
  6654. /*
  6655. ** Return true if the iterator passed as the only argument is at EOF.
  6656. */
  6657. /*
  6658. ** Move to the next matching rowid.
  6659. */
  6660. int sqlite3Fts5IterNext(Fts5IndexIter *pIndexIter){
  6661. Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
  6662. assert( pIter->pIndex->rc==SQLITE_OK );
  6663. if( pIter->nSeg==0 ){
  6664. assert( pIter->pTokenDataIter );
  6665. fts5TokendataIterNext(pIter, 0, 0);
  6666. }else{
  6667. fts5MultiIterNext(pIter->pIndex, pIter, 0, 0);
  6668. }
  6669. return fts5IndexReturn(pIter->pIndex);
  6670. }
  6671. /*
  6672. ** Move to the next matching term/rowid. Used by the fts5vocab module.
  6673. */
  6674. int sqlite3Fts5IterNextScan(Fts5IndexIter *pIndexIter){
  6675. Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
  6676. Fts5Index *p = pIter->pIndex;
  6677. assert( pIter->pIndex->rc==SQLITE_OK );
  6678. fts5MultiIterNext(p, pIter, 0, 0);
  6679. if( p->rc==SQLITE_OK ){
  6680. Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
  6681. if( pSeg->pLeaf && pSeg->term.p[0]!=FTS5_MAIN_PREFIX ){
  6682. fts5DataRelease(pSeg->pLeaf);
  6683. pSeg->pLeaf = 0;
  6684. pIter->base.bEof = 1;
  6685. }
  6686. }
  6687. return fts5IndexReturn(pIter->pIndex);
  6688. }
  6689. /*
  6690. ** Move to the next matching rowid that occurs at or after iMatch. The
  6691. ** definition of "at or after" depends on whether this iterator iterates
  6692. ** in ascending or descending rowid order.
  6693. */
  6694. int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMatch){
  6695. Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
  6696. if( pIter->nSeg==0 ){
  6697. assert( pIter->pTokenDataIter );
  6698. fts5TokendataIterNext(pIter, 1, iMatch);
  6699. }else{
  6700. fts5MultiIterNextFrom(pIter->pIndex, pIter, iMatch);
  6701. }
  6702. return fts5IndexReturn(pIter->pIndex);
  6703. }
  6704. /*
  6705. ** Return the current term.
  6706. */
  6707. const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIndexIter, int *pn){
  6708. int n;
  6709. const char *z = (const char*)fts5MultiIterTerm((Fts5Iter*)pIndexIter, &n);
  6710. assert_nc( z || n<=1 );
  6711. *pn = n-1;
  6712. return (z ? &z[1] : 0);
  6713. }
  6714. /*
  6715. ** pIter is a prefix query. This function populates pIter->pTokenDataIter
  6716. ** with an Fts5TokenDataIter object containing mappings for all rows
  6717. ** matched by the query.
  6718. */
  6719. static int fts5SetupPrefixIterTokendata(
  6720. Fts5Iter *pIter,
  6721. const char *pToken, /* Token prefix to search for */
  6722. int nToken /* Size of pToken in bytes */
  6723. ){
  6724. Fts5Index *p = pIter->pIndex;
  6725. Fts5Buffer token = {0, 0, 0};
  6726. TokendataSetupCtx ctx;
  6727. memset(&ctx, 0, sizeof(ctx));
  6728. fts5BufferGrow(&p->rc, &token, nToken+1);
  6729. ctx.pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc, sizeof(*ctx.pT));
  6730. if( p->rc==SQLITE_OK ){
  6731. /* Fill in the token prefix to search for */
  6732. token.p[0] = FTS5_MAIN_PREFIX;
  6733. memcpy(&token.p[1], pToken, nToken);
  6734. token.n = nToken+1;
  6735. fts5VisitEntries(
  6736. p, 0, token.p, token.n, 1, prefixIterSetupTokendataCb, (void*)&ctx
  6737. );
  6738. fts5TokendataIterSortMap(p, ctx.pT);
  6739. }
  6740. if( p->rc==SQLITE_OK ){
  6741. pIter->pTokenDataIter = ctx.pT;
  6742. }else{
  6743. fts5TokendataIterDelete(ctx.pT);
  6744. }
  6745. fts5BufferFree(&token);
  6746. return fts5IndexReturn(p);
  6747. }
  6748. /*
  6749. ** This is used by xInstToken() to access the token at offset iOff, column
  6750. ** iCol of row iRowid. The token is returned via output variables *ppOut
  6751. ** and *pnOut. The iterator passed as the first argument must be a tokendata=1
  6752. ** iterator (pIter->pTokenDataIter!=0).
  6753. **
  6754. ** pToken/nToken:
  6755. */
  6756. int sqlite3Fts5IterToken(
  6757. Fts5IndexIter *pIndexIter,
  6758. const char *pToken, int nToken,
  6759. i64 iRowid,
  6760. int iCol,
  6761. int iOff,
  6762. const char **ppOut, int *pnOut
  6763. ){
  6764. Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
  6765. Fts5TokenDataIter *pT = pIter->pTokenDataIter;
  6766. i64 iPos = (((i64)iCol)<<32) + iOff;
  6767. Fts5TokenDataMap *aMap = 0;
  6768. int i1 = 0;
  6769. int i2 = 0;
  6770. int iTest = 0;
  6771. assert( pT || (pToken && pIter->nSeg>0) );
  6772. if( pT==0 ){
  6773. int rc = fts5SetupPrefixIterTokendata(pIter, pToken, nToken);
  6774. if( rc!=SQLITE_OK ) return rc;
  6775. pT = pIter->pTokenDataIter;
  6776. }
  6777. i2 = pT->nMap;
  6778. aMap = pT->aMap;
  6779. while( i2>i1 ){
  6780. iTest = (i1 + i2) / 2;
  6781. if( aMap[iTest].iRowid<iRowid ){
  6782. i1 = iTest+1;
  6783. }else if( aMap[iTest].iRowid>iRowid ){
  6784. i2 = iTest;
  6785. }else{
  6786. if( aMap[iTest].iPos<iPos ){
  6787. if( aMap[iTest].iPos<0 ){
  6788. break;
  6789. }
  6790. i1 = iTest+1;
  6791. }else if( aMap[iTest].iPos>iPos ){
  6792. i2 = iTest;
  6793. }else{
  6794. break;
  6795. }
  6796. }
  6797. }
  6798. if( i2>i1 ){
  6799. if( pIter->nSeg==0 ){
  6800. Fts5Iter *pMap = pT->apIter[aMap[iTest].iIter];
  6801. *ppOut = (const char*)pMap->aSeg[0].term.p+1;
  6802. *pnOut = pMap->aSeg[0].term.n-1;
  6803. }else{
  6804. Fts5TokenDataMap *p = &aMap[iTest];
  6805. *ppOut = (const char*)&pT->terms.p[p->iIter];
  6806. *pnOut = aMap[iTest].nByte;
  6807. }
  6808. }
  6809. return SQLITE_OK;
  6810. }
  6811. /*
  6812. ** Clear any existing entries from the token-map associated with the
  6813. ** iterator passed as the only argument.
  6814. */
  6815. void sqlite3Fts5IndexIterClearTokendata(Fts5IndexIter *pIndexIter){
  6816. Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
  6817. if( pIter && pIter->pTokenDataIter
  6818. && (pIter->nSeg==0 || pIter->pIndex->pConfig->eDetail!=FTS5_DETAIL_FULL)
  6819. ){
  6820. pIter->pTokenDataIter->nMap = 0;
  6821. }
  6822. }
  6823. /*
  6824. ** Set a token-mapping for the iterator passed as the first argument. This
  6825. ** is used in detail=column or detail=none mode when a token is requested
  6826. ** using the xInstToken() API. In this case the caller tokenizers the
  6827. ** current row and configures the token-mapping via multiple calls to this
  6828. ** function.
  6829. */
  6830. int sqlite3Fts5IndexIterWriteTokendata(
  6831. Fts5IndexIter *pIndexIter,
  6832. const char *pToken, int nToken,
  6833. i64 iRowid, int iCol, int iOff
  6834. ){
  6835. Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
  6836. Fts5TokenDataIter *pT = pIter->pTokenDataIter;
  6837. Fts5Index *p = pIter->pIndex;
  6838. i64 iPos = (((i64)iCol)<<32) + iOff;
  6839. assert( p->pConfig->eDetail!=FTS5_DETAIL_FULL );
  6840. assert( pIter->pTokenDataIter || pIter->nSeg>0 );
  6841. if( pIter->nSeg>0 ){
  6842. /* This is a prefix term iterator. */
  6843. if( pT==0 ){
  6844. pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc, sizeof(*pT));
  6845. pIter->pTokenDataIter = pT;
  6846. }
  6847. if( pT ){
  6848. fts5TokendataIterAppendMap(p, pT, pT->terms.n, nToken, iRowid, iPos);
  6849. fts5BufferAppendBlob(&p->rc, &pT->terms, nToken, (const u8*)pToken);
  6850. }
  6851. }else{
  6852. int ii;
  6853. for(ii=0; ii<pT->nIter; ii++){
  6854. Fts5Buffer *pTerm = &pT->apIter[ii]->aSeg[0].term;
  6855. if( nToken==pTerm->n-1 && memcmp(pToken, pTerm->p+1, nToken)==0 ) break;
  6856. }
  6857. if( ii<pT->nIter ){
  6858. fts5TokendataIterAppendMap(p, pT, ii, 0, iRowid, iPos);
  6859. }
  6860. }
  6861. return fts5IndexReturn(p);
  6862. }
  6863. /*
  6864. ** Close an iterator opened by an earlier call to sqlite3Fts5IndexQuery().
  6865. */
  6866. void sqlite3Fts5IterClose(Fts5IndexIter *pIndexIter){
  6867. if( pIndexIter ){
  6868. Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
  6869. Fts5Index *pIndex = pIter->pIndex;
  6870. fts5TokendataIterDelete(pIter->pTokenDataIter);
  6871. fts5MultiIterFree(pIter);
  6872. sqlite3Fts5IndexCloseReader(pIndex);
  6873. }
  6874. }
  6875. /*
  6876. ** Read and decode the "averages" record from the database.
  6877. **
  6878. ** Parameter anSize must point to an array of size nCol, where nCol is
  6879. ** the number of user defined columns in the FTS table.
  6880. */
  6881. int sqlite3Fts5IndexGetAverages(Fts5Index *p, i64 *pnRow, i64 *anSize){
  6882. int nCol = p->pConfig->nCol;
  6883. Fts5Data *pData;
  6884. *pnRow = 0;
  6885. memset(anSize, 0, sizeof(i64) * nCol);
  6886. pData = fts5DataRead(p, FTS5_AVERAGES_ROWID);
  6887. if( p->rc==SQLITE_OK && pData->nn ){
  6888. int i = 0;
  6889. int iCol;
  6890. i += fts5GetVarint(&pData->p[i], (u64*)pnRow);
  6891. for(iCol=0; i<pData->nn && iCol<nCol; iCol++){
  6892. i += fts5GetVarint(&pData->p[i], (u64*)&anSize[iCol]);
  6893. }
  6894. }
  6895. fts5DataRelease(pData);
  6896. return fts5IndexReturn(p);
  6897. }
  6898. /*
  6899. ** Replace the current "averages" record with the contents of the buffer
  6900. ** supplied as the second argument.
  6901. */
  6902. int sqlite3Fts5IndexSetAverages(Fts5Index *p, const u8 *pData, int nData){
  6903. assert( p->rc==SQLITE_OK );
  6904. fts5DataWrite(p, FTS5_AVERAGES_ROWID, pData, nData);
  6905. return fts5IndexReturn(p);
  6906. }
  6907. /*
  6908. ** Return the total number of blocks this module has read from the %_data
  6909. ** table since it was created.
  6910. */
  6911. int sqlite3Fts5IndexReads(Fts5Index *p){
  6912. return p->nRead;
  6913. }
  6914. /*
  6915. ** Set the 32-bit cookie value stored at the start of all structure
  6916. ** records to the value passed as the second argument.
  6917. **
  6918. ** Return SQLITE_OK if successful, or an SQLite error code if an error
  6919. ** occurs.
  6920. */
  6921. int sqlite3Fts5IndexSetCookie(Fts5Index *p, int iNew){
  6922. int rc; /* Return code */
  6923. Fts5Config *pConfig = p->pConfig; /* Configuration object */
  6924. u8 aCookie[4]; /* Binary representation of iNew */
  6925. sqlite3_blob *pBlob = 0;
  6926. assert( p->rc==SQLITE_OK );
  6927. sqlite3Fts5Put32(aCookie, iNew);
  6928. rc = sqlite3_blob_open(pConfig->db, pConfig->zDb, p->zDataTbl,
  6929. "block", FTS5_STRUCTURE_ROWID, 1, &pBlob
  6930. );
  6931. if( rc==SQLITE_OK ){
  6932. sqlite3_blob_write(pBlob, aCookie, 4, 0);
  6933. rc = sqlite3_blob_close(pBlob);
  6934. }
  6935. return rc;
  6936. }
  6937. int sqlite3Fts5IndexLoadConfig(Fts5Index *p){
  6938. Fts5Structure *pStruct;
  6939. pStruct = fts5StructureRead(p);
  6940. fts5StructureRelease(pStruct);
  6941. return fts5IndexReturn(p);
  6942. }
  6943. /*
  6944. ** Retrieve the origin value that will be used for the segment currently
  6945. ** being accumulated in the in-memory hash table when it is flushed to
  6946. ** disk. If successful, SQLITE_OK is returned and (*piOrigin) set to
  6947. ** the queried value. Or, if an error occurs, an error code is returned
  6948. ** and the final value of (*piOrigin) is undefined.
  6949. */
  6950. int sqlite3Fts5IndexGetOrigin(Fts5Index *p, i64 *piOrigin){
  6951. Fts5Structure *pStruct;
  6952. pStruct = fts5StructureRead(p);
  6953. if( pStruct ){
  6954. *piOrigin = pStruct->nOriginCntr;
  6955. fts5StructureRelease(pStruct);
  6956. }
  6957. return fts5IndexReturn(p);
  6958. }
  6959. /*
  6960. ** Buffer pPg contains a page of a tombstone hash table - one of nPg pages
  6961. ** associated with the same segment. This function adds rowid iRowid to
  6962. ** the hash table. The caller is required to guarantee that there is at
  6963. ** least one free slot on the page.
  6964. **
  6965. ** If parameter bForce is false and the hash table is deemed to be full
  6966. ** (more than half of the slots are occupied), then non-zero is returned
  6967. ** and iRowid not inserted. Or, if bForce is true or if the hash table page
  6968. ** is not full, iRowid is inserted and zero returned.
  6969. */
  6970. static int fts5IndexTombstoneAddToPage(
  6971. Fts5Data *pPg,
  6972. int bForce,
  6973. int nPg,
  6974. u64 iRowid
  6975. ){
  6976. const int szKey = TOMBSTONE_KEYSIZE(pPg);
  6977. const int nSlot = TOMBSTONE_NSLOT(pPg);
  6978. const int nElem = fts5GetU32(&pPg->p[4]);
  6979. int iSlot = (iRowid / nPg) % nSlot;
  6980. int nCollide = nSlot;
  6981. if( szKey==4 && iRowid>0xFFFFFFFF ) return 2;
  6982. if( iRowid==0 ){
  6983. pPg->p[1] = 0x01;
  6984. return 0;
  6985. }
  6986. if( bForce==0 && nElem>=(nSlot/2) ){
  6987. return 1;
  6988. }
  6989. fts5PutU32(&pPg->p[4], nElem+1);
  6990. if( szKey==4 ){
  6991. u32 *aSlot = (u32*)&pPg->p[8];
  6992. while( aSlot[iSlot] ){
  6993. iSlot = (iSlot + 1) % nSlot;
  6994. if( nCollide--==0 ) return 0;
  6995. }
  6996. fts5PutU32((u8*)&aSlot[iSlot], (u32)iRowid);
  6997. }else{
  6998. u64 *aSlot = (u64*)&pPg->p[8];
  6999. while( aSlot[iSlot] ){
  7000. iSlot = (iSlot + 1) % nSlot;
  7001. if( nCollide--==0 ) return 0;
  7002. }
  7003. fts5PutU64((u8*)&aSlot[iSlot], iRowid);
  7004. }
  7005. return 0;
  7006. }
  7007. /*
  7008. ** This function attempts to build a new hash containing all the keys
  7009. ** currently in the tombstone hash table for segment pSeg. The new
  7010. ** hash will be stored in the nOut buffers passed in array apOut[].
  7011. ** All pages of the new hash use key-size szKey (4 or 8).
  7012. **
  7013. ** Return 0 if the hash is successfully rebuilt into the nOut pages.
  7014. ** Or non-zero if it is not (because one page became overfull). In this
  7015. ** case the caller should retry with a larger nOut parameter.
  7016. **
  7017. ** Parameter pData1 is page iPg1 of the hash table being rebuilt.
  7018. */
  7019. static int fts5IndexTombstoneRehash(
  7020. Fts5Index *p,
  7021. Fts5StructureSegment *pSeg, /* Segment to rebuild hash of */
  7022. Fts5Data *pData1, /* One page of current hash - or NULL */
  7023. int iPg1, /* Which page of the current hash is pData1 */
  7024. int szKey, /* 4 or 8, the keysize */
  7025. int nOut, /* Number of output pages */
  7026. Fts5Data **apOut /* Array of output hash pages */
  7027. ){
  7028. int ii;
  7029. int res = 0;
  7030. /* Initialize the headers of all the output pages */
  7031. for(ii=0; ii<nOut; ii++){
  7032. apOut[ii]->p[0] = szKey;
  7033. fts5PutU32(&apOut[ii]->p[4], 0);
  7034. }
  7035. /* Loop through the current pages of the hash table. */
  7036. for(ii=0; res==0 && ii<pSeg->nPgTombstone; ii++){
  7037. Fts5Data *pData = 0; /* Page ii of the current hash table */
  7038. Fts5Data *pFree = 0; /* Free this at the end of the loop */
  7039. if( iPg1==ii ){
  7040. pData = pData1;
  7041. }else{
  7042. pFree = pData = fts5DataRead(p, FTS5_TOMBSTONE_ROWID(pSeg->iSegid, ii));
  7043. }
  7044. if( pData ){
  7045. int szKeyIn = TOMBSTONE_KEYSIZE(pData);
  7046. int nSlotIn = (pData->nn - 8) / szKeyIn;
  7047. int iIn;
  7048. for(iIn=0; iIn<nSlotIn; iIn++){
  7049. u64 iVal = 0;
  7050. /* Read the value from slot iIn of the input page into iVal. */
  7051. if( szKeyIn==4 ){
  7052. u32 *aSlot = (u32*)&pData->p[8];
  7053. if( aSlot[iIn] ) iVal = fts5GetU32((u8*)&aSlot[iIn]);
  7054. }else{
  7055. u64 *aSlot = (u64*)&pData->p[8];
  7056. if( aSlot[iIn] ) iVal = fts5GetU64((u8*)&aSlot[iIn]);
  7057. }
  7058. /* If iVal is not 0 at this point, insert it into the new hash table */
  7059. if( iVal ){
  7060. Fts5Data *pPg = apOut[(iVal % nOut)];
  7061. res = fts5IndexTombstoneAddToPage(pPg, 0, nOut, iVal);
  7062. if( res ) break;
  7063. }
  7064. }
  7065. /* If this is page 0 of the old hash, copy the rowid-0-flag from the
  7066. ** old hash to the new. */
  7067. if( ii==0 ){
  7068. apOut[0]->p[1] = pData->p[1];
  7069. }
  7070. }
  7071. fts5DataRelease(pFree);
  7072. }
  7073. return res;
  7074. }
  7075. /*
  7076. ** This is called to rebuild the hash table belonging to segment pSeg.
  7077. ** If parameter pData1 is not NULL, then one page of the existing hash table
  7078. ** has already been loaded - pData1, which is page iPg1. The key-size for
  7079. ** the new hash table is szKey (4 or 8).
  7080. **
  7081. ** If successful, the new hash table is not written to disk. Instead,
  7082. ** output parameter (*pnOut) is set to the number of pages in the new
  7083. ** hash table, and (*papOut) to point to an array of buffers containing
  7084. ** the new page data.
  7085. **
  7086. ** If an error occurs, an error code is left in the Fts5Index object and
  7087. ** both output parameters set to 0 before returning.
  7088. */
  7089. static void fts5IndexTombstoneRebuild(
  7090. Fts5Index *p,
  7091. Fts5StructureSegment *pSeg, /* Segment to rebuild hash of */
  7092. Fts5Data *pData1, /* One page of current hash - or NULL */
  7093. int iPg1, /* Which page of the current hash is pData1 */
  7094. int szKey, /* 4 or 8, the keysize */
  7095. int *pnOut, /* OUT: Number of output pages */
  7096. Fts5Data ***papOut /* OUT: Output hash pages */
  7097. ){
  7098. const int MINSLOT = 32;
  7099. int nSlotPerPage = MAX(MINSLOT, (p->pConfig->pgsz - 8) / szKey);
  7100. int nSlot = 0; /* Number of slots in each output page */
  7101. int nOut = 0;
  7102. /* Figure out how many output pages (nOut) and how many slots per
  7103. ** page (nSlot). There are three possibilities:
  7104. **
  7105. ** 1. The hash table does not yet exist. In this case the new hash
  7106. ** table will consist of a single page with MINSLOT slots.
  7107. **
  7108. ** 2. The hash table exists but is currently a single page. In this
  7109. ** case an attempt is made to grow the page to accommodate the new
  7110. ** entry. The page is allowed to grow up to nSlotPerPage (see above)
  7111. ** slots.
  7112. **
  7113. ** 3. The hash table already consists of more than one page, or of
  7114. ** a single page already so large that it cannot be grown. In this
  7115. ** case the new hash consists of (nPg*2+1) pages of nSlotPerPage
  7116. ** slots each, where nPg is the current number of pages in the
  7117. ** hash table.
  7118. */
  7119. if( pSeg->nPgTombstone==0 ){
  7120. /* Case 1. */
  7121. nOut = 1;
  7122. nSlot = MINSLOT;
  7123. }else if( pSeg->nPgTombstone==1 ){
  7124. /* Case 2. */
  7125. int nElem = (int)fts5GetU32(&pData1->p[4]);
  7126. assert( pData1 && iPg1==0 );
  7127. nOut = 1;
  7128. nSlot = MAX(nElem*4, MINSLOT);
  7129. if( nSlot>nSlotPerPage ) nOut = 0;
  7130. }
  7131. if( nOut==0 ){
  7132. /* Case 3. */
  7133. nOut = (pSeg->nPgTombstone * 2 + 1);
  7134. nSlot = nSlotPerPage;
  7135. }
  7136. /* Allocate the required array and output pages */
  7137. while( 1 ){
  7138. int res = 0;
  7139. int ii = 0;
  7140. int szPage = 0;
  7141. Fts5Data **apOut = 0;
  7142. /* Allocate space for the new hash table */
  7143. assert( nSlot>=MINSLOT );
  7144. apOut = (Fts5Data**)sqlite3Fts5MallocZero(&p->rc, sizeof(Fts5Data*) * nOut);
  7145. szPage = 8 + nSlot*szKey;
  7146. for(ii=0; ii<nOut; ii++){
  7147. Fts5Data *pNew = (Fts5Data*)sqlite3Fts5MallocZero(&p->rc,
  7148. sizeof(Fts5Data)+szPage
  7149. );
  7150. if( pNew ){
  7151. pNew->nn = szPage;
  7152. pNew->p = (u8*)&pNew[1];
  7153. apOut[ii] = pNew;
  7154. }
  7155. }
  7156. /* Rebuild the hash table. */
  7157. if( p->rc==SQLITE_OK ){
  7158. res = fts5IndexTombstoneRehash(p, pSeg, pData1, iPg1, szKey, nOut, apOut);
  7159. }
  7160. if( res==0 ){
  7161. if( p->rc ){
  7162. fts5IndexFreeArray(apOut, nOut);
  7163. apOut = 0;
  7164. nOut = 0;
  7165. }
  7166. *pnOut = nOut;
  7167. *papOut = apOut;
  7168. break;
  7169. }
  7170. /* If control flows to here, it was not possible to rebuild the hash
  7171. ** table. Free all buffers and then try again with more pages. */
  7172. assert( p->rc==SQLITE_OK );
  7173. fts5IndexFreeArray(apOut, nOut);
  7174. nSlot = nSlotPerPage;
  7175. nOut = nOut*2 + 1;
  7176. }
  7177. }
  7178. /*
  7179. ** Add a tombstone for rowid iRowid to segment pSeg.
  7180. */
  7181. static void fts5IndexTombstoneAdd(
  7182. Fts5Index *p,
  7183. Fts5StructureSegment *pSeg,
  7184. u64 iRowid
  7185. ){
  7186. Fts5Data *pPg = 0;
  7187. int iPg = -1;
  7188. int szKey = 0;
  7189. int nHash = 0;
  7190. Fts5Data **apHash = 0;
  7191. p->nContentlessDelete++;
  7192. if( pSeg->nPgTombstone>0 ){
  7193. iPg = iRowid % pSeg->nPgTombstone;
  7194. pPg = fts5DataRead(p, FTS5_TOMBSTONE_ROWID(pSeg->iSegid,iPg));
  7195. if( pPg==0 ){
  7196. assert( p->rc!=SQLITE_OK );
  7197. return;
  7198. }
  7199. if( 0==fts5IndexTombstoneAddToPage(pPg, 0, pSeg->nPgTombstone, iRowid) ){
  7200. fts5DataWrite(p, FTS5_TOMBSTONE_ROWID(pSeg->iSegid,iPg), pPg->p, pPg->nn);
  7201. fts5DataRelease(pPg);
  7202. return;
  7203. }
  7204. }
  7205. /* Have to rebuild the hash table. First figure out the key-size (4 or 8). */
  7206. szKey = pPg ? TOMBSTONE_KEYSIZE(pPg) : 4;
  7207. if( iRowid>0xFFFFFFFF ) szKey = 8;
  7208. /* Rebuild the hash table */
  7209. fts5IndexTombstoneRebuild(p, pSeg, pPg, iPg, szKey, &nHash, &apHash);
  7210. assert( p->rc==SQLITE_OK || (nHash==0 && apHash==0) );
  7211. /* If all has succeeded, write the new rowid into one of the new hash
  7212. ** table pages, then write them all out to disk. */
  7213. if( nHash ){
  7214. int ii = 0;
  7215. fts5IndexTombstoneAddToPage(apHash[iRowid % nHash], 1, nHash, iRowid);
  7216. for(ii=0; ii<nHash; ii++){
  7217. i64 iTombstoneRowid = FTS5_TOMBSTONE_ROWID(pSeg->iSegid, ii);
  7218. fts5DataWrite(p, iTombstoneRowid, apHash[ii]->p, apHash[ii]->nn);
  7219. }
  7220. pSeg->nPgTombstone = nHash;
  7221. fts5StructureWrite(p, p->pStruct);
  7222. }
  7223. fts5DataRelease(pPg);
  7224. fts5IndexFreeArray(apHash, nHash);
  7225. }
  7226. /*
  7227. ** Add iRowid to the tombstone list of the segment or segments that contain
  7228. ** rows from origin iOrigin. Return SQLITE_OK if successful, or an SQLite
  7229. ** error code otherwise.
  7230. */
  7231. int sqlite3Fts5IndexContentlessDelete(Fts5Index *p, i64 iOrigin, i64 iRowid){
  7232. Fts5Structure *pStruct;
  7233. pStruct = fts5StructureRead(p);
  7234. if( pStruct ){
  7235. int bFound = 0; /* True after pSeg->nEntryTombstone incr. */
  7236. int iLvl;
  7237. for(iLvl=pStruct->nLevel-1; iLvl>=0; iLvl--){
  7238. int iSeg;
  7239. for(iSeg=pStruct->aLevel[iLvl].nSeg-1; iSeg>=0; iSeg--){
  7240. Fts5StructureSegment *pSeg = &pStruct->aLevel[iLvl].aSeg[iSeg];
  7241. if( pSeg->iOrigin1<=(u64)iOrigin && pSeg->iOrigin2>=(u64)iOrigin ){
  7242. if( bFound==0 ){
  7243. pSeg->nEntryTombstone++;
  7244. bFound = 1;
  7245. }
  7246. fts5IndexTombstoneAdd(p, pSeg, iRowid);
  7247. }
  7248. }
  7249. }
  7250. fts5StructureRelease(pStruct);
  7251. }
  7252. return fts5IndexReturn(p);
  7253. }
  7254. /*************************************************************************
  7255. **************************************************************************
  7256. ** Below this point is the implementation of the integrity-check
  7257. ** functionality.
  7258. */
  7259. /*
  7260. ** Return a simple checksum value based on the arguments.
  7261. */
  7262. u64 sqlite3Fts5IndexEntryCksum(
  7263. i64 iRowid,
  7264. int iCol,
  7265. int iPos,
  7266. int iIdx,
  7267. const char *pTerm,
  7268. int nTerm
  7269. ){
  7270. int i;
  7271. u64 ret = iRowid;
  7272. ret += (ret<<3) + iCol;
  7273. ret += (ret<<3) + iPos;
  7274. if( iIdx>=0 ) ret += (ret<<3) + (FTS5_MAIN_PREFIX + iIdx);
  7275. for(i=0; i<nTerm; i++) ret += (ret<<3) + pTerm[i];
  7276. return ret;
  7277. }
  7278. #ifdef SQLITE_DEBUG
  7279. /*
  7280. ** This function is purely an internal test. It does not contribute to
  7281. ** FTS functionality, or even the integrity-check, in any way.
  7282. **
  7283. ** Instead, it tests that the same set of pgno/rowid combinations are
  7284. ** visited regardless of whether the doclist-index identified by parameters
  7285. ** iSegid/iLeaf is iterated in forwards or reverse order.
  7286. */
  7287. static void fts5TestDlidxReverse(
  7288. Fts5Index *p,
  7289. int iSegid, /* Segment id to load from */
  7290. int iLeaf /* Load doclist-index for this leaf */
  7291. ){
  7292. Fts5DlidxIter *pDlidx = 0;
  7293. u64 cksum1 = 13;
  7294. u64 cksum2 = 13;
  7295. for(pDlidx=fts5DlidxIterInit(p, 0, iSegid, iLeaf);
  7296. fts5DlidxIterEof(p, pDlidx)==0;
  7297. fts5DlidxIterNext(p, pDlidx)
  7298. ){
  7299. i64 iRowid = fts5DlidxIterRowid(pDlidx);
  7300. int pgno = fts5DlidxIterPgno(pDlidx);
  7301. assert( pgno>iLeaf );
  7302. cksum1 += iRowid + ((i64)pgno<<32);
  7303. }
  7304. fts5DlidxIterFree(pDlidx);
  7305. pDlidx = 0;
  7306. for(pDlidx=fts5DlidxIterInit(p, 1, iSegid, iLeaf);
  7307. fts5DlidxIterEof(p, pDlidx)==0;
  7308. fts5DlidxIterPrev(p, pDlidx)
  7309. ){
  7310. i64 iRowid = fts5DlidxIterRowid(pDlidx);
  7311. int pgno = fts5DlidxIterPgno(pDlidx);
  7312. assert( fts5DlidxIterPgno(pDlidx)>iLeaf );
  7313. cksum2 += iRowid + ((i64)pgno<<32);
  7314. }
  7315. fts5DlidxIterFree(pDlidx);
  7316. pDlidx = 0;
  7317. if( p->rc==SQLITE_OK && cksum1!=cksum2 ) p->rc = FTS5_CORRUPT;
  7318. }
  7319. static int fts5QueryCksum(
  7320. Fts5Index *p, /* Fts5 index object */
  7321. int iIdx,
  7322. const char *z, /* Index key to query for */
  7323. int n, /* Size of index key in bytes */
  7324. int flags, /* Flags for Fts5IndexQuery */
  7325. u64 *pCksum /* IN/OUT: Checksum value */
  7326. ){
  7327. int eDetail = p->pConfig->eDetail;
  7328. u64 cksum = *pCksum;
  7329. Fts5IndexIter *pIter = 0;
  7330. int rc = sqlite3Fts5IndexQuery(
  7331. p, z, n, (flags | FTS5INDEX_QUERY_NOTOKENDATA), 0, &pIter
  7332. );
  7333. while( rc==SQLITE_OK && ALWAYS(pIter!=0) && 0==sqlite3Fts5IterEof(pIter) ){
  7334. i64 rowid = pIter->iRowid;
  7335. if( eDetail==FTS5_DETAIL_NONE ){
  7336. cksum ^= sqlite3Fts5IndexEntryCksum(rowid, 0, 0, iIdx, z, n);
  7337. }else{
  7338. Fts5PoslistReader sReader;
  7339. for(sqlite3Fts5PoslistReaderInit(pIter->pData, pIter->nData, &sReader);
  7340. sReader.bEof==0;
  7341. sqlite3Fts5PoslistReaderNext(&sReader)
  7342. ){
  7343. int iCol = FTS5_POS2COLUMN(sReader.iPos);
  7344. int iOff = FTS5_POS2OFFSET(sReader.iPos);
  7345. cksum ^= sqlite3Fts5IndexEntryCksum(rowid, iCol, iOff, iIdx, z, n);
  7346. }
  7347. }
  7348. if( rc==SQLITE_OK ){
  7349. rc = sqlite3Fts5IterNext(pIter);
  7350. }
  7351. }
  7352. sqlite3Fts5IterClose(pIter);
  7353. *pCksum = cksum;
  7354. return rc;
  7355. }
  7356. /*
  7357. ** Check if buffer z[], size n bytes, contains as series of valid utf-8
  7358. ** encoded codepoints. If so, return 0. Otherwise, if the buffer does not
  7359. ** contain valid utf-8, return non-zero.
  7360. */
  7361. static int fts5TestUtf8(const char *z, int n){
  7362. int i = 0;
  7363. assert_nc( n>0 );
  7364. while( i<n ){
  7365. if( (z[i] & 0x80)==0x00 ){
  7366. i++;
  7367. }else
  7368. if( (z[i] & 0xE0)==0xC0 ){
  7369. if( i+1>=n || (z[i+1] & 0xC0)!=0x80 ) return 1;
  7370. i += 2;
  7371. }else
  7372. if( (z[i] & 0xF0)==0xE0 ){
  7373. if( i+2>=n || (z[i+1] & 0xC0)!=0x80 || (z[i+2] & 0xC0)!=0x80 ) return 1;
  7374. i += 3;
  7375. }else
  7376. if( (z[i] & 0xF8)==0xF0 ){
  7377. if( i+3>=n || (z[i+1] & 0xC0)!=0x80 || (z[i+2] & 0xC0)!=0x80 ) return 1;
  7378. if( (z[i+2] & 0xC0)!=0x80 ) return 1;
  7379. i += 3;
  7380. }else{
  7381. return 1;
  7382. }
  7383. }
  7384. return 0;
  7385. }
  7386. /*
  7387. ** This function is also purely an internal test. It does not contribute to
  7388. ** FTS functionality, or even the integrity-check, in any way.
  7389. */
  7390. static void fts5TestTerm(
  7391. Fts5Index *p,
  7392. Fts5Buffer *pPrev, /* Previous term */
  7393. const char *z, int n, /* Possibly new term to test */
  7394. u64 expected,
  7395. u64 *pCksum
  7396. ){
  7397. int rc = p->rc;
  7398. if( pPrev->n==0 ){
  7399. fts5BufferSet(&rc, pPrev, n, (const u8*)z);
  7400. }else
  7401. if( rc==SQLITE_OK && (pPrev->n!=n || memcmp(pPrev->p, z, n)) ){
  7402. u64 cksum3 = *pCksum;
  7403. const char *zTerm = (const char*)&pPrev->p[1]; /* term sans prefix-byte */
  7404. int nTerm = pPrev->n-1; /* Size of zTerm in bytes */
  7405. int iIdx = (pPrev->p[0] - FTS5_MAIN_PREFIX);
  7406. int flags = (iIdx==0 ? 0 : FTS5INDEX_QUERY_PREFIX);
  7407. u64 ck1 = 0;
  7408. u64 ck2 = 0;
  7409. /* Check that the results returned for ASC and DESC queries are
  7410. ** the same. If not, call this corruption. */
  7411. rc = fts5QueryCksum(p, iIdx, zTerm, nTerm, flags, &ck1);
  7412. if( rc==SQLITE_OK ){
  7413. int f = flags|FTS5INDEX_QUERY_DESC;
  7414. rc = fts5QueryCksum(p, iIdx, zTerm, nTerm, f, &ck2);
  7415. }
  7416. if( rc==SQLITE_OK && ck1!=ck2 ) rc = FTS5_CORRUPT;
  7417. /* If this is a prefix query, check that the results returned if the
  7418. ** the index is disabled are the same. In both ASC and DESC order.
  7419. **
  7420. ** This check may only be performed if the hash table is empty. This
  7421. ** is because the hash table only supports a single scan query at
  7422. ** a time, and the multi-iter loop from which this function is called
  7423. ** is already performing such a scan.
  7424. **
  7425. ** Also only do this if buffer zTerm contains nTerm bytes of valid
  7426. ** utf-8. Otherwise, the last part of the buffer contents might contain
  7427. ** a non-utf-8 sequence that happens to be a prefix of a valid utf-8
  7428. ** character stored in the main fts index, which will cause the
  7429. ** test to fail. */
  7430. if( p->nPendingData==0 && 0==fts5TestUtf8(zTerm, nTerm) ){
  7431. if( iIdx>0 && rc==SQLITE_OK ){
  7432. int f = flags|FTS5INDEX_QUERY_TEST_NOIDX;
  7433. ck2 = 0;
  7434. rc = fts5QueryCksum(p, iIdx, zTerm, nTerm, f, &ck2);
  7435. if( rc==SQLITE_OK && ck1!=ck2 ) rc = FTS5_CORRUPT;
  7436. }
  7437. if( iIdx>0 && rc==SQLITE_OK ){
  7438. int f = flags|FTS5INDEX_QUERY_TEST_NOIDX|FTS5INDEX_QUERY_DESC;
  7439. ck2 = 0;
  7440. rc = fts5QueryCksum(p, iIdx, zTerm, nTerm, f, &ck2);
  7441. if( rc==SQLITE_OK && ck1!=ck2 ) rc = FTS5_CORRUPT;
  7442. }
  7443. }
  7444. cksum3 ^= ck1;
  7445. fts5BufferSet(&rc, pPrev, n, (const u8*)z);
  7446. if( rc==SQLITE_OK && cksum3!=expected ){
  7447. rc = FTS5_CORRUPT;
  7448. }
  7449. *pCksum = cksum3;
  7450. }
  7451. p->rc = rc;
  7452. }
  7453. #else
  7454. # define fts5TestDlidxReverse(x,y,z)
  7455. # define fts5TestTerm(u,v,w,x,y,z)
  7456. #endif
  7457. /*
  7458. ** Check that:
  7459. **
  7460. ** 1) All leaves of pSeg between iFirst and iLast (inclusive) exist and
  7461. ** contain zero terms.
  7462. ** 2) All leaves of pSeg between iNoRowid and iLast (inclusive) exist and
  7463. ** contain zero rowids.
  7464. */
  7465. static void fts5IndexIntegrityCheckEmpty(
  7466. Fts5Index *p,
  7467. Fts5StructureSegment *pSeg, /* Segment to check internal consistency */
  7468. int iFirst,
  7469. int iNoRowid,
  7470. int iLast
  7471. ){
  7472. int i;
  7473. /* Now check that the iter.nEmpty leaves following the current leaf
  7474. ** (a) exist and (b) contain no terms. */
  7475. for(i=iFirst; p->rc==SQLITE_OK && i<=iLast; i++){
  7476. Fts5Data *pLeaf = fts5DataRead(p, FTS5_SEGMENT_ROWID(pSeg->iSegid, i));
  7477. if( pLeaf ){
  7478. if( !fts5LeafIsTermless(pLeaf) ) p->rc = FTS5_CORRUPT;
  7479. if( i>=iNoRowid && 0!=fts5LeafFirstRowidOff(pLeaf) ) p->rc = FTS5_CORRUPT;
  7480. }
  7481. fts5DataRelease(pLeaf);
  7482. }
  7483. }
  7484. static void fts5IntegrityCheckPgidx(Fts5Index *p, Fts5Data *pLeaf){
  7485. i64 iTermOff = 0;
  7486. int ii;
  7487. Fts5Buffer buf1 = {0,0,0};
  7488. Fts5Buffer buf2 = {0,0,0};
  7489. ii = pLeaf->szLeaf;
  7490. while( ii<pLeaf->nn && p->rc==SQLITE_OK ){
  7491. int res;
  7492. i64 iOff;
  7493. int nIncr;
  7494. ii += fts5GetVarint32(&pLeaf->p[ii], nIncr);
  7495. iTermOff += nIncr;
  7496. iOff = iTermOff;
  7497. if( iOff>=pLeaf->szLeaf ){
  7498. p->rc = FTS5_CORRUPT;
  7499. }else if( iTermOff==nIncr ){
  7500. int nByte;
  7501. iOff += fts5GetVarint32(&pLeaf->p[iOff], nByte);
  7502. if( (iOff+nByte)>pLeaf->szLeaf ){
  7503. p->rc = FTS5_CORRUPT;
  7504. }else{
  7505. fts5BufferSet(&p->rc, &buf1, nByte, &pLeaf->p[iOff]);
  7506. }
  7507. }else{
  7508. int nKeep, nByte;
  7509. iOff += fts5GetVarint32(&pLeaf->p[iOff], nKeep);
  7510. iOff += fts5GetVarint32(&pLeaf->p[iOff], nByte);
  7511. if( nKeep>buf1.n || (iOff+nByte)>pLeaf->szLeaf ){
  7512. p->rc = FTS5_CORRUPT;
  7513. }else{
  7514. buf1.n = nKeep;
  7515. fts5BufferAppendBlob(&p->rc, &buf1, nByte, &pLeaf->p[iOff]);
  7516. }
  7517. if( p->rc==SQLITE_OK ){
  7518. res = fts5BufferCompare(&buf1, &buf2);
  7519. if( res<=0 ) p->rc = FTS5_CORRUPT;
  7520. }
  7521. }
  7522. fts5BufferSet(&p->rc, &buf2, buf1.n, buf1.p);
  7523. }
  7524. fts5BufferFree(&buf1);
  7525. fts5BufferFree(&buf2);
  7526. }
  7527. static void fts5IndexIntegrityCheckSegment(
  7528. Fts5Index *p, /* FTS5 backend object */
  7529. Fts5StructureSegment *pSeg /* Segment to check internal consistency */
  7530. ){
  7531. Fts5Config *pConfig = p->pConfig;
  7532. int bSecureDelete = (pConfig->iVersion==FTS5_CURRENT_VERSION_SECUREDELETE);
  7533. sqlite3_stmt *pStmt = 0;
  7534. int rc2;
  7535. int iIdxPrevLeaf = pSeg->pgnoFirst-1;
  7536. int iDlidxPrevLeaf = pSeg->pgnoLast;
  7537. if( pSeg->pgnoFirst==0 ) return;
  7538. fts5IndexPrepareStmt(p, &pStmt, sqlite3_mprintf(
  7539. "SELECT segid, term, (pgno>>1), (pgno&1) FROM %Q.'%q_idx' WHERE segid=%d "
  7540. "ORDER BY 1, 2",
  7541. pConfig->zDb, pConfig->zName, pSeg->iSegid
  7542. ));
  7543. /* Iterate through the b-tree hierarchy. */
  7544. while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
  7545. i64 iRow; /* Rowid for this leaf */
  7546. Fts5Data *pLeaf; /* Data for this leaf */
  7547. const char *zIdxTerm = (const char*)sqlite3_column_blob(pStmt, 1);
  7548. int nIdxTerm = sqlite3_column_bytes(pStmt, 1);
  7549. int iIdxLeaf = sqlite3_column_int(pStmt, 2);
  7550. int bIdxDlidx = sqlite3_column_int(pStmt, 3);
  7551. /* If the leaf in question has already been trimmed from the segment,
  7552. ** ignore this b-tree entry. Otherwise, load it into memory. */
  7553. if( iIdxLeaf<pSeg->pgnoFirst ) continue;
  7554. iRow = FTS5_SEGMENT_ROWID(pSeg->iSegid, iIdxLeaf);
  7555. pLeaf = fts5LeafRead(p, iRow);
  7556. if( pLeaf==0 ) break;
  7557. /* Check that the leaf contains at least one term, and that it is equal
  7558. ** to or larger than the split-key in zIdxTerm. Also check that if there
  7559. ** is also a rowid pointer within the leaf page header, it points to a
  7560. ** location before the term. */
  7561. if( pLeaf->nn<=pLeaf->szLeaf ){
  7562. if( nIdxTerm==0
  7563. && pConfig->iVersion==FTS5_CURRENT_VERSION_SECUREDELETE
  7564. && pLeaf->nn==pLeaf->szLeaf
  7565. && pLeaf->nn==4
  7566. ){
  7567. /* special case - the very first page in a segment keeps its %_idx
  7568. ** entry even if all the terms are removed from it by secure-delete
  7569. ** operations. */
  7570. }else{
  7571. p->rc = FTS5_CORRUPT;
  7572. }
  7573. }else{
  7574. int iOff; /* Offset of first term on leaf */
  7575. int iRowidOff; /* Offset of first rowid on leaf */
  7576. int nTerm; /* Size of term on leaf in bytes */
  7577. int res; /* Comparison of term and split-key */
  7578. iOff = fts5LeafFirstTermOff(pLeaf);
  7579. iRowidOff = fts5LeafFirstRowidOff(pLeaf);
  7580. if( iRowidOff>=iOff || iOff>=pLeaf->szLeaf ){
  7581. p->rc = FTS5_CORRUPT;
  7582. }else{
  7583. iOff += fts5GetVarint32(&pLeaf->p[iOff], nTerm);
  7584. res = fts5Memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm));
  7585. if( res==0 ) res = nTerm - nIdxTerm;
  7586. if( res<0 ) p->rc = FTS5_CORRUPT;
  7587. }
  7588. fts5IntegrityCheckPgidx(p, pLeaf);
  7589. }
  7590. fts5DataRelease(pLeaf);
  7591. if( p->rc ) break;
  7592. /* Now check that the iter.nEmpty leaves following the current leaf
  7593. ** (a) exist and (b) contain no terms. */
  7594. fts5IndexIntegrityCheckEmpty(
  7595. p, pSeg, iIdxPrevLeaf+1, iDlidxPrevLeaf+1, iIdxLeaf-1
  7596. );
  7597. if( p->rc ) break;
  7598. /* If there is a doclist-index, check that it looks right. */
  7599. if( bIdxDlidx ){
  7600. Fts5DlidxIter *pDlidx = 0; /* For iterating through doclist index */
  7601. int iPrevLeaf = iIdxLeaf;
  7602. int iSegid = pSeg->iSegid;
  7603. int iPg = 0;
  7604. i64 iKey;
  7605. for(pDlidx=fts5DlidxIterInit(p, 0, iSegid, iIdxLeaf);
  7606. fts5DlidxIterEof(p, pDlidx)==0;
  7607. fts5DlidxIterNext(p, pDlidx)
  7608. ){
  7609. /* Check any rowid-less pages that occur before the current leaf. */
  7610. for(iPg=iPrevLeaf+1; iPg<fts5DlidxIterPgno(pDlidx); iPg++){
  7611. iKey = FTS5_SEGMENT_ROWID(iSegid, iPg);
  7612. pLeaf = fts5DataRead(p, iKey);
  7613. if( pLeaf ){
  7614. if( fts5LeafFirstRowidOff(pLeaf)!=0 ) p->rc = FTS5_CORRUPT;
  7615. fts5DataRelease(pLeaf);
  7616. }
  7617. }
  7618. iPrevLeaf = fts5DlidxIterPgno(pDlidx);
  7619. /* Check that the leaf page indicated by the iterator really does
  7620. ** contain the rowid suggested by the same. */
  7621. iKey = FTS5_SEGMENT_ROWID(iSegid, iPrevLeaf);
  7622. pLeaf = fts5DataRead(p, iKey);
  7623. if( pLeaf ){
  7624. i64 iRowid;
  7625. int iRowidOff = fts5LeafFirstRowidOff(pLeaf);
  7626. ASSERT_SZLEAF_OK(pLeaf);
  7627. if( iRowidOff>=pLeaf->szLeaf ){
  7628. p->rc = FTS5_CORRUPT;
  7629. }else if( bSecureDelete==0 || iRowidOff>0 ){
  7630. i64 iDlRowid = fts5DlidxIterRowid(pDlidx);
  7631. fts5GetVarint(&pLeaf->p[iRowidOff], (u64*)&iRowid);
  7632. if( iRowid<iDlRowid || (bSecureDelete==0 && iRowid!=iDlRowid) ){
  7633. p->rc = FTS5_CORRUPT;
  7634. }
  7635. }
  7636. fts5DataRelease(pLeaf);
  7637. }
  7638. }
  7639. iDlidxPrevLeaf = iPg;
  7640. fts5DlidxIterFree(pDlidx);
  7641. fts5TestDlidxReverse(p, iSegid, iIdxLeaf);
  7642. }else{
  7643. iDlidxPrevLeaf = pSeg->pgnoLast;
  7644. /* TODO: Check there is no doclist index */
  7645. }
  7646. iIdxPrevLeaf = iIdxLeaf;
  7647. }
  7648. rc2 = sqlite3_finalize(pStmt);
  7649. if( p->rc==SQLITE_OK ) p->rc = rc2;
  7650. /* Page iter.iLeaf must now be the rightmost leaf-page in the segment */
  7651. #if 0
  7652. if( p->rc==SQLITE_OK && iter.iLeaf!=pSeg->pgnoLast ){
  7653. p->rc = FTS5_CORRUPT;
  7654. }
  7655. #endif
  7656. }
  7657. /*
  7658. ** Run internal checks to ensure that the FTS index (a) is internally
  7659. ** consistent and (b) contains entries for which the XOR of the checksums
  7660. ** as calculated by sqlite3Fts5IndexEntryCksum() is cksum.
  7661. **
  7662. ** Return SQLITE_CORRUPT if any of the internal checks fail, or if the
  7663. ** checksum does not match. Return SQLITE_OK if all checks pass without
  7664. ** error, or some other SQLite error code if another error (e.g. OOM)
  7665. ** occurs.
  7666. */
  7667. int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum){
  7668. int eDetail = p->pConfig->eDetail;
  7669. u64 cksum2 = 0; /* Checksum based on contents of indexes */
  7670. Fts5Buffer poslist = {0,0,0}; /* Buffer used to hold a poslist */
  7671. Fts5Iter *pIter; /* Used to iterate through entire index */
  7672. Fts5Structure *pStruct; /* Index structure */
  7673. int iLvl, iSeg;
  7674. #ifdef SQLITE_DEBUG
  7675. /* Used by extra internal tests only run if NDEBUG is not defined */
  7676. u64 cksum3 = 0; /* Checksum based on contents of indexes */
  7677. Fts5Buffer term = {0,0,0}; /* Buffer used to hold most recent term */
  7678. #endif
  7679. const int flags = FTS5INDEX_QUERY_NOOUTPUT;
  7680. /* Load the FTS index structure */
  7681. pStruct = fts5StructureRead(p);
  7682. if( pStruct==0 ){
  7683. assert( p->rc!=SQLITE_OK );
  7684. return fts5IndexReturn(p);
  7685. }
  7686. /* Check that the internal nodes of each segment match the leaves */
  7687. for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
  7688. for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
  7689. Fts5StructureSegment *pSeg = &pStruct->aLevel[iLvl].aSeg[iSeg];
  7690. fts5IndexIntegrityCheckSegment(p, pSeg);
  7691. }
  7692. }
  7693. /* The cksum argument passed to this function is a checksum calculated
  7694. ** based on all expected entries in the FTS index (including prefix index
  7695. ** entries). This block checks that a checksum calculated based on the
  7696. ** actual contents of FTS index is identical.
  7697. **
  7698. ** Two versions of the same checksum are calculated. The first (stack
  7699. ** variable cksum2) based on entries extracted from the full-text index
  7700. ** while doing a linear scan of each individual index in turn.
  7701. **
  7702. ** As each term visited by the linear scans, a separate query for the
  7703. ** same term is performed. cksum3 is calculated based on the entries
  7704. ** extracted by these queries.
  7705. */
  7706. for(fts5MultiIterNew(p, pStruct, flags, 0, 0, 0, -1, 0, &pIter);
  7707. fts5MultiIterEof(p, pIter)==0;
  7708. fts5MultiIterNext(p, pIter, 0, 0)
  7709. ){
  7710. int n; /* Size of term in bytes */
  7711. i64 iPos = 0; /* Position read from poslist */
  7712. int iOff = 0; /* Offset within poslist */
  7713. i64 iRowid = fts5MultiIterRowid(pIter);
  7714. char *z = (char*)fts5MultiIterTerm(pIter, &n);
  7715. /* If this is a new term, query for it. Update cksum3 with the results. */
  7716. fts5TestTerm(p, &term, z, n, cksum2, &cksum3);
  7717. if( p->rc ) break;
  7718. if( eDetail==FTS5_DETAIL_NONE ){
  7719. if( 0==fts5MultiIterIsEmpty(p, pIter) ){
  7720. cksum2 ^= sqlite3Fts5IndexEntryCksum(iRowid, 0, 0, -1, z, n);
  7721. }
  7722. }else{
  7723. poslist.n = 0;
  7724. fts5SegiterPoslist(p, &pIter->aSeg[pIter->aFirst[1].iFirst], 0, &poslist);
  7725. fts5BufferAppendBlob(&p->rc, &poslist, 4, (const u8*)"\0\0\0\0");
  7726. while( 0==sqlite3Fts5PoslistNext64(poslist.p, poslist.n, &iOff, &iPos) ){
  7727. int iCol = FTS5_POS2COLUMN(iPos);
  7728. int iTokOff = FTS5_POS2OFFSET(iPos);
  7729. cksum2 ^= sqlite3Fts5IndexEntryCksum(iRowid, iCol, iTokOff, -1, z, n);
  7730. }
  7731. }
  7732. }
  7733. fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3);
  7734. fts5MultiIterFree(pIter);
  7735. if( p->rc==SQLITE_OK && bUseCksum && cksum!=cksum2 ) p->rc = FTS5_CORRUPT;
  7736. fts5StructureRelease(pStruct);
  7737. #ifdef SQLITE_DEBUG
  7738. fts5BufferFree(&term);
  7739. #endif
  7740. fts5BufferFree(&poslist);
  7741. return fts5IndexReturn(p);
  7742. }
  7743. /*************************************************************************
  7744. **************************************************************************
  7745. ** Below this point is the implementation of the fts5_decode() scalar
  7746. ** function only.
  7747. */
  7748. #if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
  7749. /*
  7750. ** Decode a segment-data rowid from the %_data table. This function is
  7751. ** the opposite of macro FTS5_SEGMENT_ROWID().
  7752. */
  7753. static void fts5DecodeRowid(
  7754. i64 iRowid, /* Rowid from %_data table */
  7755. int *pbTombstone, /* OUT: Tombstone hash flag */
  7756. int *piSegid, /* OUT: Segment id */
  7757. int *pbDlidx, /* OUT: Dlidx flag */
  7758. int *piHeight, /* OUT: Height */
  7759. int *piPgno /* OUT: Page number */
  7760. ){
  7761. *piPgno = (int)(iRowid & (((i64)1 << FTS5_DATA_PAGE_B) - 1));
  7762. iRowid >>= FTS5_DATA_PAGE_B;
  7763. *piHeight = (int)(iRowid & (((i64)1 << FTS5_DATA_HEIGHT_B) - 1));
  7764. iRowid >>= FTS5_DATA_HEIGHT_B;
  7765. *pbDlidx = (int)(iRowid & 0x0001);
  7766. iRowid >>= FTS5_DATA_DLI_B;
  7767. *piSegid = (int)(iRowid & (((i64)1 << FTS5_DATA_ID_B) - 1));
  7768. iRowid >>= FTS5_DATA_ID_B;
  7769. *pbTombstone = (int)(iRowid & 0x0001);
  7770. }
  7771. #endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */
  7772. #if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
  7773. static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){
  7774. int iSegid, iHeight, iPgno, bDlidx, bTomb; /* Rowid compenents */
  7775. fts5DecodeRowid(iKey, &bTomb, &iSegid, &bDlidx, &iHeight, &iPgno);
  7776. if( iSegid==0 ){
  7777. if( iKey==FTS5_AVERAGES_ROWID ){
  7778. sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{averages} ");
  7779. }else{
  7780. sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{structure}");
  7781. }
  7782. }
  7783. else{
  7784. sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{%s%ssegid=%d h=%d pgno=%d}",
  7785. bDlidx ? "dlidx " : "",
  7786. bTomb ? "tombstone " : "",
  7787. iSegid, iHeight, iPgno
  7788. );
  7789. }
  7790. }
  7791. #endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */
  7792. #if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
  7793. static void fts5DebugStructure(
  7794. int *pRc, /* IN/OUT: error code */
  7795. Fts5Buffer *pBuf,
  7796. Fts5Structure *p
  7797. ){
  7798. int iLvl, iSeg; /* Iterate through levels, segments */
  7799. for(iLvl=0; iLvl<p->nLevel; iLvl++){
  7800. Fts5StructureLevel *pLvl = &p->aLevel[iLvl];
  7801. sqlite3Fts5BufferAppendPrintf(pRc, pBuf,
  7802. " {lvl=%d nMerge=%d nSeg=%d", iLvl, pLvl->nMerge, pLvl->nSeg
  7803. );
  7804. for(iSeg=0; iSeg<pLvl->nSeg; iSeg++){
  7805. Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg];
  7806. sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " {id=%d leaves=%d..%d",
  7807. pSeg->iSegid, pSeg->pgnoFirst, pSeg->pgnoLast
  7808. );
  7809. if( pSeg->iOrigin1>0 ){
  7810. sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " origin=%lld..%lld",
  7811. pSeg->iOrigin1, pSeg->iOrigin2
  7812. );
  7813. }
  7814. sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "}");
  7815. }
  7816. sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "}");
  7817. }
  7818. }
  7819. #endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */
  7820. #if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
  7821. /*
  7822. ** This is part of the fts5_decode() debugging aid.
  7823. **
  7824. ** Arguments pBlob/nBlob contain a serialized Fts5Structure object. This
  7825. ** function appends a human-readable representation of the same object
  7826. ** to the buffer passed as the second argument.
  7827. */
  7828. static void fts5DecodeStructure(
  7829. int *pRc, /* IN/OUT: error code */
  7830. Fts5Buffer *pBuf,
  7831. const u8 *pBlob, int nBlob
  7832. ){
  7833. int rc; /* Return code */
  7834. Fts5Structure *p = 0; /* Decoded structure object */
  7835. rc = fts5StructureDecode(pBlob, nBlob, 0, &p);
  7836. if( rc!=SQLITE_OK ){
  7837. *pRc = rc;
  7838. return;
  7839. }
  7840. fts5DebugStructure(pRc, pBuf, p);
  7841. fts5StructureRelease(p);
  7842. }
  7843. #endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */
  7844. #if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
  7845. /*
  7846. ** This is part of the fts5_decode() debugging aid.
  7847. **
  7848. ** Arguments pBlob/nBlob contain an "averages" record. This function
  7849. ** appends a human-readable representation of record to the buffer passed
  7850. ** as the second argument.
  7851. */
  7852. static void fts5DecodeAverages(
  7853. int *pRc, /* IN/OUT: error code */
  7854. Fts5Buffer *pBuf,
  7855. const u8 *pBlob, int nBlob
  7856. ){
  7857. int i = 0;
  7858. const char *zSpace = "";
  7859. while( i<nBlob ){
  7860. u64 iVal;
  7861. i += sqlite3Fts5GetVarint(&pBlob[i], &iVal);
  7862. sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "%s%d", zSpace, (int)iVal);
  7863. zSpace = " ";
  7864. }
  7865. }
  7866. #endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */
  7867. #if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
  7868. /*
  7869. ** Buffer (a/n) is assumed to contain a list of serialized varints. Read
  7870. ** each varint and append its string representation to buffer pBuf. Return
  7871. ** after either the input buffer is exhausted or a 0 value is read.
  7872. **
  7873. ** The return value is the number of bytes read from the input buffer.
  7874. */
  7875. static int fts5DecodePoslist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){
  7876. int iOff = 0;
  7877. while( iOff<n ){
  7878. int iVal;
  7879. iOff += fts5GetVarint32(&a[iOff], iVal);
  7880. sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " %d", iVal);
  7881. }
  7882. return iOff;
  7883. }
  7884. #endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */
  7885. #if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
  7886. /*
  7887. ** The start of buffer (a/n) contains the start of a doclist. The doclist
  7888. ** may or may not finish within the buffer. This function appends a text
  7889. ** representation of the part of the doclist that is present to buffer
  7890. ** pBuf.
  7891. **
  7892. ** The return value is the number of bytes read from the input buffer.
  7893. */
  7894. static int fts5DecodeDoclist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){
  7895. i64 iDocid = 0;
  7896. int iOff = 0;
  7897. if( n>0 ){
  7898. iOff = sqlite3Fts5GetVarint(a, (u64*)&iDocid);
  7899. sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " id=%lld", iDocid);
  7900. }
  7901. while( iOff<n ){
  7902. int nPos;
  7903. int bDel;
  7904. iOff += fts5GetPoslistSize(&a[iOff], &nPos, &bDel);
  7905. sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " nPos=%d%s", nPos, bDel?"*":"");
  7906. iOff += fts5DecodePoslist(pRc, pBuf, &a[iOff], MIN(n-iOff, nPos));
  7907. if( iOff<n ){
  7908. i64 iDelta;
  7909. iOff += sqlite3Fts5GetVarint(&a[iOff], (u64*)&iDelta);
  7910. iDocid += iDelta;
  7911. sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " id=%lld", iDocid);
  7912. }
  7913. }
  7914. return iOff;
  7915. }
  7916. #endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */
  7917. #if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
  7918. /*
  7919. ** This function is part of the fts5_decode() debugging function. It is
  7920. ** only ever used with detail=none tables.
  7921. **
  7922. ** Buffer (pData/nData) contains a doclist in the format used by detail=none
  7923. ** tables. This function appends a human-readable version of that list to
  7924. ** buffer pBuf.
  7925. **
  7926. ** If *pRc is other than SQLITE_OK when this function is called, it is a
  7927. ** no-op. If an OOM or other error occurs within this function, *pRc is
  7928. ** set to an SQLite error code before returning. The final state of buffer
  7929. ** pBuf is undefined in this case.
  7930. */
  7931. static void fts5DecodeRowidList(
  7932. int *pRc, /* IN/OUT: Error code */
  7933. Fts5Buffer *pBuf, /* Buffer to append text to */
  7934. const u8 *pData, int nData /* Data to decode list-of-rowids from */
  7935. ){
  7936. int i = 0;
  7937. i64 iRowid = 0;
  7938. while( i<nData ){
  7939. const char *zApp = "";
  7940. u64 iVal;
  7941. i += sqlite3Fts5GetVarint(&pData[i], &iVal);
  7942. iRowid += iVal;
  7943. if( i<nData && pData[i]==0x00 ){
  7944. i++;
  7945. if( i<nData && pData[i]==0x00 ){
  7946. i++;
  7947. zApp = "+";
  7948. }else{
  7949. zApp = "*";
  7950. }
  7951. }
  7952. sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " %lld%s", iRowid, zApp);
  7953. }
  7954. }
  7955. #endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */
  7956. #if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
  7957. static void fts5BufferAppendTerm(int *pRc, Fts5Buffer *pBuf, Fts5Buffer *pTerm){
  7958. int ii;
  7959. fts5BufferGrow(pRc, pBuf, pTerm->n*2 + 1);
  7960. if( *pRc==SQLITE_OK ){
  7961. for(ii=0; ii<pTerm->n; ii++){
  7962. if( pTerm->p[ii]==0x00 ){
  7963. pBuf->p[pBuf->n++] = '\\';
  7964. pBuf->p[pBuf->n++] = '0';
  7965. }else{
  7966. pBuf->p[pBuf->n++] = pTerm->p[ii];
  7967. }
  7968. }
  7969. pBuf->p[pBuf->n] = 0x00;
  7970. }
  7971. }
  7972. #endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */
  7973. #if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
  7974. /*
  7975. ** The implementation of user-defined scalar function fts5_decode().
  7976. */
  7977. static void fts5DecodeFunction(
  7978. sqlite3_context *pCtx, /* Function call context */
  7979. int nArg, /* Number of args (always 2) */
  7980. sqlite3_value **apVal /* Function arguments */
  7981. ){
  7982. i64 iRowid; /* Rowid for record being decoded */
  7983. int iSegid,iHeight,iPgno,bDlidx;/* Rowid components */
  7984. int bTomb;
  7985. const u8 *aBlob; int n; /* Record to decode */
  7986. u8 *a = 0;
  7987. Fts5Buffer s; /* Build up text to return here */
  7988. int rc = SQLITE_OK; /* Return code */
  7989. sqlite3_int64 nSpace = 0;
  7990. int eDetailNone = (sqlite3_user_data(pCtx)!=0);
  7991. assert( nArg==2 );
  7992. UNUSED_PARAM(nArg);
  7993. memset(&s, 0, sizeof(Fts5Buffer));
  7994. iRowid = sqlite3_value_int64(apVal[0]);
  7995. /* Make a copy of the second argument (a blob) in aBlob[]. The aBlob[]
  7996. ** copy is followed by FTS5_DATA_ZERO_PADDING 0x00 bytes, which prevents
  7997. ** buffer overreads even if the record is corrupt. */
  7998. n = sqlite3_value_bytes(apVal[1]);
  7999. aBlob = sqlite3_value_blob(apVal[1]);
  8000. nSpace = n + FTS5_DATA_ZERO_PADDING;
  8001. a = (u8*)sqlite3Fts5MallocZero(&rc, nSpace);
  8002. if( a==0 ) goto decode_out;
  8003. if( n>0 ) memcpy(a, aBlob, n);
  8004. fts5DecodeRowid(iRowid, &bTomb, &iSegid, &bDlidx, &iHeight, &iPgno);
  8005. fts5DebugRowid(&rc, &s, iRowid);
  8006. if( bDlidx ){
  8007. Fts5Data dlidx;
  8008. Fts5DlidxLvl lvl;
  8009. dlidx.p = a;
  8010. dlidx.nn = n;
  8011. memset(&lvl, 0, sizeof(Fts5DlidxLvl));
  8012. lvl.pData = &dlidx;
  8013. lvl.iLeafPgno = iPgno;
  8014. for(fts5DlidxLvlNext(&lvl); lvl.bEof==0; fts5DlidxLvlNext(&lvl)){
  8015. sqlite3Fts5BufferAppendPrintf(&rc, &s,
  8016. " %d(%lld)", lvl.iLeafPgno, lvl.iRowid
  8017. );
  8018. }
  8019. }else if( bTomb ){
  8020. u32 nElem = fts5GetU32(&a[4]);
  8021. int szKey = (aBlob[0]==4 || aBlob[0]==8) ? aBlob[0] : 8;
  8022. int nSlot = (n - 8) / szKey;
  8023. int ii;
  8024. sqlite3Fts5BufferAppendPrintf(&rc, &s, " nElem=%d", (int)nElem);
  8025. if( aBlob[1] ){
  8026. sqlite3Fts5BufferAppendPrintf(&rc, &s, " 0");
  8027. }
  8028. for(ii=0; ii<nSlot; ii++){
  8029. u64 iVal = 0;
  8030. if( szKey==4 ){
  8031. u32 *aSlot = (u32*)&aBlob[8];
  8032. if( aSlot[ii] ) iVal = fts5GetU32((u8*)&aSlot[ii]);
  8033. }else{
  8034. u64 *aSlot = (u64*)&aBlob[8];
  8035. if( aSlot[ii] ) iVal = fts5GetU64((u8*)&aSlot[ii]);
  8036. }
  8037. if( iVal!=0 ){
  8038. sqlite3Fts5BufferAppendPrintf(&rc, &s, " %lld", (i64)iVal);
  8039. }
  8040. }
  8041. }else if( iSegid==0 ){
  8042. if( iRowid==FTS5_AVERAGES_ROWID ){
  8043. fts5DecodeAverages(&rc, &s, a, n);
  8044. }else{
  8045. fts5DecodeStructure(&rc, &s, a, n);
  8046. }
  8047. }else if( eDetailNone ){
  8048. Fts5Buffer term; /* Current term read from page */
  8049. int szLeaf;
  8050. int iPgidxOff = szLeaf = fts5GetU16(&a[2]);
  8051. int iTermOff;
  8052. int nKeep = 0;
  8053. int iOff;
  8054. memset(&term, 0, sizeof(Fts5Buffer));
  8055. /* Decode any entries that occur before the first term. */
  8056. if( szLeaf<n ){
  8057. iPgidxOff += fts5GetVarint32(&a[iPgidxOff], iTermOff);
  8058. }else{
  8059. iTermOff = szLeaf;
  8060. }
  8061. fts5DecodeRowidList(&rc, &s, &a[4], iTermOff-4);
  8062. iOff = iTermOff;
  8063. while( iOff<szLeaf && rc==SQLITE_OK ){
  8064. int nAppend;
  8065. /* Read the term data for the next term*/
  8066. iOff += fts5GetVarint32(&a[iOff], nAppend);
  8067. term.n = nKeep;
  8068. fts5BufferAppendBlob(&rc, &term, nAppend, &a[iOff]);
  8069. sqlite3Fts5BufferAppendPrintf(&rc, &s, " term=");
  8070. fts5BufferAppendTerm(&rc, &s, &term);
  8071. iOff += nAppend;
  8072. /* Figure out where the doclist for this term ends */
  8073. if( iPgidxOff<n ){
  8074. int nIncr;
  8075. iPgidxOff += fts5GetVarint32(&a[iPgidxOff], nIncr);
  8076. iTermOff += nIncr;
  8077. }else{
  8078. iTermOff = szLeaf;
  8079. }
  8080. if( iTermOff>szLeaf ){
  8081. rc = FTS5_CORRUPT;
  8082. }else{
  8083. fts5DecodeRowidList(&rc, &s, &a[iOff], iTermOff-iOff);
  8084. }
  8085. iOff = iTermOff;
  8086. if( iOff<szLeaf ){
  8087. iOff += fts5GetVarint32(&a[iOff], nKeep);
  8088. }
  8089. }
  8090. fts5BufferFree(&term);
  8091. }else{
  8092. Fts5Buffer term; /* Current term read from page */
  8093. int szLeaf; /* Offset of pgidx in a[] */
  8094. int iPgidxOff;
  8095. int iPgidxPrev = 0; /* Previous value read from pgidx */
  8096. int iTermOff = 0;
  8097. int iRowidOff = 0;
  8098. int iOff;
  8099. int nDoclist;
  8100. memset(&term, 0, sizeof(Fts5Buffer));
  8101. if( n<4 ){
  8102. sqlite3Fts5BufferSet(&rc, &s, 7, (const u8*)"corrupt");
  8103. goto decode_out;
  8104. }else{
  8105. iRowidOff = fts5GetU16(&a[0]);
  8106. iPgidxOff = szLeaf = fts5GetU16(&a[2]);
  8107. if( iPgidxOff<n ){
  8108. fts5GetVarint32(&a[iPgidxOff], iTermOff);
  8109. }else if( iPgidxOff>n ){
  8110. rc = FTS5_CORRUPT;
  8111. goto decode_out;
  8112. }
  8113. }
  8114. /* Decode the position list tail at the start of the page */
  8115. if( iRowidOff!=0 ){
  8116. iOff = iRowidOff;
  8117. }else if( iTermOff!=0 ){
  8118. iOff = iTermOff;
  8119. }else{
  8120. iOff = szLeaf;
  8121. }
  8122. if( iOff>n ){
  8123. rc = FTS5_CORRUPT;
  8124. goto decode_out;
  8125. }
  8126. fts5DecodePoslist(&rc, &s, &a[4], iOff-4);
  8127. /* Decode any more doclist data that appears on the page before the
  8128. ** first term. */
  8129. nDoclist = (iTermOff ? iTermOff : szLeaf) - iOff;
  8130. if( nDoclist+iOff>n ){
  8131. rc = FTS5_CORRUPT;
  8132. goto decode_out;
  8133. }
  8134. fts5DecodeDoclist(&rc, &s, &a[iOff], nDoclist);
  8135. while( iPgidxOff<n && rc==SQLITE_OK ){
  8136. int bFirst = (iPgidxOff==szLeaf); /* True for first term on page */
  8137. int nByte; /* Bytes of data */
  8138. int iEnd;
  8139. iPgidxOff += fts5GetVarint32(&a[iPgidxOff], nByte);
  8140. iPgidxPrev += nByte;
  8141. iOff = iPgidxPrev;
  8142. if( iPgidxOff<n ){
  8143. fts5GetVarint32(&a[iPgidxOff], nByte);
  8144. iEnd = iPgidxPrev + nByte;
  8145. }else{
  8146. iEnd = szLeaf;
  8147. }
  8148. if( iEnd>szLeaf ){
  8149. rc = FTS5_CORRUPT;
  8150. break;
  8151. }
  8152. if( bFirst==0 ){
  8153. iOff += fts5GetVarint32(&a[iOff], nByte);
  8154. if( nByte>term.n ){
  8155. rc = FTS5_CORRUPT;
  8156. break;
  8157. }
  8158. term.n = nByte;
  8159. }
  8160. iOff += fts5GetVarint32(&a[iOff], nByte);
  8161. if( iOff+nByte>n ){
  8162. rc = FTS5_CORRUPT;
  8163. break;
  8164. }
  8165. fts5BufferAppendBlob(&rc, &term, nByte, &a[iOff]);
  8166. iOff += nByte;
  8167. sqlite3Fts5BufferAppendPrintf(&rc, &s, " term=");
  8168. fts5BufferAppendTerm(&rc, &s, &term);
  8169. iOff += fts5DecodeDoclist(&rc, &s, &a[iOff], iEnd-iOff);
  8170. }
  8171. fts5BufferFree(&term);
  8172. }
  8173. decode_out:
  8174. sqlite3_free(a);
  8175. if( rc==SQLITE_OK ){
  8176. sqlite3_result_text(pCtx, (const char*)s.p, s.n, SQLITE_TRANSIENT);
  8177. }else{
  8178. sqlite3_result_error_code(pCtx, rc);
  8179. }
  8180. fts5BufferFree(&s);
  8181. }
  8182. #endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */
  8183. #if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
  8184. /*
  8185. ** The implementation of user-defined scalar function fts5_rowid().
  8186. */
  8187. static void fts5RowidFunction(
  8188. sqlite3_context *pCtx, /* Function call context */
  8189. int nArg, /* Number of args (always 2) */
  8190. sqlite3_value **apVal /* Function arguments */
  8191. ){
  8192. const char *zArg;
  8193. if( nArg==0 ){
  8194. sqlite3_result_error(pCtx, "should be: fts5_rowid(subject, ....)", -1);
  8195. }else{
  8196. zArg = (const char*)sqlite3_value_text(apVal[0]);
  8197. if( 0==sqlite3_stricmp(zArg, "segment") ){
  8198. i64 iRowid;
  8199. int segid, pgno;
  8200. if( nArg!=3 ){
  8201. sqlite3_result_error(pCtx,
  8202. "should be: fts5_rowid('segment', segid, pgno))", -1
  8203. );
  8204. }else{
  8205. segid = sqlite3_value_int(apVal[1]);
  8206. pgno = sqlite3_value_int(apVal[2]);
  8207. iRowid = FTS5_SEGMENT_ROWID(segid, pgno);
  8208. sqlite3_result_int64(pCtx, iRowid);
  8209. }
  8210. }else{
  8211. sqlite3_result_error(pCtx,
  8212. "first arg to fts5_rowid() must be 'segment'" , -1
  8213. );
  8214. }
  8215. }
  8216. }
  8217. #endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */
  8218. #if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
  8219. typedef struct Fts5StructVtab Fts5StructVtab;
  8220. struct Fts5StructVtab {
  8221. sqlite3_vtab base;
  8222. };
  8223. typedef struct Fts5StructVcsr Fts5StructVcsr;
  8224. struct Fts5StructVcsr {
  8225. sqlite3_vtab_cursor base;
  8226. Fts5Structure *pStruct;
  8227. int iLevel;
  8228. int iSeg;
  8229. int iRowid;
  8230. };
  8231. /*
  8232. ** Create a new fts5_structure() table-valued function.
  8233. */
  8234. static int fts5structConnectMethod(
  8235. sqlite3 *db,
  8236. void *pAux,
  8237. int argc, const char *const*argv,
  8238. sqlite3_vtab **ppVtab,
  8239. char **pzErr
  8240. ){
  8241. Fts5StructVtab *pNew = 0;
  8242. int rc = SQLITE_OK;
  8243. rc = sqlite3_declare_vtab(db,
  8244. "CREATE TABLE xyz("
  8245. "level, segment, merge, segid, leaf1, leaf2, loc1, loc2, "
  8246. "npgtombstone, nentrytombstone, nentry, struct HIDDEN);"
  8247. );
  8248. if( rc==SQLITE_OK ){
  8249. pNew = sqlite3Fts5MallocZero(&rc, sizeof(*pNew));
  8250. }
  8251. *ppVtab = (sqlite3_vtab*)pNew;
  8252. return rc;
  8253. }
  8254. /*
  8255. ** We must have a single struct=? constraint that will be passed through
  8256. ** into the xFilter method. If there is no valid struct=? constraint,
  8257. ** then return an SQLITE_CONSTRAINT error.
  8258. */
  8259. static int fts5structBestIndexMethod(
  8260. sqlite3_vtab *tab,
  8261. sqlite3_index_info *pIdxInfo
  8262. ){
  8263. int i;
  8264. int rc = SQLITE_CONSTRAINT;
  8265. struct sqlite3_index_constraint *p;
  8266. pIdxInfo->estimatedCost = (double)100;
  8267. pIdxInfo->estimatedRows = 100;
  8268. pIdxInfo->idxNum = 0;
  8269. for(i=0, p=pIdxInfo->aConstraint; i<pIdxInfo->nConstraint; i++, p++){
  8270. if( p->usable==0 ) continue;
  8271. if( p->op==SQLITE_INDEX_CONSTRAINT_EQ && p->iColumn==11 ){
  8272. rc = SQLITE_OK;
  8273. pIdxInfo->aConstraintUsage[i].omit = 1;
  8274. pIdxInfo->aConstraintUsage[i].argvIndex = 1;
  8275. break;
  8276. }
  8277. }
  8278. return rc;
  8279. }
  8280. /*
  8281. ** This method is the destructor for bytecodevtab objects.
  8282. */
  8283. static int fts5structDisconnectMethod(sqlite3_vtab *pVtab){
  8284. Fts5StructVtab *p = (Fts5StructVtab*)pVtab;
  8285. sqlite3_free(p);
  8286. return SQLITE_OK;
  8287. }
  8288. /*
  8289. ** Constructor for a new bytecodevtab_cursor object.
  8290. */
  8291. static int fts5structOpenMethod(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCsr){
  8292. int rc = SQLITE_OK;
  8293. Fts5StructVcsr *pNew = 0;
  8294. pNew = sqlite3Fts5MallocZero(&rc, sizeof(*pNew));
  8295. *ppCsr = (sqlite3_vtab_cursor*)pNew;
  8296. return SQLITE_OK;
  8297. }
  8298. /*
  8299. ** Destructor for a bytecodevtab_cursor.
  8300. */
  8301. static int fts5structCloseMethod(sqlite3_vtab_cursor *cur){
  8302. Fts5StructVcsr *pCsr = (Fts5StructVcsr*)cur;
  8303. fts5StructureRelease(pCsr->pStruct);
  8304. sqlite3_free(pCsr);
  8305. return SQLITE_OK;
  8306. }
  8307. /*
  8308. ** Advance a bytecodevtab_cursor to its next row of output.
  8309. */
  8310. static int fts5structNextMethod(sqlite3_vtab_cursor *cur){
  8311. Fts5StructVcsr *pCsr = (Fts5StructVcsr*)cur;
  8312. Fts5Structure *p = pCsr->pStruct;
  8313. assert( pCsr->pStruct );
  8314. pCsr->iSeg++;
  8315. pCsr->iRowid++;
  8316. while( pCsr->iLevel<p->nLevel && pCsr->iSeg>=p->aLevel[pCsr->iLevel].nSeg ){
  8317. pCsr->iLevel++;
  8318. pCsr->iSeg = 0;
  8319. }
  8320. if( pCsr->iLevel>=p->nLevel ){
  8321. fts5StructureRelease(pCsr->pStruct);
  8322. pCsr->pStruct = 0;
  8323. }
  8324. return SQLITE_OK;
  8325. }
  8326. /*
  8327. ** Return TRUE if the cursor has been moved off of the last
  8328. ** row of output.
  8329. */
  8330. static int fts5structEofMethod(sqlite3_vtab_cursor *cur){
  8331. Fts5StructVcsr *pCsr = (Fts5StructVcsr*)cur;
  8332. return pCsr->pStruct==0;
  8333. }
  8334. static int fts5structRowidMethod(
  8335. sqlite3_vtab_cursor *cur,
  8336. sqlite_int64 *piRowid
  8337. ){
  8338. Fts5StructVcsr *pCsr = (Fts5StructVcsr*)cur;
  8339. *piRowid = pCsr->iRowid;
  8340. return SQLITE_OK;
  8341. }
  8342. /*
  8343. ** Return values of columns for the row at which the bytecodevtab_cursor
  8344. ** is currently pointing.
  8345. */
  8346. static int fts5structColumnMethod(
  8347. sqlite3_vtab_cursor *cur, /* The cursor */
  8348. sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
  8349. int i /* Which column to return */
  8350. ){
  8351. Fts5StructVcsr *pCsr = (Fts5StructVcsr*)cur;
  8352. Fts5Structure *p = pCsr->pStruct;
  8353. Fts5StructureSegment *pSeg = &p->aLevel[pCsr->iLevel].aSeg[pCsr->iSeg];
  8354. switch( i ){
  8355. case 0: /* level */
  8356. sqlite3_result_int(ctx, pCsr->iLevel);
  8357. break;
  8358. case 1: /* segment */
  8359. sqlite3_result_int(ctx, pCsr->iSeg);
  8360. break;
  8361. case 2: /* merge */
  8362. sqlite3_result_int(ctx, pCsr->iSeg < p->aLevel[pCsr->iLevel].nMerge);
  8363. break;
  8364. case 3: /* segid */
  8365. sqlite3_result_int(ctx, pSeg->iSegid);
  8366. break;
  8367. case 4: /* leaf1 */
  8368. sqlite3_result_int(ctx, pSeg->pgnoFirst);
  8369. break;
  8370. case 5: /* leaf2 */
  8371. sqlite3_result_int(ctx, pSeg->pgnoLast);
  8372. break;
  8373. case 6: /* origin1 */
  8374. sqlite3_result_int64(ctx, pSeg->iOrigin1);
  8375. break;
  8376. case 7: /* origin2 */
  8377. sqlite3_result_int64(ctx, pSeg->iOrigin2);
  8378. break;
  8379. case 8: /* npgtombstone */
  8380. sqlite3_result_int(ctx, pSeg->nPgTombstone);
  8381. break;
  8382. case 9: /* nentrytombstone */
  8383. sqlite3_result_int64(ctx, pSeg->nEntryTombstone);
  8384. break;
  8385. case 10: /* nentry */
  8386. sqlite3_result_int64(ctx, pSeg->nEntry);
  8387. break;
  8388. }
  8389. return SQLITE_OK;
  8390. }
  8391. /*
  8392. ** Initialize a cursor.
  8393. **
  8394. ** idxNum==0 means show all subprograms
  8395. ** idxNum==1 means show only the main bytecode and omit subprograms.
  8396. */
  8397. static int fts5structFilterMethod(
  8398. sqlite3_vtab_cursor *pVtabCursor,
  8399. int idxNum, const char *idxStr,
  8400. int argc, sqlite3_value **argv
  8401. ){
  8402. Fts5StructVcsr *pCsr = (Fts5StructVcsr *)pVtabCursor;
  8403. int rc = SQLITE_OK;
  8404. const u8 *aBlob = 0;
  8405. int nBlob = 0;
  8406. assert( argc==1 );
  8407. fts5StructureRelease(pCsr->pStruct);
  8408. pCsr->pStruct = 0;
  8409. nBlob = sqlite3_value_bytes(argv[0]);
  8410. aBlob = (const u8*)sqlite3_value_blob(argv[0]);
  8411. rc = fts5StructureDecode(aBlob, nBlob, 0, &pCsr->pStruct);
  8412. if( rc==SQLITE_OK ){
  8413. pCsr->iLevel = 0;
  8414. pCsr->iRowid = 0;
  8415. pCsr->iSeg = -1;
  8416. rc = fts5structNextMethod(pVtabCursor);
  8417. }
  8418. return rc;
  8419. }
  8420. #endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */
  8421. /*
  8422. ** This is called as part of registering the FTS5 module with database
  8423. ** connection db. It registers several user-defined scalar functions useful
  8424. ** with FTS5.
  8425. **
  8426. ** If successful, SQLITE_OK is returned. If an error occurs, some other
  8427. ** SQLite error code is returned instead.
  8428. */
  8429. int sqlite3Fts5IndexInit(sqlite3 *db){
  8430. #if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
  8431. int rc = sqlite3_create_function(
  8432. db, "fts5_decode", 2, SQLITE_UTF8, 0, fts5DecodeFunction, 0, 0
  8433. );
  8434. if( rc==SQLITE_OK ){
  8435. rc = sqlite3_create_function(
  8436. db, "fts5_decode_none", 2,
  8437. SQLITE_UTF8, (void*)db, fts5DecodeFunction, 0, 0
  8438. );
  8439. }
  8440. if( rc==SQLITE_OK ){
  8441. rc = sqlite3_create_function(
  8442. db, "fts5_rowid", -1, SQLITE_UTF8, 0, fts5RowidFunction, 0, 0
  8443. );
  8444. }
  8445. if( rc==SQLITE_OK ){
  8446. static const sqlite3_module fts5structure_module = {
  8447. 0, /* iVersion */
  8448. 0, /* xCreate */
  8449. fts5structConnectMethod, /* xConnect */
  8450. fts5structBestIndexMethod, /* xBestIndex */
  8451. fts5structDisconnectMethod, /* xDisconnect */
  8452. 0, /* xDestroy */
  8453. fts5structOpenMethod, /* xOpen */
  8454. fts5structCloseMethod, /* xClose */
  8455. fts5structFilterMethod, /* xFilter */
  8456. fts5structNextMethod, /* xNext */
  8457. fts5structEofMethod, /* xEof */
  8458. fts5structColumnMethod, /* xColumn */
  8459. fts5structRowidMethod, /* xRowid */
  8460. 0, /* xUpdate */
  8461. 0, /* xBegin */
  8462. 0, /* xSync */
  8463. 0, /* xCommit */
  8464. 0, /* xRollback */
  8465. 0, /* xFindFunction */
  8466. 0, /* xRename */
  8467. 0, /* xSavepoint */
  8468. 0, /* xRelease */
  8469. 0, /* xRollbackTo */
  8470. 0, /* xShadowName */
  8471. 0 /* xIntegrity */
  8472. };
  8473. rc = sqlite3_create_module(db, "fts5_structure", &fts5structure_module, 0);
  8474. }
  8475. return rc;
  8476. #else
  8477. return SQLITE_OK;
  8478. UNUSED_PARAM(db);
  8479. #endif
  8480. }
  8481. int sqlite3Fts5IndexReset(Fts5Index *p){
  8482. assert( p->pStruct==0 || p->iStructVersion!=0 );
  8483. if( fts5IndexDataVersion(p)!=p->iStructVersion ){
  8484. fts5StructureInvalidate(p);
  8485. }
  8486. return fts5IndexReturn(p);
  8487. }