sdDB.pas 286 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175
  1. {
  2. zhangyin
  3. 2017-11-14 TsdDataView增加主从表功能,用法同TDataSet
  4. 2017-11-30 TsdDataView增加Filter,用法同TDataSet.
  5. 大小写不敏感。
  6. 每个判断必须是[字段][运算符][值]的形式,例如 Type = 3。
  7. 判断之间只支持and, or
  8. 支持TsdDataSet所有字段类型。
  9. Boolean类型支持直接写True, False。
  10. 所有类型支持Null值
  11. 注意:1、Filter和SetRange某种程度上可以共存,先设置好Filter,再SetRange,
  12. Filter依然起作用,以后再SetRange,Filter也是起作用的。
  13. 但是SetRange完,再Filtered := True, Range就不起作用了。
  14. 为保险起见,还是不要一起用。
  15. 2、OnFilterRecord事件仍然有效,每条记录先Filter,再触发事件
  16. 3、SetRange比Filter效率高得多,但是单次操作对比不会很明显。
  17. (单字段过滤300条记录大约是0.001秒和0.00015秒的区别。
  18. Filter的速度跟记录数和作为条件的字段数量成正比。
  19. SetRange的速度跟索引的分布有关系,
  20. 以Code这种分散的字段为索引,时间是0.00015秒,以Type这种集中的字段为索引,时间趋近于0)
  21. 4、Filter使用更灵活,SetRange必须有对应索引,限制较多。
  22. Filter适合条件较复杂的情况,SetRange适合条件单一并且适合建立索引的情况。
  23. 2017-12-1 补充
  24. 典型测试:
  25. “K线”项目Bills表,3211条记录。
  26. 过滤条件'(ID > 10000) and (Flag = 0)'。
  27. Filter:0.031秒
  28. 极限测试:
  29. “K线”项目GLJList表,92041条记录。
  30. 过滤条件'(Type = 3) and (BillsItemID = 5722)'。
  31. 全部加载42秒,Filter 0.828秒,SetRange 0.015秒。
  32. Filter和SetRange效率上有数量级的差距。
  33. 另:这么大的表不建议直接连接表格
  34. 2018-7-7
  35. 增加TsdDataRecord.Cancel方法,用于回滚记录。
  36. 调用后,新增记录直接删除,修改值恢复。
  37. 在事件中调用,必须在AfterValueChanged事件及以前。
  38. 必须与BeginUpdate配合使用,否则报错。
  39. 调用一次Cancel即终止所有嵌套的BeginUpdate。
  40. 注意:事件中Cancel会对外部的嵌套BeginUpdate造成不好处理的情况,
  41. 所以原则上除非是对界面触发事件的处理,不要把代码写在事件里。
  42. 树结构暂不能支持新增节点的Cancel
  43. 2018-08-28
  44. 事件顺序调整,凡DataSet和DataView共有的事件,一律DataView的事件先触发,
  45. DataSet的事件后触发
  46. Lookup字段默认不可编辑,实在需要自动编辑,可在OnSetText事件中修改参数Allow
  47. 2019
  48. Lookup改为可编辑,只读由界面控制
  49. 2019-05-28
  50. TsdDataView.Filter增加Like运算符,可使用通配符用于字符串比较,详情可查看MatchesMask函数帮助
  51. 2024-12-11
  52. zhangyin
  53. 偶然发现Delphi的神奇现象
  54. 一个Boolean类型大小是一个bit,但是内存一次为其分配四个Byte
  55. 但是神奇的是,四个Boolean类型放到一起,还是只分配四个Byte
  56. 注意必须放一起,分开就不行
  57. 本次优化将TsdValue一个多余的Boolean字段删除,将三处分开的Boolean类型合并到一处,
  58. 一共节省8Byte(44->36, 18%),200,000条30个字段(GLJList有29个字段)的记录节省48MB内存,对于大项目还是有意义的。
  59. 实测一个大项目占用内存由1494.7MB减小到1349.6MB。
  60. 其他类的Boolean类型也做了相应的优化。
  61. 2024-12-18
  62. zhangyin
  63. 继续优化TsdValue:
  64. 1.删除无用字段FOldValue,FCachedValue及相关属性方法
  65. 2.将FEnableEvents上移到TsdDataSet.FEnableValueEvents
  66. 3.将FTag改为Byte类型,并与前三个Boolean类型放到一起,这样一共只占用4个Byte
  67. 共节省内存12Byte,现在实例占用内存24Byte
  68. 实测前述大项目内存减小到1199.6MB
  69. }
  70. unit sdDB;
  71. interface
  72. uses
  73. SysUtils, Classes, DB, DBConsts, Windows, Variants, sdInterface, FmtBcd,
  74. sdLogicalExprs;
  75. type
  76. EsdDataSet = class(Exception);
  77. EsdLog = class(Exception);
  78. TsdDataRecord = class;
  79. TsdField = class;
  80. TFieldName = string;
  81. { 暂时只支持
  82. ftString, ftWideString, ftSmallint, ftInteger, ftWord, ftBoolean, ftFloat,
  83. ftCurrency, ftDateTime, ftBCD, ftFMTBCD, ftMemo}
  84. TsdValue = class(TObject)
  85. private
  86. FIsNull: Boolean;
  87. FForceWriteData: Boolean;
  88. FOriginalCached: Boolean;
  89. FTag: Byte;
  90. FData: Pointer;
  91. FField: TsdField;
  92. FOwner: TsdDataRecord;
  93. FOriginalValue: Pointer;
  94. function GetAsBoolean: Boolean;
  95. function GetAsCurrency: Currency;
  96. function GetAsDateTime: TDateTime;
  97. function GetAsFloat: Double;
  98. function GetAsExtended: Extended;
  99. function GetAsInteger: Longint;
  100. function GetAsString: string;
  101. function GetAsWideString: WideString;
  102. function GetAsVariant: Variant;
  103. function GetAsBCD: TBCD;
  104. function GetDataSize: Integer;
  105. function GetDataType: TFieldType;
  106. function GetDisplayText: string;
  107. function GetEditText: string;
  108. function GetFieldName: string;
  109. function GetFieldNo: Integer;
  110. function GetIsNull: Boolean;
  111. procedure SetAsBoolean(const Value: Boolean);
  112. procedure SetAsCurrency(const Value: Currency);
  113. procedure SetAsDateTime(const Value: TDateTime);
  114. procedure SetAsFloat(const Value: Double);
  115. procedure SetAsExtended(const Value: Extended);
  116. procedure SetAsInteger(const Value: Longint);
  117. procedure SetAsString(const Value: string);
  118. procedure SetAsWideString(const Value: WideString);
  119. procedure SetAsVariant(const Value: Variant);
  120. procedure SetAsBCD(const Value: TBCD);
  121. procedure SetEditText(const Value: string);
  122. function ActualLength: Integer;
  123. procedure ConvertDataBeforeWriteData(const Value: string; var Data: Pointer;
  124. var NewValue: Variant; var Length: Integer; var NoNull: Boolean);
  125. function CanWriteData(Data, ACache: Pointer; Length: Integer; NoNull: Boolean): Boolean;
  126. procedure InnerWriteData(Data: Pointer; const NewValue: Variant; Length: Integer; NoNull: Boolean);
  127. procedure ReadData(var Data: Pointer; Length: Integer = 0);
  128. procedure WriteData(Data: Pointer; const NewValue: Variant; Length: Integer = 0; NoNull: Boolean = True);
  129. procedure TypeErrorOnWriting(const Value: Variant);
  130. function CopyCache: Pointer;
  131. procedure ClearCache(ACache: Pointer);
  132. //function GetSize: Integer;
  133. procedure InnerClear;
  134. procedure InnerCopy(AValue: Variant);
  135. function InnerCacheLength(ACache: Pointer): Integer;
  136. procedure InnerCopyCache(var ACache: Pointer);
  137. procedure InnerSetCache(var ACache: Pointer; AValue: Variant);
  138. function InnerGetCache(ACache: Pointer): Variant;
  139. function GetOriginalValue: Variant;
  140. procedure CacheOriginalValue;
  141. procedure ClearOriginalValue;
  142. protected
  143. procedure SetField(Field: TsdField);
  144. // zhangyin 2017-12-27 !!!for test only!!!
  145. function _CopyTo(Destination: Pointer): Integer;
  146. function _CopyFrom(Source: Pointer): Integer;
  147. function _MemorySize: Integer;
  148. procedure DisableEvents;
  149. procedure EnableEvents;
  150. public
  151. constructor Create(AOwner: TsdDataRecord); virtual;
  152. destructor Destroy; override;
  153. procedure Assign(Source: TsdValue);
  154. procedure Clear;
  155. property DataSize: Integer read GetDataSize;
  156. property DataType: TFieldType read GetDataType;
  157. property FieldName: string read GetFieldName;
  158. property FieldNo: Integer read GetFieldNo;
  159. property Field: TsdField read FField;
  160. property Owner: TsdDataRecord read FOwner;
  161. //property Size: Integer read GetSize;
  162. property IsNull: Boolean read GetIsNull;
  163. property Text: string read GetEditText write SetEditText;
  164. property DisplayText: string read GetDisplayText;
  165. property Value: Variant read GetAsVariant write SetAsVariant;
  166. property OriginalValue: Variant read GetOriginalValue;// write SetOriginalValue;
  167. property Tag: Byte read FTag write FTag;
  168. property ForceWriteData: Boolean read FForceWriteData write FForceWriteData;
  169. property AsBoolean: Boolean read GetAsBoolean write SetAsBoolean;
  170. property AsCurrency: Currency read GetAsCurrency write SetAsCurrency;
  171. property AsDateTime: TDateTime read GetAsDateTime write SetAsDateTime;
  172. property AsFloat: Double read GetAsFloat write SetAsFloat;
  173. property AsExtended: Extended read GetAsExtended write SetAsExtended;
  174. property AsInteger: Longint read GetAsInteger write SetAsInteger;
  175. property AsString: string read GetAsString write SetAsString;
  176. property AsWideString: WideString read GetAsWideString write SetAsWideString;
  177. property AsVariant: Variant read GetAsVariant write SetAsVariant;
  178. property AsBCD: TBCD read GetAsBCD write SetAsBCD;
  179. end;
  180. TsdValueList = class(TObject)
  181. private
  182. FOwner: TsdDataRecord;
  183. FList: TList;
  184. function GetValues(Index: Integer): TsdValue;
  185. function GetCount: Integer;
  186. function FindValue(Field: TsdField; var Value: TsdValue): Boolean;
  187. protected
  188. function Add(Field: TsdField): TsdValue;
  189. procedure Clear;
  190. public
  191. constructor Create(AOwner: TsdDataRecord); virtual;
  192. destructor Destroy; override;
  193. property Count: Integer read GetCount;
  194. property Values[Index: Integer]: TsdValue read GetValues; default;
  195. end;
  196. TsdIndex = class;
  197. TsdDataSet = class;
  198. TsdOperation = (sroAdd, sroModify, sroDelete, sdoActive, sdoRefresh, sdoReset);
  199. TsdDataRecordCache = class;
  200. TsdValueCache = class(TObject)
  201. private
  202. FModified: Boolean;
  203. FValue: Variant;
  204. procedure SetValue(const Value: Variant);
  205. public
  206. constructor Create(AOwner: TsdDataRecordCache); virtual;
  207. destructor Destroy; override;
  208. property Value: Variant read FValue write SetValue;
  209. property Modified: Boolean read FModified;
  210. end;
  211. TsdDataRecordCache = class(TObject)
  212. private
  213. FRecord: TsdDataRecord;
  214. FList: TList;
  215. procedure AddValues;
  216. function GetCount: Integer;
  217. function GetValues(I: Integer): TsdValueCache;
  218. public
  219. constructor Create(AOwner: TsdDataRecord); virtual;
  220. destructor Destroy; override;
  221. property Values[I: Integer]: TsdValueCache read GetValues;
  222. property Count: Integer read GetCount;
  223. end;
  224. TsdDataRecord = class(TObject)
  225. private
  226. FDeleted: Boolean;
  227. FIsInEvent: Boolean;
  228. FCanceled: Boolean;
  229. FIndex: Integer;
  230. FOwner: TsdDataSet;
  231. FUpdateLock: Integer;
  232. FInserting: Integer;
  233. FData: Pointer;
  234. FPData: Pointer;
  235. FCache: TsdDataRecordCache;
  236. procedure Clear;
  237. function GetValues(FieldNo: Integer): TsdValue;
  238. function GetIsUpdating: Boolean;
  239. function GetFieldValue(const FieldName: string): Variant;
  240. procedure NotifyIndex(Value: TsdValue);
  241. procedure ForceNotifyIndex;
  242. procedure NotifyLookup(Field: TsdField);
  243. function GetCount: Integer;
  244. function GetInserting: Boolean;
  245. procedure SetInserting(Value, NeedBeginUpdate: Boolean);
  246. procedure SetData(const Value: Pointer);
  247. procedure BeginTrans;
  248. procedure EndTrans;
  249. procedure Rollback;
  250. procedure CacheModified(Source: TsdValue);
  251. protected
  252. FRecNo: Integer;
  253. FNew: Boolean;
  254. FModified: Boolean;
  255. FNeedNotifyIndex: Boolean;
  256. FValueList: TsdValueList;
  257. FChangedValueList: TList;
  258. procedure Changed(Value: TsdValue); virtual;
  259. procedure DoAfterAddFields; virtual;
  260. procedure SetPData(Value: Pointer);
  261. property FieldValues[const FieldName: string]: Variant read GetFieldValue;
  262. property IsInEvent: Boolean read FIsInEvent;
  263. property Canceled: Boolean read FCanceled;
  264. public
  265. constructor Create(AOwner: TsdDataSet); virtual;
  266. destructor Destroy; override;
  267. procedure AddFields;
  268. function AddValue(FieldNo: Integer; DBField: TField): TsdValue; overload;
  269. function AddValue(Field: TsdField; Value: Variant; IsNull: Boolean = False): TsdValue; overload;
  270. function AddValue(FieldName: string; Value: Variant; IsNull: Boolean = False): TsdValue; overload;
  271. function ValueByName(FieldName: string): TsdValue;
  272. procedure Loaded;
  273. procedure BeginUpdate;
  274. procedure EndUpdate;
  275. procedure Cancel;
  276. procedure DoAfterSaved;
  277. procedure EnterEvent;
  278. procedure ExitEvent;
  279. procedure Delete;
  280. property MainIndex: Integer read FIndex;
  281. property Deleted: Boolean read FDeleted;
  282. property Modified: Boolean read FModified;
  283. // 标记未保存的新增记录
  284. property New: Boolean read FNew;
  285. property Owner: TsdDataSet read FOwner;
  286. property RecNo: Integer read FRecNo;
  287. property Count: Integer read GetCount;
  288. property IsUpdating: Boolean read GetIsUpdating;
  289. // 标记正在插入的记录
  290. property Inserting: Boolean read GetInserting;
  291. property Values[FieldNo: Integer]: TsdValue read GetValues; default;
  292. property Data: Pointer read FData write SetData;
  293. // 私有指针,暂时仅用于存放IDTree对应节点(树有Link的情况下,存放原始节点)
  294. property PData: Pointer read FPData;
  295. end;
  296. {
  297. TsdIndexData
  298. 索引原理
  299. 数据结构:
  300. 排序后的 | Field 1 (Level 1) | Field 2 (Level 2) |...
  301. RecordIndex | Key Index | Key Value | Key Index | Key Value |...
  302. -------------------------------------------------------------------
  303. 0 | | | | |...
  304. | | | | |
  305. 1 | | | 0 | 1 |...
  306. | | | | |
  307. 2 | 0 | 6 | | |...
  308. | | |-----------------------|
  309. 3 | | | | |...
  310. | | | 1 | 3 |
  311. 4 | | | | |...
  312. |-----------------------------------------------|
  313. 5 | | | | |...
  314. | | | 2 | 1 |
  315. 6 | 1 | 8 | | |...
  316. | | |-----------------------|
  317. 7 | | | 3 | 2 |...
  318. |-----------------------------------------------|
  319. 8 | 2 | 11 | 4 | 1 |...
  320. -------------------------------------------------------------------
  321. 将索引数据建立成树结构方便维护
  322. 2017/9/25
  323. 此索引结构有一个缺陷,当使用两个或以上字段SetRange时,字段之间并不是and关系,而是根据树结构进行过滤。
  324. 例如,上面的数据SetRange([0, 0], [9, 1])时,只要Filed 1值在1-8之间的记录都会被过滤出来,
  325. 不论Field 2的值是否在0-1之间。因为根据树结构,不管Field 2是什么值,它们都是1-8的子节点。
  326. 此时采用Filter才能过滤出正确的结果。
  327. 对ClientDataSet进行了验证,也是相同的结果,所以暂不进行修改。
  328. }
  329. EsdIndex = class(Exception);
  330. TsdIndexNode = class(TObject)
  331. private
  332. FOwner: TsdIndex;
  333. FRecIndex: Integer;
  334. FParent: TsdIndexNode;
  335. FPrevSibling: TsdIndexNode;
  336. FNextSibling: TsdIndexNode;
  337. FFirstChild: TsdIndexNode;
  338. FValue: Variant;
  339. FDataType: TFieldType;
  340. procedure SetFirstChild(const Value: TsdIndexNode);
  341. procedure SetNextSibling(const Value: TsdIndexNode);
  342. procedure SetParent(const Value: TsdIndexNode);
  343. procedure SetPrevSibling(const Value: TsdIndexNode);
  344. procedure SetRecIndex(const Value: Integer);
  345. procedure SetValue(const Value: Variant);
  346. function GetRecordCount: Integer;
  347. function GetLastPosterity: TsdIndexNode;
  348. function GetLastChild: TsdIndexNode;
  349. function GetChildCount: Integer;
  350. function GetLevel: Integer;
  351. procedure SetDataType(const Value: TFieldType);
  352. function NextNodeByLevel: TsdIndexNode;
  353. function GetChildren(Index: Integer): TsdIndexNode;
  354. public
  355. constructor Create(AOwner: TsdIndex); virtual;
  356. destructor Destroy; override;
  357. function HasRecord(ARecord: TsdDataRecord): Boolean;
  358. property Parent: TsdIndexNode read FParent write SetParent;
  359. property FirstChild: TsdIndexNode read FFirstChild write SetFirstChild;
  360. property PrevSibling: TsdIndexNode read FPrevSibling write SetPrevSibling;
  361. property NextSibling: TsdIndexNode read FNextSibling write SetNextSibling;
  362. property LastChild: TsdIndexNode read GetLastChild;
  363. property LastPosterity: TsdIndexNode read GetLastPosterity;
  364. property RecIndex: Integer read FRecIndex write SetRecIndex;
  365. property Value: Variant read FValue write SetValue;
  366. property DataType: TFieldType read FDataType write SetDataType;
  367. property Level: Integer read GetLevel;
  368. property Children[Index: Integer]: TsdIndexNode read GetChildren;
  369. property ChildCount: Integer read GetChildCount;
  370. property RecordCount: Integer read GetRecordCount;
  371. end;
  372. TsdIndexList = class;
  373. // 索引寻找标志:小于最小值,找到指定索引,在两个值中间,大于最大值,空(索引子节点为空)
  374. TsdIndexFlag = (sifLessThanMin, sifFoundIndex, sifInTheMid, sifMoreThanMax, sifNull);
  375. TsdIndex = class(TPersistent)
  376. private
  377. FDescend: Boolean;
  378. FSortNullToLast: Boolean;
  379. FFieldNames: string;
  380. FName: string;
  381. procedure Clear;
  382. function GetKeyCount(Level: Integer): Integer;
  383. function GetRecords(Index: Integer): TsdDataRecord;
  384. function FindExistKeyIndex(ARecordIndex: Integer): Integer;
  385. procedure SetFieldNames(const Value: string);
  386. procedure ParseFields;
  387. function GetLevelCount: Integer;
  388. procedure SetName(const Value: string);
  389. function GetDataSet: TsdDataSet;
  390. procedure SetDescend(const Value: Boolean);
  391. function GetFields(Index: Integer): TsdField;
  392. function GetRecordCount: Integer;
  393. protected
  394. FOwner: TsdIndexList;
  395. FDataList: TList;
  396. FFieldList: TList;
  397. FIndexNodeList: TList;
  398. FIndexRoot: TsdIndexNode;
  399. FChangedList: TList;
  400. function GetValue(ARecord: TsdDataRecord; ALevel: Integer): Variant; virtual;
  401. function CompareData(ARec1, ARec2: TsdDataRecord): Integer; virtual;
  402. function CompareValue(const AValue1, AValue2: Variant): Integer; virtual;
  403. function CompareIndex(ARec1, ARec2: TsdDataRecord): Integer; virtual;
  404. procedure Sort; virtual;
  405. function Check(ARecord: TsdDataRecord): Integer; virtual;
  406. function FindIndexNode(KeyValues: Variant): TsdIndexNode;
  407. function KeyCount(KeyValues: Variant): Integer;
  408. procedure InnerDelete(ARecord: TsdDataRecord); virtual;
  409. procedure AddChangedRecord(ARecord: TsdDataRecord);
  410. procedure LoadProperty(Reader: TReader); virtual;
  411. procedure SaveProperty(Writer: TWriter); virtual;
  412. public
  413. constructor Create(AOwner: TsdIndexList); virtual;
  414. destructor Destroy; override;
  415. function FindKeyIndex(KeyValues: Variant): Integer;
  416. function FindKeyLastIndex(KeyValues: Variant): Integer;
  417. function FindKey(KeyValues: Variant): TsdDataRecord;
  418. // 找到最接近的索引,找到:返回 True,RecIndex返回索引值;找不到:返回False, RecIndex返回最接近的前一个节点索引值
  419. function FindNearestKeyIndex(KeyValues: Variant; var RecIndex: Integer;
  420. AIsEnd: Boolean = False): TsdIndexFlag;
  421. // for debug
  422. procedure GetDebugData;
  423. function SameKeyFields(AFieldNames: string): Boolean;
  424. function HasKeyFields(AFieldNames: string): Boolean;
  425. function IsKeyField(AFieldName: string): Boolean;
  426. function IndexOf(ARecord: TsdDataRecord): Integer;
  427. procedure AssignRecords(AList: TList);
  428. function Exchange(const Index1, Index2: Integer): Integer; overload;
  429. function Exchange(ARecord1, ARecord2: TsdDataRecord): Integer; overload;
  430. function Insert(ARecord: TsdDataRecord; Index: Integer): Integer;
  431. procedure Delete(ARecord: TsdDataRecord);
  432. // 获取指定索引指定关键字的记录列表,KeyValues为空则获取按该索引排序的所有记录
  433. function RecordsByKey(KeyValues: Variant; List: TList): Integer;
  434. function RecordCountByKey(KeyValues: Variant): Integer;
  435. property DataSet: TsdDataSet read GetDataSet;
  436. property LevelCount: Integer read GetLevelCount;
  437. // 注意:在DataSet添加了记录,但是还未对索引排序的时候,索引的RecordCount比DataSet少一个
  438. property RecordCount: Integer read GetRecordCount;
  439. property Records[Index: Integer]: TsdDataRecord read GetRecords;
  440. property Fields[Index: Integer]: TsdField read GetFields;
  441. published
  442. property Name: string read FName write SetName;
  443. property FieldNames: string read FFieldNames write SetFieldNames;
  444. property Descend: Boolean read FDescend write SetDescend default False;
  445. property SortNullToLast: Boolean read FSortNullToLast write FSortNullToLast default True;
  446. end;
  447. TsdIndexList = class(TPersistent)
  448. private
  449. FOwner: TsdDataSet;
  450. FList: TList;
  451. function GetItems(I: Integer): TsdIndex;
  452. function GetCount: Integer;
  453. public
  454. constructor Create(AOwner: TsdDataSet); virtual;
  455. destructor Destroy; override;
  456. procedure Clear;
  457. procedure ClearData;
  458. function Add: TsdIndex;
  459. procedure Delete(Name: string); overload;
  460. procedure Delete(Index: TsdIndex); overload;
  461. procedure Exchange(Index1, Index2: TsdIndex);
  462. function FindByName(Name: string): TsdIndex;
  463. function FindByKeyFields(KeyFields: string; Partial: Boolean): TsdIndex;
  464. function IsKeyField(AFieldName: string): Boolean;
  465. procedure Check(ARecord: TsdDataRecord);
  466. procedure DeleteRecord(ARecord: TsdDataRecord);
  467. procedure Sort;
  468. property Count: Integer read GetCount;
  469. property Items[I: Integer]: TsdIndex read GetItems; default;
  470. end;
  471. // 进度事件,参数AProgress为0-100的整数
  472. TsdOnProgressEvent = procedure (AProgress: Integer) of object;
  473. TsdRecordClass = class of TsdDataRecord;
  474. TsdFieldList = class;
  475. TsdViewColumn = class;
  476. TsdField = class(TPersistent)
  477. private
  478. FIsKey: Boolean;
  479. FNeedProcessName: Boolean;
  480. FOwner: TsdFieldList;
  481. FDataSize: Integer;
  482. FFieldName: string;
  483. FDataType: TFieldType;
  484. FName: string;
  485. FInnerValidChars: TFieldChars;
  486. FValidChars: TFieldChars;
  487. FLookupList: TList;
  488. FSize: Integer;
  489. FPrecision: Integer;
  490. function GetFieldNo: Integer;
  491. procedure SetDataSize(const Value: Integer);
  492. procedure SetFieldName(const Value: string);
  493. function GetDataSize: Integer;
  494. procedure SetDataType(const Value: TFieldType);
  495. function IsBlobField: Boolean;
  496. function GetDataSet: TsdDataSet;
  497. procedure RefreshLookup;
  498. function HasLookup: Boolean;
  499. procedure ClearLookupField;
  500. procedure ClearLookupDataSet;
  501. procedure SetPrecision(const Value: Integer);
  502. procedure SetSize(const Value: Integer);
  503. protected
  504. procedure LoadProperty(Reader: TReader); virtual;
  505. procedure SaveProperty(Writer: TWriter); virtual;
  506. public
  507. constructor Create(AOwner: TsdFieldList); virtual;
  508. destructor Destroy; override;
  509. procedure ProcessFieldName(FieldName: string);
  510. function IsValidChar(InputChar: Char): Boolean; virtual;
  511. function IsVarField: Boolean;
  512. procedure AddLookupCol(AViewCol: TsdViewColumn);
  513. procedure RemoveLookupCol(AViewCol: TsdViewColumn);
  514. property DataSet: TsdDataSet read GetDataSet;
  515. property FieldNo: Integer read GetFieldNo;
  516. property NeedProcessName: Boolean read FNeedProcessName write FNeedProcessName;
  517. property IsKey: Boolean read FIsKey write FIsKey;
  518. property ValidChars: TFieldChars read FValidChars write FValidChars;
  519. published
  520. property Name: string read FName write FName;
  521. property DataSize: Integer read GetDataSize write SetDataSize;
  522. property DataType: TFieldType read FDataType write SetDataType;
  523. property FieldName: string read FFieldName write SetFieldName;
  524. // 这两个字段为FmtBcd字段专用
  525. property Precision: Integer read FPrecision write SetPrecision;
  526. property Size: Integer read FSize write SetSize;
  527. end;
  528. TsdFieldList = class(TPersistent)
  529. private
  530. FDataSet: TsdDataSet;
  531. FList: TList;
  532. function GetFields(Index: Integer): TsdField;
  533. function GetCount: Integer;
  534. procedure ClearLookup;
  535. protected
  536. public
  537. constructor Create(AOwner: TsdDataSet); virtual;
  538. destructor Destroy; override;
  539. function Add: TsdField; overload;
  540. function Add(const FieldName: String; DataType: TFieldType;
  541. Size: Integer = 0): TsdField; overload;
  542. procedure Exchange(Field1, Field2: TsdField);
  543. procedure Clear;
  544. function Delete(Index: Integer): Boolean;
  545. function FieldByName(FieldName: string): TsdField;
  546. property Count: Integer read GetCount;
  547. property Fields[Index: Integer]: TsdField read GetFields; default;
  548. end;
  549. IsdHistoryObject = interface
  550. ['{58FE79E8-056B-4E1A-AE17-9CA9297EA5D4}']
  551. procedure Redo(AData: Pointer);
  552. procedure Undo(AData: Pointer);
  553. procedure FreeHistoryData(AData: Pointer);
  554. end;
  555. TsdRecordEvent = procedure (ARecord: TsdDataRecord) of object;
  556. TsdAllowRecordEvent = procedure (ARecord: TsdDataRecord; var Allow: Boolean) of object;
  557. TsdValueEvent = procedure (AValue: TsdValue) of object;
  558. TsdAllowValueEvent = procedure (AValue: TsdValue; const NewValue: Variant; var Allow: Boolean) of object;
  559. TsdGetRecordClass = procedure (var ARecordClass: TsdRecordClass) of object;
  560. TsdDataView = class;
  561. TsdHistoryList = class;
  562. TsdHistoryRecord = class;
  563. TsdOperationManager = class;
  564. TsdDataSet = class(TComponent{, IsdDataSet})
  565. private
  566. FDataList: TList;
  567. FIndexList: TsdIndexList;
  568. FFieldList: TsdFieldList;
  569. FActive: Boolean;
  570. FRecordClass: TsdRecordClass;
  571. FProvider: IsdProvider;
  572. FAutoGetFields: Boolean;
  573. FHasKey: Boolean;
  574. FIsLoading: Boolean;
  575. FUpdateLock: Integer;
  576. FViewList: TList;
  577. FOnProgress: TsdOnProgressEvent;
  578. FBeforeDeleteRecord: TsdAllowRecordEvent;
  579. FBeforeAddRecord: TsdAllowRecordEvent;
  580. FAfterDeleteRecord: TsdRecordEvent;
  581. FAfterAddRecord: TsdRecordEvent;
  582. FAfterRecordChanged: TsdRecordEvent;
  583. FDesigner: TObject;
  584. FIndexDesigner: TObject;
  585. FStreamedActive: Boolean;
  586. FLoadDefaultFields: Boolean;
  587. FOnGetRecordClass: TsdGetRecordClass;
  588. FDisableCount: Integer;
  589. FAfterClose: TNotifyEvent;
  590. FAfterOpen: TNotifyEvent;
  591. FBeforeValueChange: TsdAllowValueEvent;
  592. FAfterValueChanged: TsdValueEvent;
  593. FBeforeRecordUpdate: TsdRecordEvent;
  594. FAfterRecordUpdated: TsdRecordEvent;
  595. FChangedLookupFields: TList;
  596. FKeepPosition: Boolean;
  597. FFiltered: Boolean;
  598. FFilter: string;
  599. FUseSavePoint: Boolean;
  600. FOperationManager: TsdOperationManager;
  601. FSavedPoint: Integer;
  602. function GetRecordCount: Integer;
  603. function GetRecords(Index: Integer): TsdDataRecord;
  604. procedure SetActive(const Value: Boolean);
  605. procedure SetRecordClass(const Value: TsdRecordClass);
  606. procedure SortDeletedRecords;
  607. procedure SortIndex;
  608. procedure ClearIndexData;
  609. procedure SetOnProgress(const Value: TsdOnProgressEvent);
  610. procedure CheckIndex(ARec: TsdDataRecord);
  611. procedure DeleteRecordIndex(ARec: TsdDataRecord);
  612. function IsDesigning: Boolean;
  613. function GetProvider: IsdProvider;
  614. procedure SetProvider(const Value: IsdProvider);
  615. function InnerLocate(const KeyFields: string; const KeyValues: Variant): TsdDataRecord;
  616. procedure Changed(const Sender: TObject; AOperation: TsdOperation);
  617. procedure NotifyChanged(const Sender: TObject;
  618. AOperation: TsdOperation);
  619. procedure AddToDeletedList(ARecord: TsdDataRecord);
  620. function GetHasKey: Boolean;
  621. procedure ClearViews;
  622. procedure SetAfterAddRecord(const Value: TsdRecordEvent);
  623. procedure SetAfterDeleteRecord(const Value: TsdRecordEvent);
  624. procedure SetAfterRecordChanged(const Value: TsdRecordEvent);
  625. procedure SetBeforeAddRecord(const Value: TsdAllowRecordEvent);
  626. procedure SetBeforeDeleteRecord(const Value: TsdAllowRecordEvent);
  627. procedure DoBeforeAddRecord(ARecord: TsdDataRecord; var Allow: Boolean);
  628. procedure DoAfterAddRecord(ARecord: TsdDataRecord);
  629. procedure DoAfterRecordChanged(ARecord: TsdDataRecord);
  630. procedure DoBeforeValueChange(AValue: TsdValue; const NewValue: Variant; var Allow: Boolean);
  631. procedure DoAfterValueChanged(AValue: TsdValue);
  632. procedure DoBeforeDeleteRecord(ARecord: TsdDataRecord; var Allow: Boolean);
  633. procedure DoAfterDeleteRecord(ARecord: TsdDataRecord);
  634. function GetFieldCount: Integer;
  635. procedure ProcessFieldNames;
  636. procedure SetOnGetRecordClass(const Value: TsdGetRecordClass);
  637. procedure SetAfterClose(const Value: TNotifyEvent);
  638. procedure SetAfterOpen(const Value: TNotifyEvent);
  639. procedure SetAfterRecordChange(const Value: TsdRecordEvent);
  640. procedure SetAfterValueChanged(const Value: TsdValueEvent);
  641. procedure SetBeforeValueChange(const Value: TsdAllowValueEvent);
  642. procedure SetAfterRecordUpdated(const Value: TsdRecordEvent);
  643. procedure SetBeforeRecordUpdate(const Value: TsdRecordEvent);
  644. procedure DoBeforeRecordUpdate(ARecord: TsdDataRecord);
  645. procedure DoAfterRecordUpdated(ARecord: TsdDataRecord);
  646. function GetModified: Boolean;
  647. procedure CheckChangedLookupFields(AField: TsdField; ARecord: TsdDataRecord = nil);
  648. procedure IndexDeleted(AIndexName: string);
  649. procedure SetFilter(const Value: string);
  650. procedure SetFiltered(const Value: Boolean);
  651. function GetSavePoint: Integer;
  652. procedure SetSavePoint(const Value: Integer);
  653. procedure SetUseSavePoint(const Value: Boolean);
  654. protected
  655. FCurrentView: TsdDataView;
  656. FEventRec: TsdDataRecord;
  657. FDeletedList: TList;
  658. FChangedList: TList;
  659. FHistory: TsdHistoryList;
  660. FTableName: string;
  661. FEnableValueEvents: Boolean;
  662. function CreateRecord: TsdDataRecord; virtual;
  663. procedure LoadRecords; virtual;
  664. procedure SaveRecords; virtual;
  665. procedure ClearRecords(AClearAutoFields: Boolean); virtual;
  666. procedure InitRecord(ARecord: TsdDataRecord);
  667. function AddRecord(ARecord: TsdDataRecord; NeedBeginUpdate: Boolean = False): Integer; virtual;
  668. function RemoveRecord(ARec: TsdDataRecord; FreeRecord: Boolean = True): Boolean; virtual;
  669. procedure RenumberIndex(AFromIndex: Integer = 0);
  670. procedure DeleteRecNo(ARecNo: Integer);
  671. procedure InsertRecNo(ARecNo: Integer);
  672. procedure ClearDeletedList;
  673. procedure ClearChangedList;
  674. procedure DefineProperties(Filer: TFiler); override;
  675. procedure ReadFields(Stream: TStream);
  676. procedure WriteFields(Stream: TStream);
  677. procedure ReadIndexes(Stream: TStream);
  678. procedure WriteIndexes(Stream: TStream);
  679. procedure Loaded; override;
  680. procedure CheckActive;
  681. procedure CheckForSave;
  682. procedure CancelRecord(ARecord: TsdDataRecord);
  683. // 根据AFields比较记录,-1: ARec1 < ARec2; 0: ARec1 = ARec2; 1: ARec1 > ARec2
  684. function CompareRec(ARec1, ARec2: TsdDataRecord; AKeyFields: string): Integer;
  685. // 根据AFields对AList中的记录排序
  686. procedure SortList(AList: TList; AKeyFields: string);
  687. property HasKey: Boolean read GetHasKey;
  688. public
  689. constructor Create(AOwner: TComponent); override;
  690. destructor Destroy; override;
  691. procedure Open;
  692. procedure Close;
  693. procedure Save;
  694. procedure BeginLoad;
  695. procedure EndLoad;
  696. procedure BeginUpdate;
  697. procedure EndUpdate;
  698. function IsUpdating: Boolean;
  699. procedure BeginUpdateHistoryRecord(ARecord: TsdDataRecord);
  700. procedure EndUpdateHistoryRecord;
  701. procedure RegisterView(AView: TObject);
  702. procedure UnregisterView(AView: TObject);
  703. procedure GetFieldNames(AFieldNames: TStringList);
  704. function FieldByName(AFieldName: string): TsdField;
  705. function Add(NeedBeginUpdate: Boolean = False): TsdDataRecord;
  706. function AddField(const FieldName: string): TsdField;
  707. function AddIndex(const Name, Fields: string): TsdIndex;
  708. function Delete(AIndex: Integer): Boolean;
  709. procedure DeleteAll;
  710. procedure ClearIndex;
  711. function Remove(ARec: TsdDataRecord): Boolean;
  712. function IndexOf(ARecord: TsdDataRecord): Integer;
  713. function FindKey(AIndexName: string; KeyValues: Variant): TsdDataRecord;
  714. function FindIndex(AIndexName: string): TsdIndex;
  715. function Locate(const KeyFields: string; const KeyValues: Variant): TsdDataRecord;
  716. function Lookup(const KeyFields: string; const KeyValues: Variant;
  717. const ResultFields: string): Variant;
  718. // 获取指定索引指定关键字的记录列表,KeyValues为空则获取按该索引排序的所有记录
  719. function RecordsByKey(const AIndexName: string; const KeyValues: Variant;
  720. List: TList): Integer;
  721. procedure AssignRecords(AList: TList);
  722. function ControlsDisabled: Boolean;
  723. procedure DisableControls;
  724. procedure EnableControls;
  725. function CurrentView: TsdDataView;
  726. procedure LoadFromXML(AFileName: string);
  727. procedure SaveToXML(AFileName: string);
  728. procedure FreeProviderNotify;
  729. procedure Reload;
  730. procedure SortByFields(const KeyFields: string; AList: TList);
  731. procedure FilterBy(const AFilter: string; AList: TList;
  732. AKeyFields: string = '');
  733. procedure ClearCurrentView;
  734. // 供外部对象(IsdHistoryObject)记录额外信息
  735. procedure WriteHistoryData(AOperation: TsdOperation; AObject: IsdHistoryObject; AData: Pointer);
  736. procedure Undo(AID: Integer);
  737. procedure Redo(AID: Integer);
  738. // 挂起,暂停操作记录
  739. procedure SuspendHistory;
  740. // 继续记录
  741. procedure ResumeHistory;
  742. property RecordClass: TsdRecordClass read FRecordClass write SetRecordClass;
  743. property RecordCount: Integer read GetRecordCount;
  744. property FieldCount: Integer read GetFieldCount;
  745. property Records[Index: Integer]: TsdDataRecord read GetRecords; default;
  746. property Designer: TObject read FDesigner write FDesigner;
  747. property IndexDesigner: TObject read FIndexDesigner write FIndexDesigner;
  748. property LoadDefaultFields: Boolean read FLoadDefaultFields write FLoadDefaultFields;
  749. property Modified: Boolean read GetModified;
  750. property SavePoint: Integer read GetSavePoint write SetSavePoint;
  751. // 保存到数据库的SavePoint
  752. property SavedPoint: Integer read FSavedPoint;
  753. property TableName: string read FTableName;
  754. property OperationManager: TsdOperationManager read FOperationManager;
  755. published
  756. property Active: Boolean read FActive write SetActive;
  757. property Fields: TsdFieldList read FFieldList;
  758. property Filter: string read FFilter write SetFilter;
  759. property Filtered: Boolean read FFiltered write SetFiltered;
  760. property IndexList: TsdIndexList read FIndexList;
  761. property Provider: IsdProvider read GetProvider write SetProvider;
  762. property UseSavePoint: Boolean read FUseSavePoint write SetUseSavePoint;
  763. property BeforeAddRecord: TsdAllowRecordEvent read FBeforeAddRecord write SetBeforeAddRecord;
  764. property AfterAddRecord: TsdRecordEvent read FAfterAddRecord write SetAfterAddRecord;
  765. property BeforeDeleteRecord: TsdAllowRecordEvent read FBeforeDeleteRecord write SetBeforeDeleteRecord;
  766. property AfterDeleteRecord: TsdRecordEvent read FAfterDeleteRecord write SetAfterDeleteRecord;
  767. property AfterRecordChanged: TsdRecordEvent read FAfterRecordChanged write SetAfterRecordChanged;
  768. property BeforeValueChange: TsdAllowValueEvent read FBeforeValueChange write SetBeforeValueChange;
  769. property AfterValueChanged: TsdValueEvent read FAfterValueChanged write SetAfterValueChanged;
  770. property BeforeRecordUpdate: TsdRecordEvent read FBeforeRecordUpdate write SetBeforeRecordUpdate;
  771. property AfterRecordUpdated: TsdRecordEvent read FAfterRecordUpdated write SetAfterRecordUpdated;
  772. property AfterClose: TNotifyEvent read FAfterClose write SetAfterClose;
  773. property AfterOpen: TNotifyEvent read FAfterOpen write SetAfterOpen;
  774. property OnProgress: TsdOnProgressEvent read FOnProgress write SetOnProgress;
  775. property OnGetRecordClass: TsdGetRecordClass read FOnGetRecordClass write SetOnGetRecordClass;
  776. end;
  777. EsdDataView = class(Exception);
  778. TsdViewColumn = class(TCollectionItem)
  779. private
  780. FFieldName: string;
  781. FField: TsdField;
  782. FDisplayFormat: string;
  783. FEditFormat: string;
  784. FLookupField: TsdField;
  785. FKeyFields: string;
  786. FLookupKeyFields: string;
  787. FLookupResultField: string;
  788. FLookupDataSet: TsdDataSet;
  789. FData: Pointer;
  790. procedure SetFieldName(const Value: string);
  791. procedure SetDisplayFormat(const Value: string);
  792. procedure SetEditFormat(const Value: string);
  793. function GetDataView: TsdDataView;
  794. function GetIsLookup: Boolean;
  795. procedure SetKeyFields(const Value: string);
  796. procedure SetLookupDataSet(const Value: TsdDataSet);
  797. procedure SetLookupKeyFields(const Value: string);
  798. procedure SetLookupResultField(const Value: string);
  799. procedure CheckLookupField;
  800. procedure LookupChanged;
  801. protected
  802. function GetDisplayName: string; override;
  803. public
  804. constructor Create(Collection: TCollection); override;
  805. destructor Destroy; override;
  806. function FormatText(Value: TsdValue; DisplayText: Boolean): string;
  807. procedure Assign(Source: TPersistent); override;
  808. property Field: TsdField read FField;
  809. property LookUpField: TsdField read FLookupField;
  810. property DataView: TsdDataView read GetDataView;
  811. property IsLookup: Boolean read GetIsLookup;
  812. property Data: Pointer read FData write FData;
  813. published
  814. property FieldName: string read FFieldName write SetFieldName;
  815. property DisplayFormat: string read FDisplayFormat write SetDisplayFormat;
  816. property EditFormat: string read FEditFormat write SetEditFormat;
  817. property KeyFields: string read FKeyFields write SetKeyFields;
  818. property LookupDataSet: TsdDataSet read FLookupDataSet write SetLookupDataSet;
  819. property LookupKeyFields: string read FLookupKeyFields write SetLookupKeyFields;
  820. property LookupResultField: string read FLookupResultField write SetLookupResultField;
  821. end;
  822. TsdViewColumnClass = class of TsdViewColumn;
  823. TsdViewColumnList = class(TCollection)
  824. private
  825. FDataView: TsdDataView;
  826. function GetItem(Index: Integer): TsdViewColumn;
  827. procedure SetItem(Index: Integer; const Value: TsdViewColumn);
  828. protected
  829. function GetOwner: TPersistent; override;
  830. procedure Update(Item: TCollectionItem); override;
  831. public
  832. constructor Create(ADataView: TsdDataView; ItemClass: TsdViewColumnClass);
  833. function Add: TsdViewColumn;
  834. function IndexByName(const AFieldName: string): Integer;
  835. function FindColumn(const AFieldName: string): TsdViewColumn;
  836. procedure Assign(Source: TPersistent); override;
  837. property DataView: TsdDataView read FDataView;
  838. property Items[Index: Integer]: TsdViewColumn read GetItem write SetItem; default;
  839. end;
  840. TsdColumnGetTextEvent = procedure (var Text: string; ARecord: TsdDataRecord;
  841. AValue: TsdValue; AColumn: TsdViewColumn; DisplayText: Boolean) of object;
  842. TsdColumnSetTextEvent = procedure (var Text: string; ARecord: TsdDataRecord;
  843. AValue: TsdValue; AColumn: TsdViewColumn; var Allow: Boolean) of object;
  844. TsdNeedLookupRecordEvent = procedure (ARecord: TsdDataRecord;
  845. AColumn: TsdViewColumn; ANewText: string) of object;
  846. TsdCustomSortEvent = procedure (RecordList: TList) of object;
  847. TsdDataView = class(TComponent)
  848. private
  849. FActive: Boolean;
  850. FStreamedActive: Boolean;
  851. FDataList: TList;
  852. FIndexName: string;
  853. FIndex: TsdIndex;
  854. FOnFilterRecord: TsdAllowRecordEvent;
  855. FDataSet: TsdDataSet;
  856. FColumns: TsdViewColumnList;
  857. FOnGetText: TsdColumnGetTextEvent;
  858. FOnSetText: TsdColumnSetTextEvent;
  859. FFiltered: Boolean;
  860. FRangeFrom: Variant;
  861. FRangeTo: Variant;
  862. FControlList: TInterfaceList;
  863. FCurrent: TsdDataRecord;
  864. FCurrentIndex: Integer;
  865. FBeforeDeleteRecord: TsdAllowRecordEvent;
  866. FBeforeAddRecord: TsdAllowRecordEvent;
  867. FBeforeValueChange: TsdAllowValueEvent;
  868. FAfterAddRecord: TsdRecordEvent;
  869. FAfterDeleteRecord: TsdRecordEvent;
  870. FAfterValueChanged: TsdValueEvent;
  871. FBeforeSortAddedRecord: TsdRecordEvent;
  872. FAfterClose: TNotifyEvent;
  873. FAfterOpen: TNotifyEvent;
  874. FOnCurrentChanged: TsdRecordEvent;
  875. FOnNeedLookupRecord: TsdNeedLookupRecordEvent;
  876. FRangeLock: Integer;
  877. FAfterRecordChanged: TsdRecordEvent;
  878. FMasterField: string;
  879. FKeyField: string;
  880. FMasterDataView: TsdDataView;
  881. FDetailList: TList;
  882. FFilterHelper: TsdLogicalExprs;
  883. FFilter: string;
  884. FNewCurrent: TsdDataRecord;
  885. FCurrentChanging: Boolean;
  886. FOnCustomSort: TsdCustomSortEvent;
  887. FBeforeCurrentChange: TsdRecordEvent;
  888. FOldCurrentIndex: Integer;
  889. FOldCurrent: TsdDataRecord;
  890. FAutoGetFields: Boolean;
  891. function GetFieldCount: Integer;
  892. function GetIndex: TsdIndex;
  893. function GetRecord(Index: Integer): TsdDataRecord;
  894. function GetRecordCount: Integer;
  895. procedure SetActive(const Value: Boolean);
  896. procedure SetDataSet(const Value: TsdDataSet);
  897. procedure SetIndexName(const Value: string);
  898. procedure SetOnFilterRecord(const Value: TsdAllowRecordEvent);
  899. function GetDisplayText(RecIndex, Col: Integer): string;
  900. function GetText(RecIndex, Col: Integer): string;
  901. procedure SetText(RecIndex, Col: Integer; const Value: string);
  902. procedure SetOnGetText(const Value: TsdColumnGetTextEvent);
  903. procedure SetOnSetText(const Value: TsdColumnSetTextEvent);
  904. procedure SetFiltered(const Value: Boolean);
  905. function GetValue(RecIndex, Col: Integer): TsdValue; overload;
  906. function GetValue(RecIndex, Col: Integer; var NeedLookupRecord: Boolean): TsdValue; overload;
  907. procedure FilterRecords;
  908. function FilterRecord(ARecord: TsdDataRecord): Boolean;
  909. procedure InitRecords;
  910. procedure ResetIndex;
  911. procedure RefreshRange;
  912. function CheckRange(ARecord: TsdDataRecord; AValue: TsdValue = nil): Integer;
  913. procedure SetAfterAddRecord(const Value: TsdRecordEvent);
  914. procedure SetAfterDeleteRecord(const Value: TsdRecordEvent);
  915. procedure SetAfterValueChanged(const Value: TsdValueEvent);
  916. procedure SetBeforeAddRecord(const Value: TsdAllowRecordEvent);
  917. procedure SetBeforeDeleteRecord(const Value: TsdAllowRecordEvent);
  918. procedure SetBeforeValueChange(const Value: TsdAllowValueEvent);
  919. procedure SetBeforeSortAddedRecord(const Value: TsdRecordEvent);
  920. procedure SetColumns(const Value: TsdViewColumnList);
  921. procedure NotifyDataChanged(RecIndex: Integer = -1);
  922. procedure SetAfterClose(const Value: TNotifyEvent);
  923. procedure SetAfterOpen(const Value: TNotifyEvent);
  924. procedure DoBeforeAddRecord(ARecord: TsdDataRecord; var Allow: Boolean);
  925. procedure DoAfterAddRecord(ARecord: TsdDataRecord);
  926. procedure DoBeforeDeleteRecord(ARecord: TsdDataRecord; var Allow: Boolean);
  927. procedure DoAfterDeleteRecord(ARecord: TsdDataRecord);
  928. procedure DoBeforeValueChange(AValue: TsdValue; const NewValue: Variant; var Allow: Boolean);
  929. procedure DoAfterValueChanged(AValue: TsdValue);
  930. procedure DoAfterRecordChanged(ARecord: TsdDataRecord);
  931. procedure DoBeforeSortAddedRecord(ARecord: TsdDataRecord);
  932. procedure DoOnGetText(var Text: string; ARecord: TsdDataRecord;
  933. AValue: TsdValue; AColumn: TsdViewColumn; DisplayText: Boolean);
  934. procedure DoOnSetText(var Text: string; ARecord: TsdDataRecord;
  935. AValue: TsdValue; AColumn: TsdViewColumn; var Allow: Boolean);
  936. procedure DoCustomSort(RecordList: TList);
  937. procedure DoBeforeCurrentChange(ARecord: TsdDataRecord);
  938. procedure DoOnCurrentChanged(ARecord: TsdDataRecord);
  939. function GetCurrent: TsdDataRecord;
  940. procedure SetOnCurrentChanged(const Value: TsdRecordEvent);
  941. procedure RefreshField(AViewColumn: TsdViewColumn);
  942. procedure AddLookupRecord(ARecIndex, ACol: Integer; Text: string);
  943. procedure SetOnNeedLookupRecord(const Value: TsdNeedLookupRecordEvent);
  944. procedure NotifyControlActiveChanged;
  945. procedure NotifyControlDataViewChanged;
  946. procedure NotifyControlDataChanged(RecIndex: Integer = -1);
  947. procedure NotifyControlFieldChanged(AFieldName: string);
  948. procedure NotifyControlActiveRecordChanged(RecIndex: Integer);
  949. procedure SetValueText(AValue: TsdValue; ARecord: TsdDataRecord; var Text: string; AColumn: TsdViewColumn);
  950. function GetColumns(Index: Integer): TsdViewColumn;
  951. function GetRangeLocked: Boolean;
  952. procedure SetAfterRecordChanged(const Value: TsdRecordEvent);
  953. function GetCurrentIndex: Integer;
  954. procedure SetCurrentIndex(const Value: Integer);
  955. procedure CheckCurrent(AReset: Boolean = False);
  956. procedure ResetCurrent;
  957. procedure SetKeyField(const Value: string);
  958. procedure SetMasterDataView(const Value: TsdDataView);
  959. procedure SetMasterField(const Value: string);
  960. function IsDetail: Boolean;
  961. procedure SetFilter(const Value: string);
  962. procedure ParseFilter;
  963. procedure SetOnCustomSort(const Value: TsdCustomSortEvent);
  964. procedure SetBeforeCurrentChange(const Value: TsdRecordEvent);
  965. protected
  966. procedure Loaded; override;
  967. procedure ReloadFields;
  968. procedure ChangeCurrent;
  969. procedure MasterChanged(ACurrent: TsdDataRecord);
  970. procedure RegisterDetail(ADetail: TsdDataView);
  971. procedure UnRegisterDetail(ADetail: TsdDataView);
  972. procedure ClearMasterDataView;
  973. public
  974. constructor Create(AOwner: TComponent); override;
  975. destructor Destroy; override;
  976. procedure Open;
  977. procedure Close;
  978. procedure RefreshFilter;
  979. function IndexOf(ARecord: TsdDataRecord): Integer;
  980. function Append(NeedBeginUpdate: Boolean = False): TsdDataRecord;
  981. function Insert(Index: Integer; NeedBeginUpdate: Boolean = False): TsdDataRecord;
  982. function Delete(Index: Integer): Boolean;
  983. function Remove(ARecord: TsdDataRecord): Boolean;
  984. // edit方法是为了表示从View触发的修改,必须与BeginUpdate和EndUpdate一起使用
  985. procedure Edit(ARecord: TsdDataRecord);
  986. function Exchange(const Index1, Index2: Integer): Integer;
  987. // SetRange时,前一个参数为nil表示最小值,后一个参数为nil则表示最大值
  988. // 注意主从关系与SetRange冲突,但都可以叠加Filter
  989. procedure SetRange(const StartValues, EndValues: array of const);
  990. procedure CancelRange;
  991. procedure BeginLockRange;
  992. procedure EndLockRange(ARefresh: Boolean);
  993. procedure Changed(const Sender: TObject; AOperation: TsdOperation);
  994. procedure PrepareNewCurrent(ARecord: TsdDataRecord);
  995. procedure FreeNotify;
  996. procedure RegisterControl(Control: IsdViewControl);
  997. procedure UnRegisterControl(Control: IsdViewControl);
  998. procedure LoadDefaultColumns;
  999. function FindColumn(const AFieldName: string): TsdViewColumn;
  1000. procedure GetFieldNames(AFieldNames: TStringList);
  1001. function LocateInControl(ARecord: TsdDataRecord): Boolean; overload;
  1002. function LocateInControl(const KeyFields: string; const KeyValues: Variant): Boolean; overload;
  1003. // DataView的Locate未使用索引,效率较低,一般不用
  1004. function Locate(const KeyFields: string; const KeyValues: Variant): TsdDataRecord;
  1005. procedure First;
  1006. procedure Last;
  1007. procedure SaveToXML(AFileName: string);
  1008. procedure AssignRecords(AList: TList);
  1009. property DataSetIndex: TsdIndex read GetIndex;
  1010. property Records[Index: Integer]: TsdDataRecord read GetRecord; default;
  1011. property RecordCount: Integer read GetRecordCount;
  1012. property DisplayText[RecIndex, Col: Integer]: string read GetDisplayText;
  1013. property Text[RecIndex, Col: Integer]: string read GetText write SetText;
  1014. property FieldCount: Integer read GetFieldCount;
  1015. property Column[Index: Integer]: TsdViewColumn read GetColumns;
  1016. // 目前只有调用LocateInControl后Current才有意义
  1017. property Current: TsdDataRecord read GetCurrent;
  1018. property CurrentIndex: Integer read GetCurrentIndex write SetCurrentIndex;
  1019. property RangeLocked: Boolean read GetRangeLocked;
  1020. published
  1021. property Active: Boolean read FActive write SetActive;
  1022. property DataSet: TsdDataSet read FDataSet write SetDataSet;
  1023. property Filter: string read FFilter write SetFilter;
  1024. property Filtered: Boolean read FFiltered write SetFiltered;
  1025. property IndexName: string read FIndexName write SetIndexName;
  1026. property Columns: TsdViewColumnList read FColumns write SetColumns stored True;
  1027. property MasterDataView: TsdDataView read FMasterDataView write SetMasterDataView;
  1028. property MasterField: string read FMasterField write SetMasterField;
  1029. property KeyField: string read FKeyField write SetKeyField;
  1030. property BeforeAddRecord: TsdAllowRecordEvent read FBeforeAddRecord write SetBeforeAddRecord;
  1031. property BeforeSortAddedRecord: TsdRecordEvent read FBeforeSortAddedRecord write SetBeforeSortAddedRecord;
  1032. property AfterAddRecord: TsdRecordEvent read FAfterAddRecord write SetAfterAddRecord;
  1033. property BeforeDeleteRecord: TsdAllowRecordEvent read FBeforeDeleteRecord write SetBeforeDeleteRecord;
  1034. property AfterDeleteRecord: TsdRecordEvent read FAfterDeleteRecord write SetAfterDeleteRecord;
  1035. property BeforeValueChange: TsdAllowValueEvent read FBeforeValueChange write SetBeforeValueChange;
  1036. property AfterValueChanged: TsdValueEvent read FAfterValueChanged write SetAfterValueChanged;
  1037. property AfterRecordChanged: TsdRecordEvent read FAfterRecordChanged write SetAfterRecordChanged;
  1038. property AfterClose: TNotifyEvent read FAfterClose write SetAfterClose;
  1039. property AfterOpen: TNotifyEvent read FAfterOpen write SetAfterOpen;
  1040. property OnFilterRecord: TsdAllowRecordEvent read FOnFilterRecord write SetOnFilterRecord;
  1041. property BeforeCurrentChange: TsdRecordEvent read FBeforeCurrentChange write SetBeforeCurrentChange;
  1042. property OnCurrentChanged: TsdRecordEvent read FOnCurrentChanged write SetOnCurrentChanged;
  1043. property OnGetText: TsdColumnGetTextEvent read FOnGetText write SetOnGetText;
  1044. property OnSetText: TsdColumnSetTextEvent read FOnSetText write SetOnSetText;
  1045. property OnNeedLookupRecord: TsdNeedLookupRecordEvent read FOnNeedLookupRecord write SetOnNeedLookupRecord;
  1046. property OnCustomSort: TsdCustomSortEvent read FOnCustomSort write SetOnCustomSort;
  1047. end;
  1048. TsdAggregator = class(TComponent)
  1049. private
  1050. FIndex: TsdIndex;
  1051. FIndexName: string;
  1052. FDataSet: TsdDataSet;
  1053. procedure SetDataSet(const Value: TsdDataSet);
  1054. procedure SetIndexName(const Value: string);
  1055. public
  1056. constructor Create(AOwner: TComponent); override;
  1057. destructor Destroy; override;
  1058. function Aggregate(const KeyValues: Variant; const FieldName: string): Variant;
  1059. published
  1060. property DataSet: TsdDataSet read FDataSet write SetDataSet;
  1061. property IndexName: string read FIndexName write SetIndexName;
  1062. end;
  1063. // 以下类为主从表Map类,以便快速根据主表关键字对从表排序,
  1064. // 具体算法可见《有序双列表遍历算法》
  1065. // 对于DataSet,使用TsdDataSetMasterDetailMap,主从关键字段必须有相应的Index
  1066. // 对于DataView,使用TsdDataViewMasterDetailMap,主从关键字段必须是DataView已使用的Index
  1067. // 用法:设置好主从表,关键字,调用CreateMap方法
  1068. // Map.Items[I]为主表记录对象,Map.Items[I].DetailRecords为从表对象列表
  1069. // 可参考ProjectGLJ的GatherAll等方法
  1070. // 可通过ItemByRecord方法组合多个Map
  1071. // 需要过滤时,可以使用TsdListMasterDetailMap,对过滤好的List进行Map
  1072. TsdMasterItem = class;
  1073. TsdMasterDetailMap = class;
  1074. TsdDetailList = class(TObject)
  1075. private
  1076. FMasterItem: TsdMasterItem;
  1077. FList: TList;
  1078. function GetCount: Integer;
  1079. function GetRecords(Index: Integer): TsdDataRecord;
  1080. procedure Add(ARecord: TsdDataRecord);
  1081. public
  1082. constructor Create(AMasterItem: TsdMasterItem); virtual;
  1083. destructor Destroy; override;
  1084. property Count: Integer read GetCount;
  1085. property Records[Index: Integer]: TsdDataRecord read GetRecords; default;
  1086. end;
  1087. TsdMasterItem = class(TObject)
  1088. private
  1089. FMap: TsdMasterDetailMap;
  1090. FList: TsdDetailList;
  1091. FRec: TsdDataRecord;
  1092. function GetRecords(Index: Integer): TsdDataRecord;
  1093. function GetCount: Integer;
  1094. procedure AddDetailRec(ARecord: TsdDataRecord);
  1095. public
  1096. constructor Create(AMap: TsdMasterDetailMap); virtual;
  1097. destructor Destroy; override;
  1098. property Count: Integer read GetCount;
  1099. property Rec: TsdDataRecord read FRec;
  1100. property DetailRecords[Index: Integer]: TsdDataRecord read GetRecords; default;
  1101. end;
  1102. // 比较记录值事件,AResult:-1:主表值小,0:相等,1:从表值小
  1103. TsdCompareValuesEvent = procedure (MasterRecord, DetailRecord: TsdDataRecord;
  1104. var AResult: Integer) of object;
  1105. EsdMasterDetailMap = class(Exception);
  1106. TsdMasterDetailMap = class(TObject)
  1107. private
  1108. FList: TList;
  1109. FDetailField: string;
  1110. FMasterField: string;
  1111. FOnCompareValues: TsdCompareValuesEvent;
  1112. function GetCount: Integer;
  1113. function GetItems(Index: Integer): TsdMasterItem;
  1114. procedure SetDetailField(const Value: string);
  1115. procedure SetMasterField(const Value: string);
  1116. procedure SetOnCompareValues(const Value: TsdCompareValuesEvent);
  1117. procedure CompareValues(MasterRecord, DetailRecord: TsdDataRecord; var AResult: Integer);
  1118. protected
  1119. FMasterIndex: TsdIndex;
  1120. FDetailIndex: TsdIndex;
  1121. function GetMasterRecordCount: Integer; virtual; abstract;
  1122. function GetMasterRecords(AIndex: Integer): TsdDataRecord; virtual; abstract;
  1123. function GetDetailRecords(AIndex: Integer): TsdDataRecord; virtual; abstract;
  1124. function GetDetailRecordCount: Integer; virtual; abstract;
  1125. function CheckMasterIndex: Boolean; virtual;
  1126. function CheckDetailIndex: Boolean; virtual;
  1127. property MasterField: string read FMasterField write SetMasterField;
  1128. property DetailField: string read FDetailField write SetDetailField;
  1129. public
  1130. constructor Create; virtual;
  1131. destructor Destroy; override;
  1132. procedure CreateMap;
  1133. function ItemByRecord(ARecord: TsdDataRecord): TsdMasterItem;
  1134. function ItemByDetailRecord(ARecord: TsdDataRecord): TsdMasterItem;
  1135. function RecordByDetailRecord(ARecord: TsdDataRecord): TsdDataRecord;
  1136. property Count: Integer read GetCount;
  1137. property Items[Index: Integer]: TsdMasterItem read GetItems; default;
  1138. property OnCompareValues: TsdCompareValuesEvent read FOnCompareValues write SetOnCompareValues;
  1139. end;
  1140. TsdDataSetMasterDetailMap = class(TsdMasterDetailMap)
  1141. private
  1142. FMasterDataSet: TsdDataSet;
  1143. FDetailDataSet: TsdDataSet;
  1144. procedure SetDetailDataSet(const Value: TsdDataSet);
  1145. procedure SetMasterDataSet(const Value: TsdDataSet);
  1146. protected
  1147. function GetMasterRecordCount: Integer; override;
  1148. function GetMasterRecords(AIndex: Integer): TsdDataRecord; override;
  1149. function GetDetailRecordCount: Integer; override;
  1150. function GetDetailRecords(AIndex: Integer): TsdDataRecord; override;
  1151. function CheckMasterIndex: Boolean; override;
  1152. function CheckDetailIndex: Boolean; override;
  1153. public
  1154. published
  1155. property MasterField;
  1156. property DetailField;
  1157. property MasterDataSet: TsdDataSet read FMasterDataSet write SetMasterDataSet;
  1158. property DetailDataSet: TsdDataSet read FDetailDataSet write SetDetailDataSet;
  1159. property OnCompareValues;
  1160. end;
  1161. TsdDataViewMasterDetailMap = class(TsdMasterDetailMap)
  1162. private
  1163. FMasterDataView: TsdDataView;
  1164. FDetailDataView: TsdDataView;
  1165. procedure SetDetailDataView(const Value: TsdDataView);
  1166. procedure SetMasterDataView(const Value: TsdDataView);
  1167. protected
  1168. function GetMasterRecordCount: Integer; override;
  1169. function GetMasterRecords(AIndex: Integer): TsdDataRecord; override;
  1170. function GetDetailRecordCount: Integer; override;
  1171. function GetDetailRecords(AIndex: Integer): TsdDataRecord; override;
  1172. function CheckMasterIndex: Boolean; override;
  1173. function CheckDetailIndex: Boolean; override;
  1174. public
  1175. published
  1176. property MasterField;
  1177. property DetailField;
  1178. property MasterDataView: TsdDataView read FMasterDataView write SetMasterDataView;
  1179. property DetailDataView: TsdDataView read FDetailDataView write SetDetailDataView;
  1180. property OnCompareValues;
  1181. end;
  1182. TsdListMasterDetailMap = class(TsdMasterDetailMap)
  1183. private
  1184. FMasterList: TList;
  1185. FDetailList: TList;
  1186. procedure SetDetailList(const Value: TList);
  1187. procedure SetMasterList(const Value: TList);
  1188. protected
  1189. function GetMasterRecordCount: Integer; override;
  1190. function GetMasterRecords(AIndex: Integer): TsdDataRecord; override;
  1191. function GetDetailRecordCount: Integer; override;
  1192. function GetDetailRecords(AIndex: Integer): TsdDataRecord; override;
  1193. function CheckMasterIndex: Boolean; override;
  1194. function CheckDetailIndex: Boolean; override;
  1195. public
  1196. published
  1197. property MasterField;
  1198. property DetailField;
  1199. property MasterList: TList read FMasterList write SetMasterList;
  1200. property DetailList: TList read FDetailList write SetDetailList;
  1201. property OnCompareValues;
  1202. end;
  1203. //function FieldTypeToVar(AFieldType: TFieldType): Integer;
  1204. TsdOperationItem = class;
  1205. TsdOperationBeforeEvent = procedure (AItem: TsdOperationItem; var CanDo: Boolean) of object;
  1206. TsdOperationAfterEvent = procedure (AItem: TsdOperationItem) of object;
  1207. TsdOperationDataSetBeforeEvent = procedure (ADataSet: TsdDataSet; ARecord: TsdDataRecord; AOperation: TsdOperation; ADataRec: TsdDataRecord; AFields: TStrings; AData: Pointer; var CanDo: Boolean) of object;
  1208. TsdOperationDataSetAfterEvent = procedure (ADataSet: TsdDataSet; ARecord: TsdDataRecord; AOperation: TsdOperation; ADataRec: TsdDataRecord; AFields: TStrings; AData: Pointer) of object;
  1209. TsdOperationManager = class(TObject)
  1210. private
  1211. FItems: TList;
  1212. FDataSets: TList;
  1213. FLimitedCount: Integer;
  1214. FSnapShooting: Boolean;
  1215. FNeedConfirmSnapShoot: Boolean;
  1216. FDataSetBeforeUndo: TsdOperationDataSetBeforeEvent;
  1217. FDataSetAfterUndo: TsdOperationDataSetAfterEvent;
  1218. FSavePoint: Integer;
  1219. FDataSetBeforeRedo: TsdOperationDataSetBeforeEvent;
  1220. FDataSetAfterRedo: TsdOperationDataSetAfterEvent;
  1221. FActive: Boolean;
  1222. FAfterRedo: TsdOperationAfterEvent;
  1223. FAfterUndo: TsdOperationAfterEvent;
  1224. FBeforeUndo: TsdOperationBeforeEvent;
  1225. FBeforeRedo: TsdOperationBeforeEvent;
  1226. procedure DoBeforeUndo(AItem: TsdOperationItem; var CanDo: Boolean);
  1227. procedure DoAfterUndo(AItem: TsdOperationItem);
  1228. procedure DoBeforeRedo(AItem: TsdOperationItem; var CanDo: Boolean);
  1229. procedure DoAfterRedo(AItem: TsdOperationItem);
  1230. procedure DoDataSetBeforeUndo(ADataSet: TsdDataSet; ARecord: TsdDataRecord; AOperation: TsdOperation; ADataRec: TsdDataRecord; AFields: TStrings; AData: Pointer; var CanDo: Boolean);
  1231. procedure DoDataSetAfterUndo(ADataSet: TsdDataSet; ARecord: TsdDataRecord; AOperation: TsdOperation; ADataRec: TsdDataRecord; AFields: TStrings; AData: Pointer);
  1232. procedure DoDataSetBeforeRedo(ADataSet: TsdDataSet; ARecord: TsdDataRecord; AOperation: TsdOperation; ADataRec: TsdDataRecord; AFields: TStrings; AData: Pointer; var CanDo: Boolean);
  1233. procedure DoDataSetAfterRedo(ADataSet: TsdDataSet; ARecord: TsdDataRecord; AOperation: TsdOperation; ADataRec: TsdDataRecord; AFields: TStrings; AData: Pointer);
  1234. function GetCount: Integer;
  1235. function GetItems(I: Integer): TsdOperationItem;
  1236. function GetDataSet(I: Integer): TsdDataSet;
  1237. function GetDataSetCount: Integer;
  1238. procedure SetLimitedCount(const Value: Integer);
  1239. function NewID: Integer;
  1240. procedure SetDataSetAfterUndo(const Value: TsdOperationDataSetAfterEvent);
  1241. procedure SetDataSetBeforeUndo(const Value: TsdOperationDataSetBeforeEvent);
  1242. function FindPrev(AID: Integer): TsdOperationItem;
  1243. function FindNext(AID: Integer): TsdOperationItem;
  1244. procedure SetDataSetAfterRedo(const Value: TsdOperationDataSetAfterEvent);
  1245. procedure SetDataSetBeforeRedo(const Value: TsdOperationDataSetBeforeEvent);
  1246. procedure ClearNewerItems;
  1247. procedure SetActive(const Value: Boolean);
  1248. procedure SetAfterRedo(const Value: TsdOperationAfterEvent);
  1249. procedure SetAfterUndo(const Value: TsdOperationAfterEvent);
  1250. procedure SetBeforeRedo(const Value: TsdOperationBeforeEvent);
  1251. procedure SetBeforeUndo(const Value: TsdOperationBeforeEvent);
  1252. function GetModified: Boolean;
  1253. public
  1254. constructor Create; virtual;
  1255. destructor Destroy; override;
  1256. procedure RegisterDataSet(ADataSet: TsdDataSet);
  1257. procedure UnRegisterDataSet(ADataSet: TsdDataSet);
  1258. // 生成快照, 返回ID
  1259. // (BeginSnapShoot: 强制开始快照,调用EndSnapShoot之前的SnapShoot都被略过)
  1260. // (NeedConfirm: 需确认。某些情况要在后面才确认当前是否进行了操作,所以在后面通过Confirm和Cancel确认/取消SnapShoot)
  1261. function SnapShoot(AName: string; BeginSnapShoot: Boolean = False; NeedConfirm: Boolean = False): Integer;
  1262. // 某些情况需要单独BeginSnapShoot
  1263. procedure BeginSnapShoot;
  1264. procedure EndSnapShoot;
  1265. procedure Confirm;
  1266. procedure Cancel;
  1267. // 挂起,暂停所有操作记录
  1268. procedure Suspend;
  1269. // 继续记录
  1270. procedure Resume;
  1271. // 重命名当前操作(因为很多时候生产快照时不知道当前操作如何命名,所以需要提供一个方法在后面命名当前操作)
  1272. // 注意如果BeginSnapShoot=True则要在EndSnapShoot后才能Rename
  1273. procedure RenameCurrentItem(AName: string);
  1274. // 撤销到指定ID的快照
  1275. procedure Undo(AID: Integer = -1);
  1276. // 重做到指定ID的快照
  1277. procedure Redo(AID: Integer = -1);
  1278. // 重置到当前SavePoint(因为保存的时候还会进行很多计算,所以undo之后再保存,就跟后面的redo对不上了。所以必须在保存前清理掉SavePoint后面的操作记录)
  1279. procedure Reset;
  1280. // 若SavePoint不是最新则Reset,用于添加新操作记录时检查用
  1281. procedure ResetWhenNecessary;
  1282. function FindItem(AID: Integer): TsdOperationItem;
  1283. function IndexByID(AID: Integer): Integer;
  1284. procedure OperationList(AList: TStrings; Undo: Boolean);
  1285. function UndoCount: Integer;
  1286. function RedoCount: Integer;
  1287. function CurrentUndoName: string;
  1288. function CurrentRedoName: string;
  1289. // 调试用,输出当前数据集
  1290. procedure SaveHistory(AFileName: string);
  1291. property Active: Boolean read FActive write SetActive;
  1292. property Count: Integer read GetCount;
  1293. property Items[I: Integer]: TsdOperationItem read GetItems;
  1294. property DataSetCount: Integer read GetDataSetCount;
  1295. property DataSet[I: Integer]: TsdDataSet read GetDataSet;
  1296. property LimitedCount: Integer read FLimitedCount write SetLimitedCount;
  1297. // SavePoint指当前操作ID,最新操作是最大ID+1,是一个虚拟ID
  1298. property SavePoint: Integer read FSavePoint;
  1299. property Modified: Boolean read GetModified;
  1300. property BeforeUndo: TsdOperationBeforeEvent read FBeforeUndo write SetBeforeUndo;
  1301. property AfterUndo: TsdOperationAfterEvent read FAfterUndo write SetAfterUndo;
  1302. property BeforeRedo: TsdOperationBeforeEvent read FBeforeRedo write SetBeforeRedo;
  1303. property AfterRedo: TsdOperationAfterEvent read FAfterRedo write SetAfterRedo;
  1304. property DataSetBeforeUndo: TsdOperationDataSetBeforeEvent read FDataSetBeforeUndo write SetDataSetBeforeUndo;
  1305. property DataSetAfterUndo: TsdOperationDataSetAfterEvent read FDataSetAfterUndo write SetDataSetAfterUndo;
  1306. property DataSetBeforeRedo: TsdOperationDataSetBeforeEvent read FDataSetBeforeRedo write SetDataSetBeforeRedo;
  1307. property DataSetAfterRedo: TsdOperationDataSetAfterEvent read FDataSetAfterRedo write SetDataSetAfterRedo;
  1308. end;
  1309. PsdHistoryInfo = ^TsdHistoryInfo;
  1310. TsdHistoryInfo = record
  1311. DataSet: TsdDataSet;
  1312. StartPoint: Integer;
  1313. EndPoint: Integer;
  1314. end;
  1315. TsdOperationItem = class(TObject)
  1316. private
  1317. FOwner: TsdOperationManager;
  1318. FInfos: TList;
  1319. FID: Integer;
  1320. FName: string;
  1321. procedure EndSnap;
  1322. public
  1323. constructor Create(AOwner: TsdOperationManager; AID: Integer; AName: string); virtual;
  1324. destructor Destroy; override;
  1325. procedure SnapShoot;
  1326. procedure Undo;
  1327. procedure Redo;
  1328. procedure Clear;
  1329. // 清除新的记录,包括自己
  1330. procedure ClearNewerHistoryRecord;
  1331. // 清除旧的记录,不包括自己
  1332. procedure ClearOlderHistoryRecord;
  1333. property ID: Integer read FID;
  1334. property Name: string read FName;
  1335. end;
  1336. EsdHistory = class(Exception);
  1337. TsdHistoryValue = class;
  1338. TsdHistoryList = class(TObject)
  1339. private
  1340. FDataSet: TsdDataSet;
  1341. FSavePoint: Integer;
  1342. FUpdateRecordLock: Integer;
  1343. FAdding: Boolean;
  1344. FStopping: Integer;
  1345. function LastID: Integer;
  1346. procedure SetSavePoint(const Value: Integer);
  1347. function GetSavePoint: Integer;
  1348. function IndexByID(AID: Integer): Integer;
  1349. // 新增/删除操作中缓存的DataRecord要视条件清理,所以不能在TsdHistoryRecord的Free中释放DataRecord,而在释放本对象时单独写一个全部清理方法
  1350. procedure ClearAllDataRecords;
  1351. function FindLastValue(AValue: TsdValue): TsdHistoryValue;
  1352. function FindLastRecord(ARecord: TsdDataRecord): TsdHistoryRecord;
  1353. function GetStopping: Boolean;
  1354. protected
  1355. FRecList: TList;
  1356. FLastHistoryRecords: TList;
  1357. function IsUpdatingRecord: Boolean;
  1358. // 清除新的记录,包括自己
  1359. procedure ClearNewerRecord(AID: Integer);
  1360. // 清除旧的记录,不包括自己
  1361. procedure ClearOlderRecord(AID: Integer);
  1362. // Undo前将最新值Cache到LastRecord
  1363. procedure CacheLastRecord(AValue: TsdValue);
  1364. // Redo时获取新值
  1365. procedure CopyLastValue(AID: Integer; AValue: TsdValue);
  1366. // 最新一次undo前要清空全部LastRecord
  1367. procedure ClearLastRecords;
  1368. public
  1369. constructor Create(ADataSet: TsdDataSet); virtual;
  1370. destructor Destroy; override;
  1371. // 原DataSet增加记录的操作,在增加记录时写入的数据无需单独记录操作
  1372. procedure BeginAdd;
  1373. procedure EndAdd;
  1374. // 注意批量操作只能对一条记录进行,存在多条记录的修改会出错
  1375. procedure BeginRecordUpdate(ARecord: TsdDataRecord);
  1376. procedure EndRecordUpdate;
  1377. procedure Add(ARecord: TsdDataRecord);
  1378. procedure Delete(ARecord: TsdDataRecord);
  1379. procedure Modify(AValue: TsdValue);
  1380. // 供外部对象(IsdHistoryObject)记录额外信息
  1381. procedure WriteHistoryData(AOperation: TsdOperation; AObject: IsdHistoryObject; AData: Pointer);
  1382. procedure Undo(AID: Integer);
  1383. procedure Redo(AID: Integer);
  1384. // 挂起,暂停所有操作记录
  1385. procedure Suspend;
  1386. // 继续记录
  1387. procedure Resume;
  1388. function FindByRecord(ARecord: TsdDataRecord): TsdHistoryRecord;
  1389. procedure Clear;
  1390. property DataSet: TsdDataSet read FDataSet;
  1391. property SavePoint: Integer read GetSavePoint write SetSavePoint;
  1392. // 1,OperationManager.Active=False;2,在Undo/Redo操作中写入DataSet的操作无需记录,以此属性标记
  1393. property Stopping: Boolean read GetStopping;
  1394. end;
  1395. TsdHistoryRecord = class(TObject)
  1396. private
  1397. FOwner: TsdHistoryList;
  1398. FValueList: TList;
  1399. FOperation: TsdOperation;
  1400. FID: Integer;
  1401. FModified: Boolean;
  1402. FNeedFreeCheck: Boolean;
  1403. function GetValues(I: Integer): TsdHistoryValue;
  1404. function GetCount: Integer;
  1405. protected
  1406. FRec: TsdDataRecord;
  1407. // 外部对象
  1408. FHistoryObject: IsdHistoryObject;
  1409. // 外部对象的Data
  1410. FData: Pointer;
  1411. function FindValue(AValue: TsdValue): TsdHistoryValue;
  1412. procedure RemoveValue(AValue: TsdValue);
  1413. public
  1414. constructor Create(AOwner: TsdHistoryList); virtual;
  1415. destructor Destroy; override;
  1416. procedure Add(ARecord: TsdDataRecord);
  1417. procedure Delete(ARecord: TsdDataRecord);
  1418. procedure Modify(AValue: TsdValue);
  1419. procedure Undo(ADataRecord: TsdDataRecord);
  1420. procedure Redo(ADataRecord: TsdDataRecord);
  1421. property ID: Integer read FID;
  1422. property Values[I: Integer]: TsdHistoryValue read GetValues;
  1423. property Count: Integer read GetCount;
  1424. property Operation: TsdOperation read FOperation write FOperation;
  1425. // 记录操作前是否修改过
  1426. property Modified: Boolean read FModified;
  1427. // 用于记录额外的信息(例如树节点)
  1428. property Data: Pointer read FData;
  1429. end;
  1430. TsdHistoryValue = class(TObject)
  1431. private
  1432. FFieldName: string;
  1433. FOriginalCache: Pointer;
  1434. FOriginalCacheLength: Integer;
  1435. FData: Pointer;
  1436. FLength: Integer;
  1437. FIsNull: Boolean;
  1438. public
  1439. constructor Create; virtual;
  1440. destructor Destroy; override;
  1441. procedure CopyFrom(AValue: TsdValue);
  1442. procedure CopyTo(AValue: TsdValue);
  1443. property FieldName: string read FFieldName;
  1444. end;
  1445. procedure OutputDataSetFields(ADataSet: TsdDataSet; AList: TStringList);
  1446. procedure OutputDataViewFields(ADataView: TsdDataView; AList: TStringList);
  1447. var
  1448. ReadValueCount: Integer = 0;
  1449. const
  1450. BooleanStrArray: array [Boolean] of string =(STextFalse, STextTrue);
  1451. SavePointMin = -999;
  1452. implementation
  1453. uses
  1454. TypInfo, XMLDoc, XMLIntf, Math, DateUtils, Forms;
  1455. procedure OutputDataSetFields(ADataSet: TsdDataSet; AList: TStringList);
  1456. var
  1457. I: Integer;
  1458. Field: TsdField;
  1459. begin
  1460. AList.Clear;
  1461. AList.Add(Format('DataSet: %s', [ADataSet.Name]));
  1462. for I := 0 to ADataSet.FieldCount - 1 do
  1463. begin
  1464. Field := ADataSet.Fields.Fields[I];
  1465. AList.Add(Format('Fields: %s', [Field.FieldName]));
  1466. end;
  1467. end;
  1468. procedure OutputDataViewFields(ADataView: TsdDataView; AList: TStringList);
  1469. var
  1470. I: Integer;
  1471. Col: TsdViewColumn;
  1472. begin
  1473. AList.Clear;
  1474. AList.Add(Format('DataView: %s', [ADataView.Name]));
  1475. for I := 0 to ADataView.Columns.Count - 1 do
  1476. begin
  1477. Col := ADataView.Column[I];
  1478. AList.Add(Format('Fields: %s', [Col.FieldName]));
  1479. end;
  1480. end;
  1481. var
  1482. Logs: TStringList;
  1483. LogOn: Boolean = False;
  1484. LogFile: string;
  1485. procedure BeginLog(AFileName: string);
  1486. var
  1487. Dir: string;
  1488. begin
  1489. Logs := TStringList.Create;
  1490. LogFile := AFileName;
  1491. Dir := ExtractFileDir(AFileName);
  1492. LogOn := DirectoryExists(Dir);
  1493. end;
  1494. procedure EndLog;
  1495. begin
  1496. if LogOn then
  1497. Logs.SaveToFile(LogFile);
  1498. FreeAndNil(Logs);
  1499. LogOn := False;
  1500. end;
  1501. procedure AddLog(ALog: string);
  1502. begin
  1503. if LogOn and Assigned(Logs) then
  1504. Logs.Add(ALog);
  1505. end;
  1506. {function FieldTypeToVar(AFieldType: TFieldType): Integer;
  1507. begin
  1508. case AFieldType of
  1509. ftBoolean:
  1510. Result := vtBoolean;
  1511. ftString:
  1512. Result := vtString;
  1513. ftWideString:
  1514. Result := vtWideString;
  1515. ftMemo:
  1516. Result := vtWideString;
  1517. ftSmallint, ftInteger, ftWord:
  1518. Result := vtInteger;
  1519. ftFloat, ftDateTime:
  1520. Result := vtExtended;
  1521. ftCurrency, ftBCD:
  1522. Result := vtCurrency;
  1523. else
  1524. Result := vtVariant;
  1525. end;
  1526. end; }
  1527. function sdVarToInteger(Value: Variant): Integer;
  1528. begin
  1529. if VarIsNull(Value) then
  1530. Result := 0
  1531. else
  1532. Result := Value;
  1533. end;
  1534. function sdVarToFloat(Value: Variant): Double;
  1535. begin
  1536. if VarIsNull(Value) then
  1537. Result := 0
  1538. else
  1539. Result := Value;
  1540. end;
  1541. function sdVarToCurrency(Value: Variant): Currency;
  1542. begin
  1543. if VarIsNull(Value) then
  1544. Result := 0
  1545. else
  1546. Result := Value;
  1547. end;
  1548. function sdVarToBoolean(Value: Variant): Boolean;
  1549. begin
  1550. if VarIsNull(Value) then
  1551. Result := False
  1552. else
  1553. Result := Value;
  1554. end;
  1555. {function StrToTypedVar(Value: string; AFieldType: TFieldType): Variant;
  1556. begin
  1557. if Value = '' then
  1558. Result := Null
  1559. else
  1560. begin
  1561. case AFieldType of
  1562. ftBoolean:
  1563. Result := StrToBool(Value);
  1564. ftString:
  1565. Result := Value;
  1566. ftWideString:
  1567. Result := Value;
  1568. ftMemo:
  1569. Result := Value;
  1570. ftSmallint, ftInteger, ftWord:
  1571. Result := StrToInt(Value);
  1572. ftFloat:
  1573. Result := StrToFloat(Value);
  1574. ftDateTime:
  1575. Result := StrToDateTime(Value);
  1576. ftCurrency, ftBCD:
  1577. Result := StrToCurr(Value);
  1578. else
  1579. Result := Value;
  1580. end;
  1581. end;
  1582. end;
  1583. }
  1584. { TsdValue }
  1585. function TsdValue.ActualLength: Integer;
  1586. begin
  1587. Result := InnerCacheLength(FData);
  1588. end;
  1589. procedure TsdValue.Clear;
  1590. begin
  1591. SetAsVariant(Null);
  1592. end;
  1593. constructor TsdValue.Create(AOwner: TsdDataRecord);
  1594. begin
  1595. FOwner := AOwner;
  1596. FData := nil;
  1597. FIsNull := True;
  1598. FOriginalValue := nil;
  1599. FTag := 0;
  1600. FForceWriteData := False;
  1601. FOriginalCached := False;
  1602. end;
  1603. destructor TsdValue.Destroy;
  1604. begin
  1605. if Assigned(FData) then
  1606. FreeMem(FData);
  1607. if Assigned(FOriginalValue) then
  1608. FreeMem(FOriginalValue);
  1609. inherited;
  1610. end;
  1611. function TsdValue.GetAsBoolean: Boolean;
  1612. var
  1613. P: Pointer;
  1614. begin
  1615. Result := False;
  1616. case DataType of
  1617. ftBoolean:
  1618. begin
  1619. ReadData(P);
  1620. Result := PBoolean(P)^;
  1621. end;
  1622. ftString, ftWideString, ftMemo,
  1623. ftSmallint, ftInteger, ftWord,
  1624. ftFloat, ftDateTime,
  1625. ftCurrency, ftBCD, ftFMTBCD:
  1626. TypeErrorOnWriting(Result);
  1627. end;
  1628. end;
  1629. function TsdValue.GetAsCurrency: Currency;
  1630. var
  1631. P: Pointer;
  1632. begin
  1633. Result := 0;
  1634. case DataType of
  1635. ftCurrency, ftBCD:
  1636. begin
  1637. ReadData(P);
  1638. Result := PCurrency(P)^;
  1639. end;
  1640. ftFMTBCD:
  1641. begin
  1642. ReadData(P);
  1643. BCDToCurr(PBCD(P)^, Result);
  1644. end;
  1645. ftFloat:
  1646. begin
  1647. ReadData(P);
  1648. Result := PDouble(P)^;
  1649. end;
  1650. ftBoolean,
  1651. ftString, ftWideString, ftMemo,
  1652. ftSmallint, ftInteger, ftWord,
  1653. ftDateTime:
  1654. TypeErrorOnWriting(Result);
  1655. end;
  1656. end;
  1657. function TsdValue.GetAsDateTime: TDateTime;
  1658. var
  1659. P: Pointer;
  1660. begin
  1661. Result := 0;
  1662. case DataType of
  1663. ftDateTime:
  1664. begin
  1665. ReadData(P);
  1666. Result := PDouble(P)^;
  1667. end;
  1668. ftBoolean,
  1669. ftString, ftWideString, ftMemo,
  1670. ftSmallint, ftInteger, ftWord,
  1671. ftFloat, ftCurrency, ftBCD, ftFMTBCD:
  1672. TypeErrorOnWriting(Result);
  1673. end;
  1674. end;
  1675. function TsdValue.GetAsFloat: Double;
  1676. var
  1677. P: Pointer;
  1678. strValue: string;
  1679. begin
  1680. Result := 0;
  1681. case DataType of
  1682. ftFloat:
  1683. begin
  1684. ReadData(P);
  1685. Result := PDouble(P)^;
  1686. end;
  1687. ftCurrency, ftBCD:
  1688. begin
  1689. ReadData(P);
  1690. Result := PCurrency(P)^;
  1691. end;
  1692. ftFMTBCD:
  1693. begin
  1694. ReadData(P);
  1695. Result := BcdToDouble(PBCD(P)^);
  1696. end;
  1697. ftSmallint:
  1698. begin
  1699. ReadData(P);
  1700. Result := PSmallInt(P)^;
  1701. end;
  1702. ftInteger:
  1703. begin
  1704. ReadData(P);
  1705. Result := PInteger(P)^;
  1706. end;
  1707. ftWord:
  1708. begin
  1709. ReadData(P);
  1710. Result := PWord(P)^;
  1711. end;
  1712. ftBoolean,
  1713. ftString, ftWideString, ftMemo:
  1714. begin
  1715. strValue := GetAsString;
  1716. if strValue <> '' then
  1717. Result := StrToFloat(GetAsString)
  1718. else
  1719. Result := 0;
  1720. end;
  1721. ftDateTime:
  1722. TypeErrorOnWriting(Result);
  1723. end;
  1724. end;
  1725. function TsdValue.GetAsExtended: Extended;
  1726. var
  1727. P: Pointer;
  1728. strValue: string;
  1729. begin
  1730. Result := 0;
  1731. case DataType of
  1732. ftFloat:
  1733. begin
  1734. ReadData(P);
  1735. Result := PDouble(P)^;
  1736. end;
  1737. ftCurrency, ftBCD:
  1738. begin
  1739. ReadData(P);
  1740. Result := PCurrency(P)^;
  1741. end;
  1742. ftFMTBCD:
  1743. begin
  1744. ReadData(P);
  1745. Result := BcdToDouble(PBCD(P)^);
  1746. end;
  1747. ftSmallint:
  1748. begin
  1749. ReadData(P);
  1750. Result := PSmallInt(P)^;
  1751. end;
  1752. ftInteger:
  1753. begin
  1754. ReadData(P);
  1755. Result := PInteger(P)^;
  1756. end;
  1757. ftWord:
  1758. begin
  1759. ReadData(P);
  1760. Result := PWord(P)^;
  1761. end;
  1762. ftBoolean,
  1763. ftString, ftWideString, ftMemo:
  1764. begin
  1765. strValue := GetAsString;
  1766. if strValue <> '' then
  1767. Result := StrToFloat(GetAsString)
  1768. else
  1769. Result := 0;
  1770. end;
  1771. ftDateTime:
  1772. TypeErrorOnWriting(Result);
  1773. end;
  1774. end;
  1775. function TsdValue.GetAsInteger: Longint;
  1776. var
  1777. P: Pointer;
  1778. begin
  1779. Result := 0;
  1780. case DataType of
  1781. ftSmallint:
  1782. begin
  1783. ReadData(P);
  1784. Result := PSmallInt(P)^;
  1785. end;
  1786. ftWord:
  1787. begin
  1788. ReadData(P);
  1789. Result := PWord(P)^;
  1790. end;
  1791. ftInteger:
  1792. begin
  1793. ReadData(P);
  1794. Result := PInteger(P)^;
  1795. end;
  1796. ftFloat, ftCurrency, ftBCD:
  1797. begin
  1798. ReadData(P);
  1799. Result := Longint(Round(PDouble(P)^));
  1800. end;
  1801. ftFMTBCD:
  1802. begin
  1803. ReadData(P);
  1804. Result := BcdToInteger(PBCD(P)^);
  1805. end;
  1806. ftBoolean,
  1807. ftString, ftWideString, ftMemo,
  1808. ftDateTime:
  1809. TypeErrorOnWriting(Result);
  1810. end;
  1811. end;
  1812. function TsdValue.GetAsString: string;
  1813. var
  1814. P: Pointer;
  1815. iLength: Integer;
  1816. wsValue: WideString;
  1817. begin
  1818. Result := '';
  1819. if FIsNull then Exit;
  1820. // if not FField.IsVarField then
  1821. // SetLength(Result, DataSize);
  1822. case DataType of
  1823. ftBoolean:
  1824. begin
  1825. ReadData(P);
  1826. Result := BooleanStrArray[PBoolean(P)^];
  1827. end;
  1828. ftString, ftMemo:
  1829. begin
  1830. iLength := ActualLength;
  1831. SetLength(Result, iLength);
  1832. P := @Result[1];
  1833. if iLength > 0 then
  1834. begin
  1835. ReadData(P, iLength);
  1836. end
  1837. else
  1838. Result := '';
  1839. end;
  1840. ftWideString:
  1841. begin
  1842. iLength := ActualLength;
  1843. SetLength(wsValue, iLength);
  1844. P := @wsValue[1];
  1845. if iLength > 0 then
  1846. begin
  1847. ReadData(P, iLength);
  1848. Result := wsValue;
  1849. end
  1850. else
  1851. Result := '';
  1852. end;
  1853. ftSmallint:
  1854. begin
  1855. ReadData(P);
  1856. Result := IntToStr(PSmallInt(P)^);
  1857. end;
  1858. ftWord:
  1859. begin
  1860. ReadData(P);
  1861. Result := IntToStr(PWord(P)^);
  1862. end;
  1863. ftInteger:
  1864. begin
  1865. ReadData(P);
  1866. Result := IntToStr(PInteger(P)^);
  1867. end;
  1868. ftFloat:
  1869. begin
  1870. ReadData(P);
  1871. Result := FloatToStr(PDouble(P)^);
  1872. end;
  1873. ftDateTime:
  1874. begin
  1875. ReadData(P);
  1876. Result := DateTimeToStr(PDouble(P)^);
  1877. end;
  1878. ftCurrency, ftBCD:
  1879. begin
  1880. ReadData(P);
  1881. Result := FloatToStr(PCurrency(P)^);
  1882. end;
  1883. ftFMTBCD:
  1884. begin
  1885. ReadData(P);
  1886. Result := BcdToStr(PBCD(P)^);
  1887. end;
  1888. end;
  1889. end;
  1890. function TsdValue.GetAsVariant: Variant;
  1891. var
  1892. fBCD: TBCD;
  1893. begin
  1894. Result := Null;
  1895. if FIsNull then Exit;
  1896. case DataType of
  1897. ftBoolean: Result := GetAsBoolean;
  1898. ftString, ftWideString, ftMemo: Result := GetAsString;
  1899. ftSmallint, ftWord, ftInteger: Result := GetAsInteger;
  1900. ftFloat: Result := GetAsFloat;
  1901. ftDateTime: Result := GetAsDateTime;
  1902. ftCurrency, ftBCD: Result := GetAsCurrency;
  1903. ftFMTBCD:
  1904. begin
  1905. fBCD := GetAsBCD;
  1906. Result := VarFMTBcdCreate(fBCD);
  1907. end;
  1908. end;
  1909. end;
  1910. function TsdValue.GetDataSize: Integer;
  1911. begin
  1912. Result := FField.DataSize;
  1913. end;
  1914. function TsdValue.GetDataType: TFieldType;
  1915. begin
  1916. Result := FField.DataType;
  1917. end;
  1918. function TsdValue.GetDisplayText: string;
  1919. begin
  1920. {to do: 要考虑格式化的问题,以后再完善}
  1921. Result := GetAsString;
  1922. end;
  1923. function TsdValue.GetEditText: string;
  1924. begin
  1925. {to do: 要考虑格式化的问题,以后再完善}
  1926. Result := GetAsString;
  1927. end;
  1928. function TsdValue.GetFieldName: string;
  1929. begin
  1930. Result := FField.FieldName;
  1931. end;
  1932. function TsdValue.GetFieldNo: Integer;
  1933. begin
  1934. Result := FField.FieldNo;
  1935. end;
  1936. function TsdValue.GetIsNull: Boolean;
  1937. begin
  1938. Result := FIsNull;
  1939. end;
  1940. procedure TsdValue.ReadData(var Data: Pointer; Length: Integer);
  1941. var
  1942. iLength: Integer;
  1943. begin
  1944. iLength := Length;
  1945. if FData = nil then ZeroMemory(Data, iLength);
  1946. if iLength = 0 then iLength := DataSize;
  1947. if not FField.IsBlobField then
  1948. if iLength > DataSize then iLength := DataSize
  1949. else if FField.DataType = ftWideString then
  1950. iLength := iLength * 2;
  1951. if Field.IsVarField then
  1952. CopyMemory(Data, FData, iLength)
  1953. else
  1954. Data := FData;
  1955. //Inc(ReadValueCount);
  1956. end;
  1957. procedure TsdValue.SetAsBoolean(const Value: Boolean);
  1958. begin
  1959. case DataType of
  1960. ftBoolean:
  1961. WriteData(@Value, Value);
  1962. ftString, ftWideString, ftMemo,
  1963. ftSmallint, ftInteger, ftWord,
  1964. ftFloat, ftDateTime,
  1965. ftCurrency, ftBCD, ftFMTBCD:
  1966. TypeErrorOnWriting(Value);
  1967. end;
  1968. end;
  1969. procedure TsdValue.SetAsCurrency(const Value: Currency);
  1970. var
  1971. fValue: Double;
  1972. fBCD: TBCD;
  1973. begin
  1974. case DataType of
  1975. ftBoolean,
  1976. ftString, ftWideString, ftMemo,
  1977. ftSmallint, ftInteger, ftWord,
  1978. ftDateTime:
  1979. TypeErrorOnWriting(Value);
  1980. ftFloat:
  1981. begin
  1982. fValue := Value;
  1983. WriteData(@fValue, fValue);
  1984. end;
  1985. ftCurrency, ftBCD:
  1986. WriteData(@Value, Value);
  1987. ftFMTBCD:
  1988. begin
  1989. CurrToBCD(Value, fBCD);
  1990. WriteData(@fBCD, Value);
  1991. end;
  1992. end;
  1993. end;
  1994. procedure TsdValue.SetAsDateTime(const Value: TDateTime);
  1995. begin
  1996. case DataType of
  1997. ftDateTime:
  1998. WriteData(@Value, Value);
  1999. ftBoolean,
  2000. ftString, ftWideString, ftMemo,
  2001. ftSmallint, ftInteger, ftWord,
  2002. ftFloat, ftCurrency, ftBCD, ftFMTBCD:
  2003. TypeErrorOnWriting(Value);
  2004. end;
  2005. end;
  2006. procedure TsdValue.SetAsFloat(const Value: Double);
  2007. var
  2008. iValue: SmallInt;
  2009. iWord: Word;
  2010. iInt: Longint;
  2011. fValue: Currency;
  2012. fBCD: TBCD;
  2013. begin
  2014. case DataType of
  2015. ftFloat:
  2016. WriteData(@Value, Value);
  2017. ftCurrency, ftBCD:
  2018. begin
  2019. fValue := Value;
  2020. WriteData(@fValue, fValue);
  2021. end;
  2022. ftFMTBCD:
  2023. begin
  2024. fBCD := DoubleToBcd(Value);
  2025. WriteData(@fBCD, Value);
  2026. end;
  2027. ftSmallint:
  2028. begin
  2029. iValue := SmallInt(Round(Value));
  2030. WriteData(@iValue, iValue);
  2031. end;
  2032. ftWord:
  2033. begin
  2034. iWord := Word(Round(Value));
  2035. WriteData(@iWord, iWord);
  2036. end;
  2037. ftInteger:
  2038. begin
  2039. iInt := Longint(Round(Value));
  2040. WriteData(@iInt, iInt);
  2041. end;
  2042. ftBoolean,
  2043. ftString, ftWideString, ftMemo:
  2044. SetAsString(FloatToStr(Value));
  2045. ftDateTime:
  2046. TypeErrorOnWriting(Value);
  2047. end;
  2048. end;
  2049. procedure TsdValue.SetAsExtended(const Value: Extended);
  2050. var
  2051. iValue: SmallInt;
  2052. iWord: Word;
  2053. iInt: Longint;
  2054. fValue: Double;
  2055. cValue: Currency;
  2056. fBCD: TBCD;
  2057. begin
  2058. case DataType of
  2059. ftFloat:
  2060. begin
  2061. begin
  2062. fValue := Value;
  2063. WriteData(@fValue, fValue);
  2064. end;
  2065. end;
  2066. ftCurrency, ftBCD:
  2067. begin
  2068. cValue := Value;
  2069. WriteData(@cValue, cValue);
  2070. end;
  2071. ftFMTBCD:
  2072. begin
  2073. fBCD := DoubleToBcd(Value);
  2074. WriteData(@fBCD, Value);
  2075. end;
  2076. ftSmallint:
  2077. begin
  2078. iValue := SmallInt(Round(Value));
  2079. WriteData(@iValue, iValue);
  2080. end;
  2081. ftWord:
  2082. begin
  2083. iWord := Word(Round(Value));
  2084. WriteData(@iWord, iWord);
  2085. end;
  2086. ftInteger:
  2087. begin
  2088. iInt := Longint(Round(Value));
  2089. WriteData(@iInt, iInt);
  2090. end;
  2091. ftBoolean,
  2092. ftString, ftWideString, ftMemo:
  2093. SetAsString(FloatToStr(Value));
  2094. ftDateTime:
  2095. TypeErrorOnWriting(Value);
  2096. end;
  2097. end;
  2098. procedure TsdValue.SetAsInteger(const Value: Longint);
  2099. var
  2100. iValue: SmallInt;
  2101. iWord: Word;
  2102. fValue: Double;
  2103. cValue: Currency;
  2104. fBCD: TBCD;
  2105. begin
  2106. case DataType of
  2107. ftSmallint:
  2108. begin
  2109. iValue := Value;
  2110. WriteData(@iValue, iValue);
  2111. end;
  2112. ftWord:
  2113. begin
  2114. iWord := Value;
  2115. WriteData(@iWord, iWord);
  2116. end;
  2117. ftInteger:
  2118. WriteData(@Value, Value);
  2119. ftFloat, ftDateTime:
  2120. begin
  2121. fValue := Value;
  2122. WriteData(@fValue, fValue);
  2123. end;
  2124. ftCurrency, ftBCD:
  2125. begin
  2126. cValue := Value;
  2127. WriteData(@cValue, cValue);
  2128. end;
  2129. ftFMTBCD:
  2130. begin
  2131. fBCD := IntegerToBcd(Value);
  2132. WriteData(@fBCD, Value);
  2133. end;
  2134. ftBoolean,
  2135. ftString, ftWideString, ftMemo:
  2136. TypeErrorOnWriting(Value);
  2137. end;
  2138. end;
  2139. procedure TsdValue.SetAsString(const Value: string);
  2140. var
  2141. {B: Boolean;
  2142. isValue: SmallInt;
  2143. iWord: Word;
  2144. iE: Integer;
  2145. ilValue: Longint;
  2146. fDouble: Double;
  2147. fE: Extended;
  2148. fDataTime: TDateTime;
  2149. fCurrency: Currency; }
  2150. pData: Pointer;
  2151. vValue: Variant;
  2152. iLength: Integer;
  2153. bNoNull: Boolean;
  2154. begin
  2155. try
  2156. pData := nil;
  2157. ConvertDataBeforeWriteData(Value, pData, vValue, iLength, bNoNull);
  2158. WriteData(pData, vValue, iLength, bNoNull);
  2159. finally
  2160. if Assigned(pData) then
  2161. FreeMem(pData);
  2162. end;
  2163. {if Value = '' then
  2164. // 直接clear有问题,不会触发通知方法,还是需要调用WriteData
  2165. WriteData(nil, Null, 0, False)
  2166. else
  2167. case DataType of
  2168. ftBoolean:
  2169. begin
  2170. if SameText(BooleanStrArray[True], Value) then
  2171. B := True
  2172. else
  2173. B := False;
  2174. WriteData(@B, B);
  2175. end;
  2176. ftString, ftWideString, ftMemo:
  2177. WriteData(@Value[1], Value, Length(Value));
  2178. ftSmallint, ftInteger, ftWord:
  2179. begin
  2180. Val(Value, ilValue, iE);
  2181. if iE <> 0 then TypeErrorOnWriting(Value);
  2182. case DataType of
  2183. ftSmallint:
  2184. begin
  2185. isValue := ilValue;
  2186. WriteData(@isValue, isValue);
  2187. end;
  2188. ftWord:
  2189. begin
  2190. iWord := ilValue;
  2191. WriteData(@ilValue, ilValue);
  2192. end;
  2193. ftInteger:
  2194. WriteData(@ilValue, ilValue);
  2195. end;
  2196. end;
  2197. ftFloat:
  2198. begin
  2199. if not TextToFloat(PChar(Value), fE, fvExtended) then
  2200. TypeErrorOnWriting(Value);
  2201. fDouble := fE;
  2202. WriteData(@fDouble, fDouble);
  2203. end;
  2204. ftDateTime:
  2205. begin
  2206. fDataTime := StrToDateTime(Value);
  2207. WriteData(@fDataTime, fDataTime);
  2208. end;
  2209. ftCurrency, ftBCD:
  2210. begin
  2211. fCurrency := StrToCurr(Value);
  2212. WriteData(@fCurrency, fCurrency);
  2213. end;
  2214. end; }
  2215. end;
  2216. procedure TsdValue.SetAsVariant(const Value: Variant);
  2217. begin
  2218. if VarIsNull(Value) then
  2219. // 直接clear有问题,不会触发通知方法,还是需要调用WriteData
  2220. WriteData(nil, Null, 0, False)
  2221. else
  2222. case DataType of
  2223. ftBoolean: SetAsBoolean(sdVarToBoolean(Value));
  2224. ftCurrency, ftBCD: SetAsCurrency(sdVarToCurrency(Value));
  2225. ftFMTBCD: SetAsBCD(VarToBcd(Value));
  2226. ftDateTime: SetAsDateTime(sdVarToFloat(Value));
  2227. ftFloat: SetAsFloat(sdVarToFloat(Value));
  2228. ftSmallint, ftInteger, ftWord: SetAsInteger(sdVarToInteger(Value));
  2229. ftString, ftWideString, ftMemo: SetAsString(Value);
  2230. end;
  2231. end;
  2232. procedure TsdValue.SetEditText(const Value: string);
  2233. begin
  2234. SetAsString(Value);
  2235. end;
  2236. procedure TsdValue.SetField(Field: TsdField);
  2237. begin
  2238. FField := Field;
  2239. if Assigned(FData) then FreeMem(FData);
  2240. if not Field.IsVarField then
  2241. begin
  2242. FData := AllocMem(DataSize);
  2243. end
  2244. else
  2245. FData := nil;
  2246. end;
  2247. procedure TsdValue.TypeErrorOnWriting(const Value: Variant);
  2248. begin
  2249. raise EsdDataSet.Create(Format('Type mismached, can not assign value [%s] to field [%s.%s]', [VarToStr(Value), Owner.Owner.Name, FieldName]));
  2250. end;
  2251. function TsdValue.CanWriteData(Data, ACache: Pointer; Length: Integer; NoNull: Boolean): Boolean;
  2252. function SameData: Boolean;
  2253. var
  2254. I: Integer;
  2255. iLength, iCacheLength: Integer;
  2256. Pt1, Pt2: PByte;
  2257. begin
  2258. Result := False;
  2259. if ACache = nil then
  2260. Exit;
  2261. if FField.IsVarField then
  2262. begin
  2263. if FField.DataType = ftWideString then
  2264. begin
  2265. iLength := Length * 2;
  2266. iCacheLength := InnerCacheLength(ACache) * 2;
  2267. end
  2268. else
  2269. begin
  2270. iLength := Length;
  2271. iCacheLength := InnerCacheLength(ACache);
  2272. end;
  2273. if iCacheLength <> iLength then
  2274. Exit;
  2275. end
  2276. else
  2277. iLength := DataSize;
  2278. Result := CompareMem(ACache, Data, iLength);
  2279. end;
  2280. begin
  2281. Result := False;
  2282. if FForceWriteData then
  2283. begin
  2284. Result := True;
  2285. Exit;
  2286. end;
  2287. // 新数据不为空
  2288. if Data <> nil then
  2289. begin
  2290. // 判断是否相同
  2291. if SameData then
  2292. begin
  2293. // 对于数字类型,0和空会被SameData判断成一样的。
  2294. // 所以这里要对旧数据为空的情况,判断新数据是不是为空。
  2295. if FIsNull then
  2296. begin
  2297. if not NoNull then Exit;
  2298. end
  2299. else
  2300. Exit;
  2301. end;
  2302. end
  2303. // 新旧数据都为空
  2304. else if FIsNull then Exit;
  2305. Result := True;
  2306. end;
  2307. procedure TsdValue.InnerWriteData(Data: Pointer; const NewValue: Variant;
  2308. Length: Integer; NoNull: Boolean);
  2309. var
  2310. iLength: Integer;
  2311. Pt: PByte;
  2312. begin
  2313. if FOwner.Owner.UseSavePoint and FOwner.Owner.FEnableValueEvents and (not FOwner.Owner.FIsLoading)
  2314. and (not FOwner.Owner.FHistory.Stopping) then
  2315. FOwner.Owner.FHistory.Modify(Self);
  2316. InnerClear;
  2317. iLength := Length;
  2318. if FField.IsBlobField then
  2319. begin
  2320. if Length > 65535 then
  2321. iLength := 65535;
  2322. end
  2323. else
  2324. if (iLength <= 0) or (iLength > DataSize) then
  2325. iLength := DataSize;
  2326. if FField.IsVarField then
  2327. begin
  2328. if Assigned(FData) then FreeMem(FData);
  2329. // 字符串必须以0结尾,所以特殊处理
  2330. if FField.DataType = ftWideString then
  2331. FData := AllocMem((iLength + 1) * 2)
  2332. else
  2333. FData := AllocMem(iLength + 1);
  2334. end;
  2335. if (Data <> nil) and (NewValue <> Null) then
  2336. begin
  2337. if FField.DataType = ftWideString then
  2338. CopyMemory(FData, Data, iLength * 2)
  2339. else
  2340. CopyMemory(FData, Data, iLength);
  2341. // 字符串必须以0结尾,所以特殊处理
  2342. if FField.IsVarField then
  2343. begin
  2344. if FField.DataType = ftWideString then
  2345. begin
  2346. Pt := PByte(FData);
  2347. Inc(Pt, iLength * 2);
  2348. Pt^ := 0;
  2349. Inc(Pt);
  2350. Pt^ := 0;
  2351. end
  2352. else
  2353. begin
  2354. Pt := PByte(FData);
  2355. Inc(Pt, iLength);
  2356. Pt^ := 0;
  2357. end;
  2358. end;
  2359. FIsNull := False;
  2360. end
  2361. else
  2362. FIsNull := True;
  2363. if FOwner.Owner.FEnableValueEvents and (not FOwner.Owner.FIsLoading) then
  2364. FOwner.CacheModified(Self);
  2365. end;
  2366. procedure TsdValue.WriteData(Data: Pointer; const NewValue: Variant; Length: Integer; NoNull: Boolean);
  2367. var
  2368. Allow: Boolean;
  2369. iLength: Integer;
  2370. PCache: Pointer;
  2371. begin
  2372. if FOwner.Owner.FEnableValueEvents then
  2373. begin
  2374. if not FOwner.Owner.FIsLoading then
  2375. PCache := CopyCache
  2376. else
  2377. PCache := nil;
  2378. try
  2379. if not CanWriteData(Data, PCache, Length, NoNull) then Exit;
  2380. Allow := True;
  2381. // 节约内存,有变化时才缓存原始值
  2382. CacheOriginalValue;
  2383. FOwner.Owner.DoBeforeValueChange(Self, NewValue, Allow);
  2384. if not Allow then Exit;
  2385. InnerWriteData(Data, NewValue, Length, NoNull);
  2386. FOwner.Owner.DoAfterValueChanged(Self);
  2387. FOwner.Changed(Self);
  2388. finally
  2389. if not FOwner.Owner.FIsLoading then
  2390. ClearCache(PCache);
  2391. end;
  2392. end
  2393. else
  2394. InnerWriteData(Data, NewValue, Length, NoNull);
  2395. end;
  2396. procedure TsdValue.ConvertDataBeforeWriteData(const Value: string;
  2397. var Data: Pointer; var NewValue: Variant; var Length: Integer;
  2398. var NoNull: Boolean);
  2399. var
  2400. B: Boolean;
  2401. isValue: SmallInt;
  2402. iWord: Word;
  2403. iE: Integer;
  2404. ilValue: Longint;
  2405. fDouble: Double;
  2406. fE: Extended;
  2407. fDataTime: TDateTime;
  2408. fCurrency: Currency;
  2409. fBCD: TBCD;
  2410. pData: Pointer;
  2411. iLength: Integer;
  2412. wsValue: WideString;
  2413. begin
  2414. if Value = '' then
  2415. begin
  2416. // 直接clear有问题,不会触发通知方法,还是需要调用WriteData
  2417. pData := nil;
  2418. NewValue := Null;
  2419. Length := 0;
  2420. NoNull := False;
  2421. end
  2422. else
  2423. case DataType of
  2424. ftBoolean:
  2425. begin
  2426. if SameText(BooleanStrArray[True], Value) then
  2427. B := True
  2428. else
  2429. B := False;
  2430. pData := @B;
  2431. NewValue := B;
  2432. Length := 0;
  2433. NoNull := True;
  2434. end;
  2435. ftString, ftMemo:
  2436. begin
  2437. pData := @Value[1];
  2438. NewValue := Value;
  2439. Length := System.Length(Value);
  2440. NoNull := False;
  2441. end;
  2442. ftWideString:
  2443. begin
  2444. wsValue := Value;
  2445. pData := @wsValue[1];
  2446. NewValue := wsValue;
  2447. Length := System.Length(wsValue);
  2448. NoNull := False;
  2449. end;
  2450. ftSmallint, ftInteger, ftWord:
  2451. begin
  2452. Val(Value, ilValue, iE);
  2453. if iE <> 0 then TypeErrorOnWriting(Value);
  2454. case DataType of
  2455. ftSmallint:
  2456. begin
  2457. isValue := ilValue;
  2458. pData := @isValue;
  2459. NewValue := isValue;
  2460. Length := 0;
  2461. NoNull := True;
  2462. end;
  2463. ftWord:
  2464. begin
  2465. iWord := ilValue;
  2466. pData := @iWord;
  2467. NewValue := iWord;
  2468. Length := 0;
  2469. NoNull := True;
  2470. end;
  2471. ftInteger:
  2472. begin
  2473. pData := @ilValue;
  2474. NewValue := ilValue;
  2475. Length := 0;
  2476. NoNull := True;
  2477. end;
  2478. end;
  2479. end;
  2480. ftFloat:
  2481. begin
  2482. if not TextToFloat(PChar(Value), fE, fvExtended) then
  2483. TypeErrorOnWriting(Value);
  2484. fDouble := fE;
  2485. pData := @fDouble;
  2486. NewValue := fDouble;
  2487. Length := 0;
  2488. NoNull := True;
  2489. end;
  2490. ftDateTime:
  2491. begin
  2492. fDataTime := StrToDateTime(Value);
  2493. pData := @fDataTime;
  2494. NewValue := fDataTime;
  2495. Length := 0;
  2496. NoNull := True;
  2497. end;
  2498. ftCurrency, ftBCD:
  2499. begin
  2500. fCurrency := StrToCurr(Value);
  2501. pData := @fCurrency;
  2502. NewValue := fCurrency;
  2503. Length := 0;
  2504. NoNull := True;
  2505. end;
  2506. ftFMTBCD:
  2507. begin
  2508. if not TextToFloat(PChar(Value), fE, fvExtended) then
  2509. TypeErrorOnWriting(Value);
  2510. fBCD := StrToBcd(Value);
  2511. pData := @fBCD;
  2512. NewValue := fE;
  2513. Length := 0;
  2514. NoNull := True;
  2515. end;
  2516. end;
  2517. if pData = nil then
  2518. Data := nil
  2519. else
  2520. begin
  2521. iLength := Length;
  2522. if FField.IsBlobField then
  2523. begin
  2524. if Length > 65535 then
  2525. iLength := 65535;
  2526. end
  2527. else
  2528. begin
  2529. if (iLength <= 0) or (iLength > DataSize) then
  2530. iLength := DataSize;
  2531. if FField.DataType = ftWideString then
  2532. iLength := iLength * 2;
  2533. end;
  2534. Data := AllocMem(iLength);
  2535. CopyMemory(Data, pData, iLength);
  2536. end;
  2537. end;
  2538. procedure TsdValue.ClearCache(ACache: Pointer);
  2539. begin
  2540. if Assigned(ACache) then
  2541. FreeMem(ACache);
  2542. ACache := nil;
  2543. end;
  2544. function TsdValue.CopyCache: Pointer;
  2545. var
  2546. iLength: Integer;
  2547. begin
  2548. Result := nil;
  2549. if Assigned(FData) then
  2550. begin
  2551. // 字符串类型最后有一个#0字符
  2552. if FField.IsVarField then
  2553. begin
  2554. if FField.DataType = ftWideString then
  2555. iLength := (ActualLength + 1) * 2
  2556. else
  2557. iLength := ActualLength + 1;
  2558. end
  2559. else
  2560. iLength := DataSize;
  2561. Result := AllocMem(iLength);
  2562. CopyMemory(Result, FData, iLength);
  2563. end;
  2564. end;
  2565. procedure TsdValue.Assign(Source: TsdValue);
  2566. begin
  2567. if Source.DataType <> DataType then
  2568. raise EsdDataSet.Create('Can not assign value from different type sdValue');
  2569. if FField.IsVarField then
  2570. WriteData(Source.FData, Source.Value, Source.ActualLength)
  2571. else
  2572. WriteData(Source.FData, Source.Value);
  2573. end;
  2574. procedure TsdValue.InnerClear;
  2575. begin
  2576. if Assigned(FData) then
  2577. begin
  2578. if FField.IsVarField then
  2579. begin
  2580. if FField.DataType = ftWideString then
  2581. ZeroMemory(FData, ActualLength * 2)
  2582. else
  2583. ZeroMemory(FData, ActualLength);
  2584. end
  2585. else
  2586. ZeroMemory(FData, DataSize);
  2587. end;
  2588. FIsNull := True;
  2589. end;
  2590. function TsdValue.GetAsBCD: TBCD;
  2591. var
  2592. P: Pointer;
  2593. begin
  2594. Result := NullBcd;
  2595. case DataType of
  2596. ftFMTBCD:
  2597. begin
  2598. ReadData(P);
  2599. Result := PBCD(P)^;
  2600. end;
  2601. ftBoolean,
  2602. ftString, ftWideString, ftMemo,
  2603. ftSmallint, ftInteger, ftWord,
  2604. ftDateTime, ftCurrency, ftBCD, ftFloat:
  2605. TypeErrorOnWriting(0);
  2606. end;
  2607. end;
  2608. procedure TsdValue.SetAsBCD(const Value: TBCD);
  2609. begin
  2610. case DataType of
  2611. ftFMTBCD:
  2612. WriteData(@Value, BcdToDouble(Value));
  2613. ftBoolean,
  2614. ftString, ftWideString, ftMemo,
  2615. ftSmallint, ftInteger, ftWord,
  2616. ftDateTime, ftCurrency, ftBCD, ftFloat:
  2617. TypeErrorOnWriting(BcdToDouble(Value));
  2618. end;
  2619. end;
  2620. function TsdValue.GetOriginalValue: Variant;
  2621. begin
  2622. if not FOriginalCached then
  2623. Result := Value
  2624. else
  2625. Result := InnerGetCache(FOriginalValue);
  2626. end;
  2627. function TsdValue.GetAsWideString: WideString;
  2628. begin
  2629. Result := GetAsString;
  2630. end;
  2631. procedure TsdValue.SetAsWideString(const Value: WideString);
  2632. begin
  2633. SetAsString(Value);
  2634. end;
  2635. // 暂只测试整数和浮点数类型
  2636. function TsdValue._CopyFrom(Source: Pointer): Integer;
  2637. begin
  2638. raise EsdDataSet.Create('_CopyFrom暂未启用');
  2639. CopyMemory(FData, Source, DataSize);
  2640. FIsNull := False;
  2641. Result := DataSize;
  2642. end;
  2643. function TsdValue._MemorySize: Integer;
  2644. begin
  2645. if FField.IsVarField then
  2646. begin
  2647. if FField.DataType = ftWideString then
  2648. Result := ActualLength * 2
  2649. else
  2650. Result := ActualLength;
  2651. end
  2652. else
  2653. Result := DataSize;
  2654. end;
  2655. function TsdValue._CopyTo(Destination: Pointer): Integer;
  2656. begin
  2657. raise EsdDataSet.Create('_CopyTo暂未启用');
  2658. CopyMemory(Destination, FData, DataSize);
  2659. Result := DataSize;
  2660. end;
  2661. procedure TsdValue.InnerCopy(AValue: Variant);
  2662. begin
  2663. DisableEvents;
  2664. try
  2665. Value := AValue;
  2666. finally
  2667. EnableEvents;
  2668. end;
  2669. end;
  2670. function TsdValue.InnerCacheLength(ACache: Pointer): Integer;
  2671. var
  2672. I, iLength: Integer;
  2673. B, B2: Byte;
  2674. Pt: PByte;
  2675. begin
  2676. Result := 0;
  2677. if ACache = nil then Exit;
  2678. if FField.IsBlobField then
  2679. iLength := 65535
  2680. else
  2681. iLength := DataSize;
  2682. Result := iLength;
  2683. Pt := PByte(ACache);
  2684. if FField.DataType = ftWideString then
  2685. for I := 0 to iLength - 1 do
  2686. begin
  2687. B := Pt^;
  2688. Inc(Pt);
  2689. B2 := Pt^;
  2690. Inc(Pt);
  2691. if (B = 0) and (B2 = 0) then
  2692. begin
  2693. Result := I;
  2694. Break;
  2695. end;
  2696. end
  2697. else
  2698. for I := 0 to iLength - 1 do
  2699. begin
  2700. B := Pt^;
  2701. Inc(Pt);
  2702. if B = 0 then
  2703. begin
  2704. Result := I;
  2705. Break;
  2706. end;
  2707. end;
  2708. end;
  2709. function TsdValue.InnerGetCache(ACache: Pointer): Variant;
  2710. var
  2711. iLength: Integer;
  2712. strValue: string;
  2713. wsValue: WideString;
  2714. begin
  2715. Result := Null;
  2716. if not Assigned(ACache) then Exit;
  2717. case FField.DataType of
  2718. ftBoolean:
  2719. Result := PBoolean(ACache)^;
  2720. ftString, ftMemo:
  2721. begin
  2722. iLength := InnerCacheLength(ACache);
  2723. SetLength(strValue, iLength);
  2724. if iLength > 0 then
  2725. begin
  2726. CopyMemory(@strValue[1], ACache, iLength);
  2727. Result := strValue;
  2728. end
  2729. else
  2730. Result := '';
  2731. end;
  2732. ftWideString:
  2733. begin
  2734. iLength := InnerCacheLength(ACache);
  2735. SetLength(wsValue, iLength);
  2736. if iLength > 0 then
  2737. begin
  2738. CopyMemory(@wsValue[1], ACache, iLength * 2);
  2739. Result := wsValue;
  2740. end
  2741. else
  2742. Result := '';
  2743. end;
  2744. ftSmallint:
  2745. Result := PSmallInt(ACache)^;
  2746. ftWord:
  2747. Result := PWord(ACache)^;
  2748. ftInteger:
  2749. Result := PInteger(ACache)^;
  2750. ftFloat:
  2751. Result := PDouble(ACache)^;
  2752. ftDateTime:
  2753. Result := PDouble(ACache)^;
  2754. ftCurrency, ftBCD:
  2755. Result := PCurrency(ACache)^;
  2756. ftFMTBCD:
  2757. Result := VarFMTBcdCreate(PBCD(ACache)^);
  2758. end;
  2759. end;
  2760. procedure TsdValue.InnerSetCache(var ACache: Pointer; AValue: Variant);
  2761. var
  2762. iLength: Integer;
  2763. pData: Pointer;
  2764. B: Boolean;
  2765. isValue: SmallInt;
  2766. iWord: Word;
  2767. iE: Integer;
  2768. ilValue: Longint;
  2769. fDouble: Double;
  2770. fE: Extended;
  2771. fDataTime: TDateTime;
  2772. fCurrency: Currency;
  2773. fBCD: TBCD;
  2774. strValue: string;
  2775. wsValue: WideString;
  2776. begin
  2777. if VarIsNull(AValue) then
  2778. begin
  2779. if Assigned(ACache) then
  2780. FreeMem(ACache);
  2781. ACache := nil;
  2782. Exit;
  2783. end;
  2784. if Assigned(ACache) then
  2785. begin
  2786. if FField.IsVarField then
  2787. begin
  2788. FreeMem(ACache);
  2789. ACache := nil;
  2790. end
  2791. else
  2792. ZeroMemory(ACache, FField.DataSize);
  2793. end;
  2794. case FField.DataType of
  2795. ftBoolean:
  2796. begin
  2797. B := AValue;
  2798. pData := @B;
  2799. end;
  2800. ftString, ftMemo:
  2801. begin
  2802. strValue := AValue;
  2803. pData := @strValue[1];
  2804. iLength := System.Length(strValue);
  2805. end;
  2806. ftWideString:
  2807. begin
  2808. wsValue := AValue;
  2809. pData := @wsValue[1];
  2810. iLength := System.Length(wsValue);
  2811. end;
  2812. ftSmallint:
  2813. begin
  2814. isValue := AValue;
  2815. pData := @isValue;
  2816. end;
  2817. ftWord:
  2818. begin
  2819. iWord := AValue;
  2820. pData := @iWord;
  2821. end;
  2822. ftInteger:
  2823. begin
  2824. ilValue := AValue;
  2825. pData := @ilValue;
  2826. end;
  2827. ftFloat:
  2828. begin
  2829. fDouble := AValue;
  2830. pData := @fDouble;
  2831. end;
  2832. ftDateTime:
  2833. begin
  2834. fDataTime := Value;
  2835. pData := @fDataTime;
  2836. end;
  2837. ftCurrency, ftBCD:
  2838. begin
  2839. fCurrency := AValue;
  2840. pData := @fCurrency;
  2841. end;
  2842. ftFMTBCD:
  2843. begin
  2844. fBCD := VarToBcd(AValue);
  2845. pData := @fBCD;
  2846. end;
  2847. end;
  2848. if FField.IsVarField then
  2849. begin
  2850. // 字符串必须以0结尾,所以特殊处理
  2851. if FField.DataType = ftWideString then
  2852. begin
  2853. ACache := AllocMem((iLength + 1) * 2);
  2854. CopyMemory(ACache, pData, iLength * 2);
  2855. end
  2856. else
  2857. begin
  2858. ACache := AllocMem(iLength + 1);
  2859. CopyMemory(ACache, pData, iLength);
  2860. end;
  2861. end
  2862. else
  2863. begin
  2864. iLength := FField.DataSize;
  2865. if not Assigned(ACache) then
  2866. ACache := AllocMem(iLength);
  2867. CopyMemory(ACache, pData, iLength);
  2868. end;
  2869. end;
  2870. procedure TsdValue.InnerCopyCache(var ACache: Pointer);
  2871. var
  2872. iLength: Integer;
  2873. begin
  2874. if IsNull then
  2875. begin
  2876. if Assigned(ACache) then
  2877. begin
  2878. FreeMem(ACache);
  2879. ACache := nil;
  2880. end;
  2881. Exit;
  2882. end;
  2883. if FField.IsVarField then
  2884. begin
  2885. if Assigned(ACache) then
  2886. FreeMem(ACache);
  2887. iLength := ActualLength + 1;
  2888. if FField.DataType = ftWideString then
  2889. iLength := iLength * 2;
  2890. ACache := AllocMem(iLength);
  2891. end
  2892. else
  2893. begin
  2894. iLength := FField.DataSize;
  2895. if not Assigned(ACache) then
  2896. ACache := AllocMem(iLength);
  2897. end;
  2898. CopyMemory(ACache, FData, iLength);
  2899. end;
  2900. procedure TsdValue.CacheOriginalValue;
  2901. begin
  2902. if Owner.Owner.FIsLoading or Owner.FNew then Exit;
  2903. if not FOriginalCached then
  2904. begin
  2905. InnerCopyCache(FOriginalValue);
  2906. FOriginalCached := True;
  2907. end;
  2908. end;
  2909. procedure TsdValue.ClearOriginalValue;
  2910. begin
  2911. if Assigned(FOriginalValue) then
  2912. FreeMem(FOriginalValue);
  2913. FOriginalValue := nil;
  2914. FOriginalCached := False;
  2915. end;
  2916. procedure TsdValue.DisableEvents;
  2917. begin
  2918. FOwner.Owner.FEnableValueEvents := False;
  2919. end;
  2920. procedure TsdValue.EnableEvents;
  2921. begin
  2922. FOwner.Owner.FEnableValueEvents := True;
  2923. end;
  2924. { TsdValueList }
  2925. function TsdValueList.Add(Field: TsdField): TsdValue;
  2926. begin
  2927. if FindValue(Field, Result) then Exit;
  2928. Result := TsdValue.Create(FOwner);
  2929. Result.SetField(Field);
  2930. FList.Add(Result);
  2931. end;
  2932. procedure TsdValueList.Clear;
  2933. var
  2934. I: Integer;
  2935. s: string;
  2936. begin
  2937. for I := 0 to FList.Count - 1 do
  2938. try
  2939. s := FOwner.FOwner.Name + ' ';
  2940. s := s + TsdValue(FList[I]).FieldName;
  2941. TsdValue(FList[I]).Free;
  2942. except
  2943. MessageBox(0, PChar(s), PChar(IntToStr(I)), IDOK);
  2944. end;
  2945. FList.Clear;
  2946. end;
  2947. constructor TsdValueList.Create(AOwner: TsdDataRecord);
  2948. begin
  2949. FOwner := AOwner;
  2950. FList := TList.Create;
  2951. end;
  2952. destructor TsdValueList.Destroy;
  2953. begin
  2954. Clear;
  2955. FList.Free;
  2956. inherited;
  2957. end;
  2958. function TsdValueList.FindValue(Field: TsdField; var Value: TsdValue): Boolean;
  2959. var
  2960. I: Integer;
  2961. V: TsdValue;
  2962. begin
  2963. Result := False;
  2964. for I := 0 to FList.Count - 1 do
  2965. begin
  2966. V := Values[I];
  2967. if V.FField = Field then
  2968. begin
  2969. Value := V;
  2970. Result := True;
  2971. Break;
  2972. end;
  2973. end;
  2974. end;
  2975. function TsdValueList.GetCount: Integer;
  2976. begin
  2977. Result := FList.Count;
  2978. end;
  2979. function TsdValueList.GetValues(Index: Integer): TsdValue;
  2980. begin
  2981. Result := nil;
  2982. if (Index >=0) and (Index <= FList.Count - 1) then
  2983. Result := TsdValue(FList[Index]);
  2984. end;
  2985. { TsdDataRecord }
  2986. function TsdDataRecord.AddValue(FieldNo: Integer; DBField: TField): TsdValue;
  2987. begin
  2988. Result := FValueList.Values[FieldNo];
  2989. if Result <> nil then
  2990. begin
  2991. if Result.FIsNull and (not DBField.IsNull) then
  2992. Result.ForceWriteData := True;
  2993. try
  2994. if DBField.IsNull then
  2995. Result.Clear
  2996. else
  2997. case Result.DataType of
  2998. ftBoolean:
  2999. Result.AsBoolean := DBField.AsBoolean;
  3000. ftString, ftMemo:
  3001. Result.AsString := DBField.AsString;
  3002. ftWideString:
  3003. Result.AsWideString := TWideStringField(DBField).Value;
  3004. ftSmallint, ftInteger, ftWord:
  3005. Result.AsInteger := DBField.AsInteger;
  3006. ftDateTime:
  3007. Result.AsDateTime := DBField.AsDateTime;
  3008. ftFloat:
  3009. Result.AsFloat := DBField.AsFloat;
  3010. ftCurrency, ftBCD:
  3011. Result.AsCurrency := DBField.AsCurrency;
  3012. ftFMTBCD:
  3013. Result.AsBCD := TFMTBCDField(DBField).AsBCD;
  3014. end;
  3015. finally
  3016. Result.ForceWriteData := False;
  3017. end;
  3018. end
  3019. else
  3020. raise EsdDataSet.Create(Format('Can not find field %d', [FieldNo]));
  3021. end;
  3022. function TsdDataRecord.AddValue(Field: TsdField; Value: Variant; IsNull: Boolean): TsdValue;
  3023. begin
  3024. Result := FValueList.Add(Field);
  3025. if Result <> nil then
  3026. begin
  3027. if Result.FIsNull and (not IsNull) then
  3028. Result.ForceWriteData := True;
  3029. Result.FIsNull := IsNull;
  3030. try
  3031. Result.Value := Value;
  3032. finally
  3033. Result.ForceWriteData := False;
  3034. end;
  3035. end;
  3036. end;
  3037. procedure TsdDataRecord.AddFields;
  3038. var
  3039. I: Integer;
  3040. Field: TsdField;
  3041. begin
  3042. for I := 0 to FOwner.FieldCount - 1 do
  3043. begin
  3044. Field := FOwner.Fields.Fields[I];
  3045. FValueList.Add(Field);
  3046. end;
  3047. DoAfterAddFields;
  3048. end;
  3049. function TsdDataRecord.AddValue(FieldName: string;
  3050. Value: Variant; IsNull: Boolean): TsdValue;
  3051. var
  3052. Field: TsdField;
  3053. begin
  3054. Result := nil;
  3055. Field := FOwner.FFieldList.FieldByName(FieldName);
  3056. if Field <> nil then
  3057. Result := AddValue(Field, Value, IsNull);
  3058. end;
  3059. procedure TsdDataRecord.Changed(Value: TsdValue);
  3060. begin
  3061. if FOwner.FIsLoading then Exit;
  3062. NotifyIndex(Value);
  3063. if not IsUpdating then
  3064. FOwner.CheckIndex(Self);
  3065. if not FModified then FModified := True;
  3066. if FChangedValueList.IndexOf(Value) < 0 then
  3067. FChangedValueList.Add(Value);
  3068. if FModified and (not IsUpdating) then
  3069. begin
  3070. FOwner.Changed(Self, sroModify);
  3071. FOwner.DoAfterRecordChanged(Self);
  3072. end;
  3073. NotifyLookup(Value.Field);
  3074. end;
  3075. procedure TsdDataRecord.Clear;
  3076. begin
  3077. FValueList.Clear;
  3078. end;
  3079. constructor TsdDataRecord.Create(AOwner: TsdDataSet);
  3080. begin
  3081. FIndex := -1;
  3082. FRecNo := -1;
  3083. FUpdateLock := 0;
  3084. FNew := False;
  3085. FNeedNotifyIndex := False;
  3086. FModified := False;
  3087. FInserting := 0;
  3088. FOwner := AOwner;
  3089. FValueList := TsdValueList.Create(Self);
  3090. FChangedValueList := TList.Create;
  3091. FCanceled := False;
  3092. FCache := nil;
  3093. FData := nil;
  3094. FPData := nil;
  3095. end;
  3096. destructor TsdDataRecord.Destroy;
  3097. begin
  3098. Clear;
  3099. FChangedValueList.Free;
  3100. FValueList.Free;
  3101. if Assigned(FCache) then
  3102. FreeAndNil(FCache);
  3103. inherited;
  3104. end;
  3105. function TsdDataRecord.GetValues(FieldNo: Integer): TsdValue;
  3106. begin
  3107. Result := FValueList[FieldNo];
  3108. end;
  3109. procedure TsdDataRecord.Loaded;
  3110. var
  3111. I: Integer;
  3112. begin
  3113. FNew := False;
  3114. FModified := False;
  3115. for I := 0 to FValueList.Count - 1 do
  3116. FValueList[I].ClearOriginalValue;
  3117. end;
  3118. function TsdDataRecord.ValueByName(FieldName: string): TsdValue;
  3119. var
  3120. I: Integer;
  3121. begin
  3122. Result := nil;
  3123. for I := 0 to FValueList.Count - 1 do
  3124. if SameText(FieldName, TsdValue(FValueList[I]).FieldName) then
  3125. begin
  3126. Result := TsdValue(FValueList[I]);
  3127. Break;
  3128. end;
  3129. end;
  3130. function TsdDataRecord.GetIsUpdating: Boolean;
  3131. begin
  3132. Result := FUpdateLock > 0;
  3133. end;
  3134. procedure TsdDataRecord.BeginUpdate;
  3135. begin
  3136. if not IsUpdating then
  3137. BeginTrans;
  3138. Inc(FUpdateLock);
  3139. FOwner.DoBeforeRecordUpdate(Self);
  3140. end;
  3141. procedure TsdDataRecord.EndUpdate;
  3142. begin
  3143. if FUpdateLock = 0 then
  3144. Exit;
  3145. if FUpdateLock > 0 then
  3146. Dec(FUpdateLock);
  3147. if not IsUpdating then
  3148. begin
  3149. // 事件中的Cancel才会运行到这里
  3150. if Canceled then
  3151. begin
  3152. FOwner.CancelRecord(Self);
  3153. if not Inserting then
  3154. EndTrans;
  3155. Exit;
  3156. end
  3157. else
  3158. EndTrans;
  3159. end;
  3160. if FModified and (not IsUpdating) then
  3161. begin
  3162. Owner.CheckIndex(Self);
  3163. Owner.Changed(Self, sroModify);
  3164. Owner.DoAfterRecordChanged(Self);
  3165. NotifyLookup(nil);
  3166. end;
  3167. if FInserting > FUpdateLock then
  3168. SetInserting(False, True);
  3169. FOwner.DoAfterRecordUpdated(Self);
  3170. if (not IsUpdating) and (Owner.FEventRec = Self) then
  3171. begin
  3172. Owner.FCurrentView := nil;
  3173. Owner.FEventRec := nil;
  3174. end;
  3175. end;
  3176. procedure TsdDataRecord.DoAfterAddFields;
  3177. begin
  3178. end;
  3179. function TsdDataRecord.GetFieldValue(const FieldName: string): Variant;
  3180. var
  3181. I, iPos: Integer;
  3182. strFields, strField: string;
  3183. V: TsdValue;
  3184. ValueList: TList;
  3185. begin
  3186. if Pos(';', FieldName) <> 0 then
  3187. begin
  3188. ValueList := TList.Create;
  3189. try
  3190. strFields := FieldName;
  3191. while Length(strFields) > 0 do
  3192. begin
  3193. iPos := Pos(';', strFields);
  3194. if iPos > 0 then
  3195. begin
  3196. strField := Copy(strFields, 1, iPos - 1);
  3197. System.Delete(strFields, 1, iPos - 1);
  3198. end
  3199. else
  3200. begin
  3201. strField := strFields;
  3202. strFields := '';
  3203. end;
  3204. V := ValueByName(strField);
  3205. ValueList.Add(V);
  3206. end;
  3207. Result := VarArrayCreate([0, ValueList.Count - 1], varVariant);
  3208. for I := 0 to ValueList.Count - 1 do
  3209. Result[I] := TsdValue(ValueList[I]).Value;
  3210. finally
  3211. ValueList.Free;
  3212. end;
  3213. end
  3214. else
  3215. Result := ValueByName(FieldName).Value;
  3216. end;
  3217. procedure TsdDataRecord.NotifyLookup(Field: TsdField);
  3218. begin
  3219. FOwner.CheckChangedLookupFields(Field, Self);
  3220. end;
  3221. procedure TsdDataRecord.DoAfterSaved;
  3222. var
  3223. I: Integer;
  3224. begin
  3225. //if FNew then FNew := False;
  3226. //if FModified then FModified := False;
  3227. Loaded;
  3228. FChangedValueList.Clear;
  3229. end;
  3230. procedure TsdDataRecord.NotifyIndex(Value: TsdValue);
  3231. var
  3232. I: Integer;
  3233. Idx: TsdIndex;
  3234. begin
  3235. for I := 0 to Owner.IndexList.Count - 1 do
  3236. begin
  3237. Idx := Owner.IndexList[I];
  3238. if FNeedNotifyIndex or Idx.IsKeyField(Value.FieldName) then
  3239. Idx.AddChangedRecord(Self);
  3240. end;
  3241. if FNeedNotifyIndex then FNeedNotifyIndex := False;
  3242. end;
  3243. procedure TsdDataRecord.EnterEvent;
  3244. begin
  3245. FIsInEvent := True;
  3246. end;
  3247. procedure TsdDataRecord.ExitEvent;
  3248. begin
  3249. FIsInEvent := False;
  3250. end;
  3251. function TsdDataRecord.GetCount: Integer;
  3252. begin
  3253. Result := FValueList.Count;
  3254. end;
  3255. function TsdDataRecord.GetInserting: Boolean;
  3256. begin
  3257. Result := FInserting > 0;
  3258. end;
  3259. procedure TsdDataRecord.SetInserting(Value, NeedBeginUpdate: Boolean);
  3260. begin
  3261. if Value then
  3262. begin
  3263. if NeedBeginUpdate then
  3264. FInserting := FUpdateLock + 1
  3265. else
  3266. FInserting := MaxInt;
  3267. end
  3268. else
  3269. FInserting := 0;
  3270. end;
  3271. procedure TsdDataRecord.SetData(const Value: Pointer);
  3272. begin
  3273. FData := Value;
  3274. end;
  3275. procedure TsdDataRecord.Cancel;
  3276. begin
  3277. if not IsUpdating then
  3278. raise EsdDataSet.Create('Please call BeginUpdate before Cancel');
  3279. FCanceled := True;
  3280. // 在事件中先不处理,在EndUpdate中处理
  3281. if not IsInEvent then
  3282. begin
  3283. //FInserting := 0;
  3284. FUpdateLock := 0;
  3285. FOwner.CancelRecord(Self);
  3286. end;
  3287. end;
  3288. procedure TsdDataRecord.BeginTrans;
  3289. begin
  3290. FCache := TsdDataRecordCache.Create(Self);
  3291. end;
  3292. procedure TsdDataRecord.EndTrans;
  3293. begin
  3294. if FCache <> nil then
  3295. FreeAndNil(FCache);
  3296. end;
  3297. procedure TsdDataRecord.Rollback;
  3298. var
  3299. I: Integer;
  3300. VTarget: TsdValueCache;
  3301. VSource: TsdValue;
  3302. begin
  3303. if FCache = nil then Exit;
  3304. for I := 0 to FValueList.Count - 1 do
  3305. begin
  3306. VTarget := FCache.Values[I];
  3307. if VTarget.FModified then
  3308. begin
  3309. VSource := FValueList[I];
  3310. VSource.InnerCopy(VTarget.Value);
  3311. end;
  3312. end;
  3313. FreeAndNil(FCache);
  3314. end;
  3315. procedure TsdDataRecord.CacheModified(Source: TsdValue);
  3316. var
  3317. VTarget: TsdValueCache;
  3318. begin
  3319. if FCache = nil then Exit;
  3320. VTarget := FCache.Values[Source.FieldNo];
  3321. if VTarget <> nil then
  3322. VTarget.FModified := True;
  3323. end;
  3324. procedure TsdDataRecord.Delete;
  3325. begin
  3326. FOwner.Remove(Self);
  3327. end;
  3328. procedure TsdDataRecord.ForceNotifyIndex;
  3329. var
  3330. I: Integer;
  3331. Idx: TsdIndex;
  3332. begin
  3333. for I := 0 to Owner.IndexList.Count - 1 do
  3334. begin
  3335. Idx := Owner.IndexList[I];
  3336. Idx.AddChangedRecord(Self);
  3337. end;
  3338. end;
  3339. procedure TsdDataRecord.SetPData(Value: Pointer);
  3340. begin
  3341. FPData := Value;
  3342. end;
  3343. { TsdIndexNode }
  3344. constructor TsdIndexNode.Create(AOwner: TsdIndex);
  3345. begin
  3346. FOwner := AOwner;
  3347. end;
  3348. destructor TsdIndexNode.Destroy;
  3349. begin
  3350. inherited;
  3351. end;
  3352. function TsdIndexNode.GetChildCount: Integer;
  3353. var
  3354. Node: TsdIndexNode;
  3355. begin
  3356. Result := 0;
  3357. Node := FirstChild;
  3358. while Node <> nil do
  3359. begin
  3360. Inc(Result);
  3361. Node := Node.NextSibling;
  3362. end;
  3363. end;
  3364. function TsdIndexNode.GetChildren(Index: Integer): TsdIndexNode;
  3365. var
  3366. I: Integer;
  3367. begin
  3368. Result := nil;
  3369. if (Index >= 0) and (Index < ChildCount) then
  3370. begin
  3371. I := 0;
  3372. Result := FirstChild;
  3373. while I < Index do
  3374. begin
  3375. Result := Result.NextSibling;
  3376. Inc(I);
  3377. end;
  3378. end;
  3379. end;
  3380. function TsdIndexNode.GetLastChild: TsdIndexNode;
  3381. begin
  3382. if FirstChild = nil then
  3383. Result := nil
  3384. else
  3385. begin
  3386. Result := FirstChild;
  3387. while Result.NextSibling <> nil do
  3388. Result := Result.NextSibling;
  3389. end;
  3390. end;
  3391. function TsdIndexNode.GetLastPosterity: TsdIndexNode;
  3392. begin
  3393. Result := LastChild;
  3394. if Result = nil then Exit;
  3395. while Result.LastChild <> nil do
  3396. Result := Result.LastChild;
  3397. end;
  3398. function TsdIndexNode.GetLevel: Integer;
  3399. var
  3400. ParentNode: TsdIndexNode;
  3401. begin
  3402. Result := -1;
  3403. ParentNode := Parent;
  3404. while ParentNode <> nil do
  3405. begin
  3406. ParentNode := ParentNode.Parent;
  3407. Inc(Result);
  3408. end;
  3409. end;
  3410. function TsdIndexNode.GetRecordCount: Integer;
  3411. var
  3412. NextNode: TsdIndexNode;
  3413. begin
  3414. // 找后一个兄弟,有后兄弟则是后兄弟,没有后兄弟则是最后一个子节点的下一个节点,
  3415. // 没有子节点则是自己下一个节点
  3416. NextNode := NextNodeByLevel;
  3417. // 没有下一个节点则是最后所有记录
  3418. if NextNode <> nil then
  3419. Result := NextNode.RecIndex - RecIndex
  3420. else
  3421. Result := FOwner.FDataList.Count - RecIndex;
  3422. end;
  3423. function TsdIndexNode.HasRecord(ARecord: TsdDataRecord): Boolean;
  3424. var
  3425. iIdx: Integer;
  3426. Node: TsdIndexNode;
  3427. begin
  3428. iIdx := FOwner.IndexOf(ARecord);
  3429. Result := iIdx >= RecIndex;
  3430. Node := NextNodeByLevel;
  3431. if Result and (Node <> nil) then
  3432. Result := iIdx < Node.RecIndex;
  3433. end;
  3434. // 找后一个兄弟,有后兄弟则是后兄弟,没有后兄弟则是最后一个子节点的下一个节点,
  3435. // 没有子节点则是自己下一个节点
  3436. function TsdIndexNode.NextNodeByLevel: TsdIndexNode;
  3437. var
  3438. Node, NextNode: TsdIndexNode;
  3439. iIdx: Integer;
  3440. begin
  3441. NextNode := nil;
  3442. if NextSibling <> nil then
  3443. NextNode := NextSibling
  3444. else
  3445. begin
  3446. if FirstChild <> nil then
  3447. Node := LastPosterity
  3448. else
  3449. Node := Self;
  3450. iIdx := FOwner.FIndexNodeList.IndexOf(Node);
  3451. if iIdx < FOwner.FIndexNodeList.Count - 1 then
  3452. NextNode := TsdIndexNode(FOwner.FIndexNodeList[iIdx + 1]);
  3453. end;
  3454. Result := NextNode;
  3455. end;
  3456. procedure TsdIndexNode.SetDataType(const Value: TFieldType);
  3457. begin
  3458. FDataType := Value;
  3459. end;
  3460. procedure TsdIndexNode.SetFirstChild(const Value: TsdIndexNode);
  3461. begin
  3462. FFirstChild := Value;
  3463. end;
  3464. procedure TsdIndexNode.SetNextSibling(const Value: TsdIndexNode);
  3465. begin
  3466. FNextSibling := Value;
  3467. end;
  3468. procedure TsdIndexNode.SetParent(const Value: TsdIndexNode);
  3469. begin
  3470. FParent := Value;
  3471. end;
  3472. procedure TsdIndexNode.SetPrevSibling(const Value: TsdIndexNode);
  3473. begin
  3474. FPrevSibling := Value;
  3475. end;
  3476. procedure TsdIndexNode.SetRecIndex(const Value: Integer);
  3477. begin
  3478. FRecIndex := Value;
  3479. end;
  3480. procedure TsdIndexNode.SetValue(const Value: Variant);
  3481. begin
  3482. FValue := Value;
  3483. end;
  3484. { TsdIndex }
  3485. procedure TsdIndex.Clear;
  3486. var
  3487. I: Integer;
  3488. begin
  3489. FDataList.Clear;
  3490. for I := 0 to FIndexNodeList.Count - 1 do
  3491. TsdIndexNode(FIndexNodeList[I]).Free;
  3492. FIndexNodeList.Clear;
  3493. FIndexRoot.FFirstChild := nil;
  3494. end;
  3495. // Result: 0: ARec1 = ARec2 >0: ARec1 > ARec2 <0: ARec1 < ARec2
  3496. function TsdIndex.CompareData(ARec1, ARec2: TsdDataRecord): Integer;
  3497. var
  3498. V1, V2: Variant;
  3499. iLevel: Integer;
  3500. begin
  3501. iLevel := 0;
  3502. repeat
  3503. V1 := GetValue(ARec1, iLevel);
  3504. V2 := GetValue(ARec2, iLevel);
  3505. Result := CompareValue(V1, V2);
  3506. // 对于不唯一的字段,作为索引的时候,如果因为其它字段被修改引发了排序,相同索引值下的记录可能会混乱
  3507. // 所以要根据一个唯一值再比较一下,这里选用Record.FIndex
  3508. if (Result = 0) and (iLevel = LevelCount - 1) then
  3509. Result := CompareIndex(ARec1, ARec2);
  3510. Inc(iLevel);
  3511. until (Result <> 0) or (iLevel > LevelCount - 1);
  3512. end;
  3513. constructor TsdIndex.Create(AOwner: TsdIndexList);
  3514. begin
  3515. FDescend := False;
  3516. FSortNullToLast := True;
  3517. FOwner := AOwner;
  3518. FDataList := TList.Create;
  3519. FIndexNodeList := TList.Create;
  3520. FFieldList := TList.Create;
  3521. FIndexRoot := TsdIndexNode.Create(Self);
  3522. FIndexRoot.FValue := 'Root';
  3523. FChangedList := TList.Create;
  3524. end;
  3525. destructor TsdIndex.Destroy;
  3526. begin
  3527. Clear;
  3528. FIndexRoot.Free;
  3529. FDataList.Free;
  3530. FIndexNodeList.Free;
  3531. FFieldList.Free;
  3532. FChangedList.Free;
  3533. FOwner.FOwner.IndexDeleted(Name);
  3534. inherited;
  3535. end;
  3536. function TsdIndex.GetKeyCount(Level: Integer): Integer;
  3537. begin
  3538. Result := FFieldList.Count;
  3539. end;
  3540. function TsdIndex.GetRecords(Index: Integer): TsdDataRecord;
  3541. begin
  3542. Result := nil;
  3543. if (Index >= 0) and (Index < FDataList.Count) then
  3544. Result := TsdDataRecord(FDataList[Index]);
  3545. end;
  3546. function TsdIndex.GetValue(ARecord: TsdDataRecord;
  3547. ALevel: Integer): Variant;
  3548. var
  3549. Field: TsdField;
  3550. begin
  3551. Result := Null;
  3552. if (ALevel >= 0) and (ALevel <= LevelCount - 1) then
  3553. begin
  3554. Field := TsdField(FFieldList[ALevel]);
  3555. Result := ARecord.Values[Field.FieldNo].Value;
  3556. end;
  3557. end;
  3558. // 根据记录索引查找已存在的索引位置
  3559. // -1: 找不到索引(需要进行处理以防出错)
  3560. // 0-maxint: 索引位置
  3561. function TsdIndex.FindExistKeyIndex(ARecordIndex: Integer): Integer;
  3562. var
  3563. I: Integer;
  3564. begin
  3565. Result := -1;
  3566. if FIndexNodeList.Count = 0 then Exit;
  3567. // 只有一条索引记录
  3568. if FIndexNodeList.Count = 1 then
  3569. begin
  3570. Result := 0;
  3571. Exit;
  3572. end;
  3573. // 属于最后一条索引记录
  3574. if TsdIndexNode(FIndexNodeList[FIndexNodeList.Count - 1]).RecIndex <= ARecordIndex then
  3575. begin
  3576. Result := FIndexNodeList.Count - 1;
  3577. Exit;
  3578. end;
  3579. // 中间
  3580. for I := 0 to FIndexNodeList.Count - 2 do
  3581. begin
  3582. if (TsdIndexNode(FIndexNodeList[I]).RecIndex <= ARecordIndex) and
  3583. (ARecordIndex < TsdIndexNode(FIndexNodeList[I + 1]).RecIndex) then
  3584. begin
  3585. Result := I;
  3586. Break;
  3587. end;
  3588. end;
  3589. end;
  3590. function TsdIndex.Check(ARecord: TsdDataRecord): Integer;
  3591. // 获取插入位置的索引号列表
  3592. // 相同的记录,后插入的放在后面
  3593. // 二分法不好设计,暂用顺序遍历
  3594. {function FindInsertPos(ARecord: TsdDataRecord): Integer;
  3595. var
  3596. I: Integer;
  3597. begin
  3598. Result := 0;
  3599. // 没有记录
  3600. if FDataList.Count = 0 then
  3601. Exit;
  3602. // 小于最小
  3603. if CompareData(TsdDataRecord(FDataList[0]), ARecord) > 0 then
  3604. begin
  3605. Result := 0;
  3606. Exit;
  3607. end;
  3608. // 大于等于最大
  3609. if CompareData(ARecord, TsdDataRecord(FDataList[FDataList.Count - 1])) >= 0 then
  3610. begin
  3611. Result := FDataList.Count;
  3612. Exit;
  3613. end;
  3614. // 只有一条记录
  3615. if FDataList.Count = 1 then
  3616. begin
  3617. if CompareData(TsdDataRecord(FDataList[0]), ARecord) <= 0 then
  3618. Result := 1
  3619. else
  3620. Result := 0;
  3621. Exit;
  3622. end;
  3623. // 顺序查找
  3624. for I := 0 to FDataList.Count - 1 do
  3625. begin
  3626. if (CompareData(TsdDataRecord(FDataList[I]), ARecord) <= 0) and
  3627. (CompareData(ARecord, TsdDataRecord(FDataList[I + 1])) < 0) then
  3628. begin
  3629. Result := I + 1;
  3630. Break;
  3631. end;
  3632. end;
  3633. end; }
  3634. function FindInBrothers(ARecord: TsdDataRecord; AFirstChild: TsdIndexNode; AValue: Variant;
  3635. var ANode: TsdIndexNode): Boolean;
  3636. var
  3637. Node: TsdIndexNode;
  3638. iResult: Integer;
  3639. begin
  3640. Result := False;
  3641. ANode := nil;
  3642. Node := AFirstChild;
  3643. while Node <> nil do
  3644. begin
  3645. iResult := CompareValue(Node.Value, AValue);
  3646. if iResult >= 0 then
  3647. begin
  3648. Result := iResult = 0;
  3649. ANode := Node;
  3650. Break;
  3651. end;
  3652. Node := Node.NextSibling;
  3653. ANode := Node;
  3654. end;
  3655. end;
  3656. function AddIndexNode(ARecord: TsdDataRecord; var ARecordIndex: Integer): TsdIndexNode;
  3657. var
  3658. ParentNode, NextNode, Node, PrevSibling, ChildNode: TsdIndexNode;
  3659. I, J, iKey: Integer;
  3660. vData: Variant;
  3661. bNeedInsert: Boolean;
  3662. begin
  3663. Result := nil;
  3664. ParentNode := FIndexRoot;
  3665. for I := 0 to FFieldList.Count - 1 do
  3666. begin
  3667. bNeedInsert := False;
  3668. vData := GetValue(ARecord, I);
  3669. NextNode := nil;
  3670. // 还没有子节点
  3671. if ParentNode.FirstChild = nil then
  3672. begin
  3673. bNeedInsert := True;
  3674. end
  3675. else
  3676. begin
  3677. // 找后兄弟
  3678. bNeedInsert := not FindInBrothers(ARecord, ParentNode.FirstChild, vData, Node);
  3679. // 找到符合要求的节点
  3680. if not bNeedInsert then
  3681. begin
  3682. // 已经到最后一层节点
  3683. if I = FFieldList.Count - 1 then
  3684. begin
  3685. Result := Node;
  3686. // 插入位置是后兄弟最后一个后代节点之后
  3687. if Node.LastChild <> nil then
  3688. Node := Node.LastPosterity;
  3689. // 加入FDataList, 加在当前节点最后一条记录之后
  3690. ARecordIndex := Node.RecIndex + Node.RecordCount;
  3691. FDataList.Insert(ARecordIndex, ARecord);
  3692. // 添加完最底层节点需要维护主索引
  3693. iKey := FIndexNodeList.IndexOf(Node);
  3694. for J := iKey + 1 to FIndexNodeList.Count - 1 do
  3695. Inc(TsdIndexNode(FIndexNodeList[J]).FRecIndex);
  3696. end
  3697. else
  3698. ParentNode := Node;
  3699. Continue;
  3700. end
  3701. else // 没有符合要求的节点
  3702. begin
  3703. NextNode := Node;
  3704. end;
  3705. end;
  3706. // 开始添加节点
  3707. Result := TsdIndexNode.Create(Self);
  3708. Result.Parent := ParentNode;
  3709. Result.Value := vData;
  3710. //Result.RecIndex := ARecordIndex;
  3711. // 有后兄弟
  3712. if NextNode <> nil then
  3713. begin
  3714. // 插入到中间
  3715. if NextNode.PrevSibling <> nil then
  3716. begin
  3717. Node := NextNode.PrevSibling;
  3718. Node.NextSibling := Result;
  3719. Result.PrevSibling := Node;
  3720. Result.FRecIndex := NextNode.RecIndex;
  3721. end
  3722. // 插入到最前
  3723. else
  3724. begin
  3725. ParentNode.FirstChild := Result;
  3726. Result.FRecIndex := ParentNode.RecIndex;
  3727. end;
  3728. NextNode.PrevSibling := Result;
  3729. Result.NextSibling := NextNode;
  3730. iKey := FIndexNodeList.IndexOf(NextNode);
  3731. end
  3732. // 无后兄弟
  3733. else
  3734. begin
  3735. // 找到最后一个兄弟
  3736. if ParentNode.LastChild <> nil then
  3737. begin
  3738. Node := ParentNode.LastChild;
  3739. Result.PrevSibling := Node;
  3740. // 插入位置是后兄弟最后一个后代节点之后
  3741. ChildNode := Node;
  3742. if ChildNode.LastChild <> nil then
  3743. ChildNode := ChildNode.LastPosterity;
  3744. iKey := FIndexNodeList.IndexOf(ChildNode) + 1;
  3745. Result.FRecIndex := ChildNode.RecIndex + ChildNode.RecordCount;
  3746. // Node.RecordCount需要调用NextSibling,所以NextSibling赋值要放在后面
  3747. Node.NextSibling := Result;
  3748. end
  3749. // 没有最后兄弟表示没有子节点
  3750. else
  3751. begin
  3752. ParentNode.FirstChild := Result;
  3753. iKey := FIndexNodeList.IndexOf(ParentNode) + 1;
  3754. // 第一层第一个节点RecIndex为0,下层第一个字节的跟父节点一样
  3755. if Result.Level = 0 then
  3756. Result.FRecIndex := 0
  3757. else
  3758. Result.FRecIndex := ParentNode.RecIndex;
  3759. end;
  3760. end;
  3761. ParentNode := Result;
  3762. // 插入节点列表
  3763. if iKey = -1 then iKey := 0;
  3764. FIndexNodeList.Insert(iKey, Result);
  3765. // 添加完最底层节点
  3766. if I = FFieldList.Count - 1 then
  3767. begin
  3768. // 插入FDataList
  3769. ARecordIndex := Result.RecIndex;
  3770. FDataList.Insert(ARecordIndex, ARecord);
  3771. // 维护主索引
  3772. for J := iKey + 1 to FIndexNodeList.Count - 1 do
  3773. Inc(TsdIndexNode(FIndexNodeList[J]).FRecIndex);
  3774. end;
  3775. end;
  3776. end;
  3777. var
  3778. I, iIdx, iKey: Integer;
  3779. Node: TsdIndexNode;
  3780. begin
  3781. Result := -1;
  3782. // 此记录修改不影响本索引,则退出
  3783. if FChangedList.IndexOf(ARecord) < 0 then Exit;
  3784. // 如果是修改值,先将记录取出
  3785. if FDataList.IndexOf(ARecord) >= 0 then
  3786. InnerDelete(ARecord);
  3787. // 插入数据记录
  3788. //iIdx := FindInsertPos(ARecord);
  3789. //FDataList.Insert(iIdx, ARecord);
  3790. // 生成索引数据
  3791. Node := AddIndexNode(ARecord, iIdx);
  3792. // 容错处理:若插入失败则重新生成索引,只在调试状态提示
  3793. if Node = nil then
  3794. try
  3795. raise EsdIndex.Create('Failed to add record to index');
  3796. except
  3797. Sort;
  3798. end;
  3799. Result := iIdx;
  3800. FChangedList.Remove(ARecord);
  3801. //GetDebugData;
  3802. end;
  3803. procedure TsdIndex.InnerDelete(ARecord: TsdDataRecord);
  3804. procedure DeleteNode(Node: TsdIndexNode);
  3805. begin
  3806. // 因为此处不会有子节点,所以不处理子节点
  3807. // 本节点是父节点第一个子节点
  3808. if Node.Parent.FirstChild = Node then
  3809. Node.Parent.FirstChild := Node.NextSibling;
  3810. // 处理兄弟节点
  3811. if Node.PrevSibling <> nil then
  3812. begin
  3813. Node.PrevSibling.NextSibling := Node.NextSibling;
  3814. if Node.NextSibling <> nil then
  3815. Node.NextSibling.PrevSibling := Node.PrevSibling;
  3816. end
  3817. else
  3818. if Node.NextSibling <> nil then
  3819. Node.NextSibling.PrevSibling := nil;
  3820. FIndexNodeList.Remove(Node);
  3821. Node.Free;
  3822. end;
  3823. var
  3824. I, iIdx, iKey: Integer;
  3825. Node, Parent: TsdIndexNode;
  3826. begin
  3827. iIdx := FDataList.IndexOf(ARecord);
  3828. if iIdx < 0 then Exit;
  3829. // 获得记录所属索引节点(最底层节点)
  3830. iKey := FindExistKeyIndex(iIdx);
  3831. if iKey < 0 then
  3832. raise EsdIndex.Create(Format('Index error: Can not find key, index(%d)', [iIdx]));
  3833. if iKey >= 0 then
  3834. begin
  3835. Node := TsdIndexNode(FIndexNodeList[iKey]);
  3836. // 只有一条数据记录,则直接删除索引记录
  3837. if FDataList.Count = 1 then
  3838. Clear
  3839. // 不止一条数据记录
  3840. else
  3841. begin
  3842. // 且只有一条索引记录,则不需处理; 处理有多条索引记录
  3843. if FIndexNodeList.Count > 1 then
  3844. begin
  3845. // 当前索引记录只包含一条数据记录
  3846. if Node.RecordCount = 1 then
  3847. begin
  3848. Parent := Node.Parent;
  3849. // 移除索引记录
  3850. DeleteNode(Node);
  3851. // 父项如果没有子节点,也要移除
  3852. while (Parent <> FIndexRoot) and (Parent.ChildCount = 0) do
  3853. begin
  3854. Node := Parent;
  3855. Parent := Parent.Parent;
  3856. DeleteNode(Node);
  3857. // 2016-09-15 删除了父节点也要将iKey减1
  3858. Dec(iKey);
  3859. end;
  3860. // 维护受影响的索引记录
  3861. for I := iKey to FIndexNodeList.Count - 1 do
  3862. Dec(TsdIndexNode(FIndexNodeList[I]).FRecIndex);
  3863. end
  3864. // 指定数据记录不是当前索引记录的唯一记录
  3865. else
  3866. begin
  3867. // 维护受影响的索引记录
  3868. if iKey < FIndexNodeList.Count - 1 then
  3869. for I := iKey + 1 to FIndexNodeList.Count - 1 do
  3870. Dec(TsdIndexNode(FIndexNodeList[I]).FRecIndex);
  3871. end;
  3872. end;
  3873. end;
  3874. end;
  3875. FDataList.Remove(ARecord);
  3876. end;
  3877. procedure TsdIndex.Sort;
  3878. procedure QuickSort(iLo, iHi: Integer);
  3879. var
  3880. Lo, Hi: Integer;
  3881. MidRec: TsdDataRecord;
  3882. begin
  3883. Lo := iLo;
  3884. Hi := iHi;
  3885. MidRec := TsdDataRecord(FDataList[(iLo + iHi) div 2]);
  3886. repeat
  3887. while CompareData(TsdDataRecord(FDataList[Lo]), MidRec) < 0 do
  3888. Inc(Lo);
  3889. while CompareData(TsdDataRecord(FDataList[Hi]), MidRec) > 0 do
  3890. Dec(Hi);
  3891. if Lo <= Hi then
  3892. begin
  3893. if Lo < Hi then begin
  3894. FDataList.Exchange(Lo, Hi);
  3895. end;
  3896. Inc(Lo);
  3897. Dec(Hi);
  3898. end;
  3899. until Lo > Hi;
  3900. if Hi > iLo then QuickSort(iLo, Hi);
  3901. if Lo < iHi then QuickSort(Lo, iHi);
  3902. end;
  3903. var
  3904. I, J: Integer;
  3905. vData: Variant;
  3906. DataType: TFieldType;
  3907. PeriodNode, PrevNode, Node: TsdIndexNode;
  3908. begin
  3909. Clear;
  3910. FDataList.Assign(DataSet.FDataList);
  3911. // 排序
  3912. if FDataList.Count > 0 then QuickSort(0, FDataList.Count - 1);
  3913. //GetDebugData;
  3914. // 生成索引树
  3915. PeriodNode := FIndexRoot;
  3916. for I := 0 to FDataList.Count - 1 do
  3917. begin
  3918. for J := 0 to LevelCount - 1 do
  3919. begin
  3920. vData := GetValue(TsdDataRecord(FDataList[I]), J);
  3921. DataType := TsdField(FFieldList[J]).DataType;
  3922. // 获取当前节点的前兄弟节点
  3923. // 当前节点与前一节点同层
  3924. if J = PeriodNode.Level then
  3925. PrevNode := PeriodNode
  3926. // 当前节点比前一节点层次高
  3927. else if J < PeriodNode.Level then
  3928. begin
  3929. PrevNode := PeriodNode;
  3930. repeat
  3931. PrevNode := PrevNode.Parent;
  3932. until J = PrevNode.Level;
  3933. end
  3934. // 当前节点比前一节点层次低
  3935. else
  3936. PrevNode := nil;
  3937. // 前一节点是父节点 或 前兄弟节点值有变化 则建立新节点
  3938. if (PrevNode = nil) or (CompareValue(PrevNode.Value, vData) <> 0) then
  3939. begin
  3940. Node := TsdIndexNode.Create(Self);
  3941. // 前一节点是前面分支的子节点(<) 或 是兄弟节点(=)
  3942. if J <= PeriodNode.Level then
  3943. begin
  3944. Node.Parent := PrevNode.Parent;
  3945. Node.PrevSibling := PrevNode;
  3946. PrevNode.NextSibling := Node;
  3947. end
  3948. // 前一节点是父节点
  3949. else if J = PeriodNode.Level + 1 then
  3950. begin
  3951. Node.Parent := PeriodNode;
  3952. PeriodNode.FirstChild := Node;
  3953. end
  3954. else
  3955. begin
  3956. Node.Free;
  3957. raise EsdIndex.Create('Sort index error');
  3958. end;
  3959. Node.RecIndex := I;
  3960. Node.Value := vData;
  3961. Node.DataType := DataType;
  3962. FIndexNodeList.Add(Node);
  3963. PeriodNode := Node;
  3964. end;
  3965. end;
  3966. end;
  3967. FChangedList.Clear;
  3968. GetDebugData;
  3969. end;
  3970. (*function TsdIndex.FindKeyIndex(AValue: Variant; ALevel: Integer): Integer;
  3971. var
  3972. KeyList: TList;
  3973. iLow, iHigh, iIndex: Integer;
  3974. begin
  3975. Result := -1;
  3976. KeyList := TList(FIndexNodeList[ALevel]);
  3977. iLow := 0;
  3978. iHigh := KeyList.Count - 1;
  3979. if KeyList.Count = 0 then
  3980. begin
  3981. //Result:= 0;
  3982. Exit;
  3983. end;
  3984. // 二分法查找给定KeyID节点的序号
  3985. while iLow <= iHigh do
  3986. begin
  3987. iIndex := (iLow + iHigh) div 2;
  3988. if PsdIndexData(KeyList[iIndex])^.Value = AValue then
  3989. begin
  3990. Result := iIndex;
  3991. Break;
  3992. end
  3993. else if PsdIndexData(KeyList[iIndex])^.Value < AValue then
  3994. iLow := iIndex + 1
  3995. else
  3996. iHigh := iIndex - 1;
  3997. end;
  3998. end; *)
  3999. procedure TsdIndex.GetDebugData;
  4000. var
  4001. I: Integer;
  4002. sdRec: TsdDataRecord;
  4003. Node: TsdIndexNode;
  4004. Log: TStringList;
  4005. begin
  4006. (* if LevelCount < 1 then Exit;
  4007. Log := TStringList.Create;
  4008. Log.Add(Format('Sort Data: %d', [FDataList.Count]));
  4009. Log.Add('I, ParentID, ID');
  4010. for I := 0 to FDataList.Count - 1 do
  4011. begin
  4012. sdRec := TsdDataRecord(FDataList[I]);
  4013. Log.Add(Format('%d, %s, %s', [I, sdRec.ValueByName('ParentNodeID').AsString, sdRec.ValueByName('NodeID').AsString]));
  4014. end;
  4015. Log.Add(Format('Node Data: %d', [FIndexNodeList.Count]));
  4016. Log.Add('I, Value, Level, ChildCount, RecIndex');
  4017. for I := 0 to FIndexNodeList.Count - 1 do
  4018. begin
  4019. Node := TsdIndexNode(FIndexNodeList[I]);
  4020. sdRec := TsdDataRecord(FDataList[Node.RecIndex]);
  4021. Log.Add(Format('%d, %d, %d, %d, %d, %d', [I, sdVarToInteger(Node.Value),
  4022. Node.Level, Node.ChildCount, Node.RecIndex, sdRec.ValueByName('NodeID').AsInteger]));
  4023. end;
  4024. Log.SaveToFile('E:\Temp\1.log');
  4025. Log.Free; *)
  4026. end;
  4027. procedure TsdIndex.SetFieldNames(const Value: string);
  4028. begin
  4029. FFieldNames := Value;
  4030. ParseFields;
  4031. if DataSet.Active then
  4032. Sort;
  4033. end;
  4034. procedure TsdIndex.ParseFields;
  4035. var
  4036. NameList: TStringList;
  4037. I: Integer;
  4038. Field: TsdField;
  4039. begin
  4040. FFieldList.Clear;
  4041. NameList := TStringList.Create;
  4042. try
  4043. NameList.Delimiter := ';';
  4044. NameList.DelimitedText := FFieldNames;
  4045. for I := 0 to NameList.Count - 1 do
  4046. begin
  4047. Field := DataSet.FFieldList.FieldByName(Trim(NameList[I]));
  4048. if Field = nil then
  4049. begin
  4050. FFieldList.Clear;
  4051. raise EsdIndex.Create(Format('Can not find field ''%s''', [NameList[I]]));
  4052. end;
  4053. FFieldList.Add(Field);
  4054. end;
  4055. finally
  4056. NameList.Free;
  4057. end;
  4058. end;
  4059. function TsdIndex.GetLevelCount: Integer;
  4060. begin
  4061. Result := FFieldList.Count;
  4062. end;
  4063. function TsdIndex.FindKeyIndex(KeyValues: Variant): Integer;
  4064. var
  4065. Node: TsdIndexNode;
  4066. begin
  4067. Result := -1;
  4068. Node := FindIndexNode(KeyValues);
  4069. if Node <> nil then
  4070. Result := Node.RecIndex;
  4071. end;
  4072. function TsdIndex.FindKeyLastIndex(KeyValues: Variant): Integer;
  4073. var
  4074. Node: TsdIndexNode;
  4075. begin
  4076. Result := -1;
  4077. Node := FindIndexNode(KeyValues);
  4078. if Node <> nil then
  4079. Result := Node.RecIndex + Node.RecordCount - 1;
  4080. end;
  4081. { function FindIndexNode(Value: Variant; Parent: TsdIndexNode): TsdIndexNode;
  4082. var
  4083. Node: TsdIndexNode;
  4084. begin
  4085. Result := nil;
  4086. Node := Parent.FirstChild;
  4087. while Node <> nil do
  4088. begin
  4089. // 若索引节点值大于目标值,则直接退出
  4090. if CompareValue(Node.Value, Value) > 0 then Break;
  4091. if CompareValue(Node.Value, Value) = 0 then
  4092. begin
  4093. Result := Node;
  4094. Break;
  4095. end;
  4096. Node := Node.NextSibling;
  4097. end;
  4098. end;
  4099. var
  4100. KeyCount, I: Integer;
  4101. V: Variant;
  4102. KeyNode: TsdIndexNode;
  4103. begin
  4104. Result := -1;
  4105. if VarIsArray(KeyValues) then
  4106. KeyCount := VarArrayHighBound(KeyValues, 1) - VarArrayLowBound(KeyValues, 1)
  4107. else
  4108. KeyCount := 1;
  4109. if KeyCount > LevelCount then KeyCount := LevelCount;
  4110. KeyNode := FIndexRoot;
  4111. for I := 0 to KeyCount - 1 do
  4112. begin
  4113. if VarIsArray(KeyValues) then
  4114. V := KeyValues[I]
  4115. else
  4116. V := KeyValues;
  4117. KeyNode := FindIndexNode(V, KeyNode);
  4118. if KeyNode = nil then
  4119. Exit;
  4120. end;
  4121. Result := KeyNode.RecIndex;
  4122. end;}
  4123. function TsdIndex.FindKey(KeyValues: Variant): TsdDataRecord;
  4124. begin
  4125. Result := Records[FindKeyIndex(KeyValues)];
  4126. end;
  4127. procedure TsdIndex.SetName(const Value: string);
  4128. begin
  4129. if FOwner.FindByName(Value) <> nil then
  4130. raise EsdIndex.Create(Format('Index "%s" exists', [Value]));
  4131. FName := Value;
  4132. end;
  4133. function TsdIndex.SameKeyFields(AFieldNames: string): Boolean;
  4134. var
  4135. NameList: TStringList;
  4136. I: Integer;
  4137. Field: TsdField;
  4138. begin
  4139. Result := True;
  4140. NameList := TStringList.Create;
  4141. try
  4142. NameList.Delimiter := ';';
  4143. NameList.DelimitedText := AFieldNames;
  4144. if NameList.Count > LevelCount then
  4145. begin
  4146. Result := False;
  4147. Exit;
  4148. end;
  4149. for I := 0 to NameList.Count - 1 do
  4150. begin
  4151. Field := TsdField(FFieldList[I]);
  4152. if not SameText(Field.FieldName, Trim(NameList[I])) then
  4153. begin
  4154. Result := False;
  4155. Break;
  4156. end;
  4157. end;
  4158. finally
  4159. NameList.Free;
  4160. end;
  4161. end;
  4162. function TsdIndex.GetDataSet: TsdDataSet;
  4163. begin
  4164. Result := FOwner.FOwner;
  4165. end;
  4166. function TsdIndex.HasKeyFields(AFieldNames: string): Boolean;
  4167. var
  4168. NameList: TStringList;
  4169. I, KeyCount: Integer;
  4170. Field: TsdField;
  4171. begin
  4172. Result := True;
  4173. NameList := TStringList.Create;
  4174. try
  4175. NameList.Delimiter := ';';
  4176. NameList.DelimitedText := AFieldNames;
  4177. if NameList.Count > LevelCount then
  4178. begin
  4179. Result := False;
  4180. Exit;
  4181. end;
  4182. if NameList.Count < LevelCount then
  4183. KeyCount := NameList.Count
  4184. else
  4185. KeyCount := LevelCount;
  4186. for I := 0 to KeyCount - 1 do
  4187. begin
  4188. Field := TsdField(FFieldList[I]);
  4189. if not SameText(Field.FieldName, Trim(NameList[I])) then
  4190. begin
  4191. Result := False;
  4192. Break;
  4193. end;
  4194. end;
  4195. finally
  4196. NameList.Free;
  4197. end;
  4198. end;
  4199. function TsdIndex.CompareValue(const AValue1, AValue2: Variant): Integer;
  4200. var
  4201. V1, V2: Variant;
  4202. VType1, VType2: TVarType;
  4203. begin
  4204. // 为空的值可选择是否排到最后,方便表格显示
  4205. if FSortNullToLast and (VarIsNull(AValue1) or VarIsNull(AValue2)) or (VarToStr(AValue1) = '') or (VarToStr(AValue2) = '') then
  4206. begin
  4207. if (VarIsNull(AValue1) or (VarToStr(AValue1) = '')) and (not (VarIsNull(AValue2) or (VarToStr(AValue2) = ''))) then
  4208. Result := 1
  4209. else if (not (VarIsNull(AValue1) or (VarToStr(AValue1) = ''))) and (VarIsNull(AValue2) or (VarToStr(AValue2) = '')) then
  4210. Result := -1
  4211. else
  4212. Result := 0;
  4213. end
  4214. else
  4215. begin
  4216. // 处理两个值类型不一样的情况。暂时只遇到一个为字符串的情况,只处理这个
  4217. V1 := AValue1;
  4218. V2 := AValue2;
  4219. VType1 := VarType(V1);
  4220. VType2 := VarType(V2);
  4221. if (VType1 <> VType2) and ((VType1 = varString) or (VType2 = varString)) then
  4222. begin
  4223. V1 := VarToStr(V1);
  4224. V2 := VarToStr(V2);
  4225. end;
  4226. if not FDescend then
  4227. begin
  4228. // Result: 0: 1 = 2 >0: 1 > 2 <0: 1 < 2
  4229. if V1 > V2 then
  4230. Result := 1
  4231. else if V1 < V2 then
  4232. Result := -1
  4233. else
  4234. Result := 0;
  4235. end
  4236. else
  4237. begin
  4238. // Result: 0: 1 = 2 >0: 1 < 2 <0: 1 > 2
  4239. if V1 > V2 then
  4240. Result := -1
  4241. else if V1 < V2 then
  4242. Result := 1
  4243. else
  4244. Result := 0;
  4245. end;
  4246. end;
  4247. end;
  4248. procedure TsdIndex.SetDescend(const Value: Boolean);
  4249. begin
  4250. FDescend := Value;
  4251. end;
  4252. procedure TsdIndex.AssignRecords(AList: TList);
  4253. begin
  4254. AList.Assign(FDataList);
  4255. end;
  4256. function TsdIndex.FindNearestKeyIndex(KeyValues: Variant; var RecIndex: Integer;
  4257. AIsEnd: Boolean): TsdIndexFlag;
  4258. function FindIndexNode(Value: Variant; Parent: TsdIndexNode; var AFlag: TsdIndexFlag): TsdIndexNode;
  4259. var
  4260. Node: TsdIndexNode;
  4261. begin
  4262. Result := nil;
  4263. AFlag := sifFoundIndex;
  4264. Node := Parent.FirstChild;
  4265. if Node = nil then
  4266. begin
  4267. AFlag := sifNull;
  4268. Exit;
  4269. end;
  4270. // 若目标值小于第一个索引子节点值,则说明目标值小于所有索引值,返回空
  4271. if CompareValue(Value, Node.Value) < 0 then
  4272. begin
  4273. AFlag := sifLessThanMin;
  4274. Exit;
  4275. end;
  4276. Node := Parent.LastChild;
  4277. // 若目标值大于最后一个索引子节点值,则说明目标值大于所有索引值,返回最后节点
  4278. if CompareValue(Value, Node.Value) > 0 then
  4279. begin
  4280. Result := Node;
  4281. AFlag := sifMoreThanMax;
  4282. Exit;
  4283. end;
  4284. Node := Parent.FirstChild;
  4285. while Node <> nil do
  4286. begin
  4287. if CompareValue(Node.Value, Value) = 0 then
  4288. begin
  4289. Result := Node;
  4290. Break;
  4291. end
  4292. // 若索引节点值大于目标值,则说明前面无相同值,返回最接近节点(前一个节点)
  4293. else if CompareValue(Node.Value, Value) > 0 then
  4294. begin
  4295. Result := Node.PrevSibling;
  4296. AFlag := sifInTheMid;
  4297. Break;
  4298. end;
  4299. Node := Node.NextSibling;
  4300. end;
  4301. end;
  4302. var
  4303. KeyCount, I: Integer;
  4304. V: Variant;
  4305. KeyNode, ParentNode: TsdIndexNode;
  4306. Flag: TsdIndexFlag;
  4307. begin
  4308. Result := sifInTheMid;
  4309. RecIndex := -1;
  4310. if VarIsArray(KeyValues) then
  4311. KeyCount := VarArrayHighBound(KeyValues, 1) - VarArrayLowBound(KeyValues, 1) + 1
  4312. else
  4313. KeyCount := 1;
  4314. if KeyCount > LevelCount then KeyCount := LevelCount;
  4315. KeyNode := FIndexRoot;
  4316. Flag := sifFoundIndex;
  4317. for I := 0 to KeyCount - 1 do
  4318. begin
  4319. if VarIsArray(KeyValues) then
  4320. V := KeyValues[I]
  4321. else
  4322. V := KeyValues;
  4323. ParentNode := KeyNode;
  4324. KeyNode := FindIndexNode(V, KeyNode, Flag);
  4325. case Flag of
  4326. sifLessThanMin:
  4327. begin
  4328. // 如果是第二层及以下比最小值小,则返回父节点,并设置Flag为已找到
  4329. if I > 0 then
  4330. begin
  4331. Flag := sifFoundIndex;
  4332. KeyNode := ParentNode;
  4333. end;
  4334. Break;
  4335. end;
  4336. sifFoundIndex:
  4337. begin
  4338. // do nothing
  4339. end;
  4340. sifInTheMid:
  4341. begin
  4342. // 在中间,则KeyNode是前一个节点,返回前一个节点的最后后代节点
  4343. if KeyNode.FirstChild <> nil then
  4344. KeyNode := KeyNode.LastPosterity;
  4345. Break;
  4346. end;
  4347. sifMoreThanMax:
  4348. begin
  4349. // 比最大更大,返回父节点的最后后代节点
  4350. KeyNode := ParentNode.LastPosterity;
  4351. Break;
  4352. end;
  4353. sifNull:
  4354. begin
  4355. // 如果是空且是第二层及以下,则返回父节点,并设置Flag为已找到
  4356. if I > 0 then
  4357. begin
  4358. Flag := sifFoundIndex;
  4359. KeyNode := ParentNode;
  4360. end;
  4361. Break;
  4362. end;
  4363. end;
  4364. // 如果找不到指定节点
  4365. if KeyNode = nil then
  4366. begin
  4367. // 且不是第一层
  4368. if I > 0 then
  4369. Result := sifFoundIndex
  4370. else
  4371. Result := Flag;
  4372. Exit;
  4373. end;
  4374. // 只找到接近节点,且有子节点,则最接近的子节点是其最后一个子节点
  4375. if Flag <> sifFoundIndex then
  4376. begin
  4377. if KeyNode.FirstChild <> nil then
  4378. KeyNode := KeyNode.LastPosterity;
  4379. Break;
  4380. end;
  4381. RecIndex := KeyNode.RecIndex;
  4382. end;
  4383. Result := Flag;
  4384. case Result of
  4385. sifLessThanMin:
  4386. begin
  4387. if AIsEnd then
  4388. RecIndex := -1
  4389. else
  4390. RecIndex := 0;
  4391. end;
  4392. sifFoundIndex:
  4393. begin
  4394. // 如AIsEnd=True,返回包含本节点记录数的最后一个索引值
  4395. if AIsEnd then
  4396. RecIndex := KeyNode.RecIndex + KeyNode.RecordCount - 1
  4397. else
  4398. RecIndex := KeyNode.RecIndex;
  4399. end;
  4400. sifInTheMid:
  4401. begin
  4402. if AIsEnd then
  4403. RecIndex := KeyNode.RecIndex + KeyNode.RecordCount - 1
  4404. else
  4405. RecIndex := KeyNode.RecIndex + KeyNode.RecordCount;
  4406. end;
  4407. sifMoreThanMax:
  4408. begin
  4409. if AIsEnd then
  4410. RecIndex := KeyNode.RecIndex + KeyNode.RecordCount - 1
  4411. else
  4412. RecIndex := KeyNode.RecIndex + KeyNode.RecordCount;
  4413. end;
  4414. sifNull:
  4415. begin
  4416. RecIndex := -1;
  4417. end;
  4418. end;
  4419. end;
  4420. function TsdIndex.GetFields(Index: Integer): TsdField;
  4421. begin
  4422. Result := TsdField(FFieldList[Index]);
  4423. end;
  4424. function TsdIndex.IndexOf(ARecord: TsdDataRecord): Integer;
  4425. begin
  4426. Result := FDataList.IndexOf(ARecord);
  4427. end;
  4428. function TsdIndex.Exchange(const Index1, Index2: Integer): Integer;
  4429. var
  4430. Rec1, Rec2: TsdDataRecord;
  4431. begin
  4432. Rec1 := Records[Index1];
  4433. Rec2 := Records[Index2];
  4434. Result := Exchange(Rec1, Rec2);
  4435. end;
  4436. function TsdIndex.Exchange(ARecord1, ARecord2: TsdDataRecord): Integer;
  4437. var
  4438. I: Integer;
  4439. vKey1, vKey2: array of Variant;
  4440. begin
  4441. SetLength(vKey1, LevelCount);
  4442. SetLength(vKey2, LevelCount);
  4443. for I := 0 to LevelCount - 1 do
  4444. begin
  4445. vKey1[I] := GetValue(ARecord1, I);
  4446. vKey2[I] := GetValue(ARecord2, I);
  4447. end;
  4448. ARecord1.BeginUpdate;
  4449. for I := 0 to LevelCount - 1 do
  4450. ARecord1.ValueByName(Fields[I].FieldName).AsVariant := vKey2[I];
  4451. ARecord1.EndUpdate;
  4452. ARecord2.BeginUpdate;
  4453. for I := 0 to LevelCount - 1 do
  4454. ARecord2.ValueByName(Fields[I].FieldName).AsVariant := vKey1[I];
  4455. ARecord2.EndUpdate;
  4456. Result := IndexOf(ARecord1);
  4457. end;
  4458. function TsdIndex.Insert(ARecord: TsdDataRecord; Index: Integer): Integer;
  4459. begin
  4460. FDataList.Insert(Index, ARecord);
  4461. Result := IndexOf(ARecord);
  4462. end;
  4463. procedure TsdIndex.LoadProperty(Reader: TReader);
  4464. var
  4465. PropName: string;
  4466. v: Variant;
  4467. begin
  4468. Reader.ReadListBegin;
  4469. while not Reader.EndOfList do
  4470. begin
  4471. PropName := Reader.ReadStr;
  4472. v := Reader.ReadVariant;
  4473. if GetPropInfo(Self, PropName) <> nil then
  4474. SetPropValue(Self, PropName, v);
  4475. end;
  4476. Reader.ReadListEnd;
  4477. end;
  4478. procedure TsdIndex.SaveProperty(Writer: TWriter);
  4479. procedure WriteProp(const AName: string; AValue: Variant);
  4480. begin
  4481. Writer.WriteStr(AName);
  4482. Writer.WriteVariant(AValue);
  4483. end;
  4484. begin
  4485. Writer.WriteListBegin;
  4486. WriteProp('Name', Name);
  4487. WriteProp('FieldNames', FieldNames);
  4488. Writer.WriteListEnd;
  4489. end;
  4490. function TsdIndex.RecordsByKey(KeyValues: Variant; List: TList): Integer;
  4491. var
  4492. iPos, I: Integer;
  4493. IndexNode: TsdIndexNode;
  4494. Rec: TsdDataRecord;
  4495. begin
  4496. Result := 0;
  4497. List.Clear;
  4498. if not VarIsNull(KeyValues) then
  4499. begin
  4500. Rec := FindKey(KeyValues);
  4501. if Rec = nil then Exit;
  4502. iPos := IndexOf(Rec);
  4503. IndexNode := FindIndexNode(KeyValues);
  4504. repeat
  4505. List.Add(Rec);
  4506. Inc(iPos);
  4507. Rec := Records[iPos];
  4508. if (Rec <> nil) and (not IndexNode.HasRecord(Rec)) then
  4509. Break;
  4510. until Rec = nil;
  4511. end
  4512. else
  4513. List.Assign(FDataList);
  4514. Result := List.Count;
  4515. end;
  4516. function TsdIndex.RecordCountByKey(KeyValues: Variant): Integer;
  4517. var
  4518. IndexNode: TsdIndexNode;
  4519. begin
  4520. Result := 0;
  4521. if not VarIsNull(KeyValues) then
  4522. begin
  4523. IndexNode := FindIndexNode(KeyValues);
  4524. // 如果DataSet.IsUpdating,索引不刷新,这里可能为nil
  4525. if IndexNode <> nil then
  4526. Result := IndexNode.RecordCount;
  4527. end;
  4528. end;
  4529. function TsdIndex.FindIndexNode(KeyValues: Variant): TsdIndexNode;
  4530. // 来自TStringList.Find的二分查找代码,精妙简洁,略带炫技
  4531. function QuickFind(Value: Variant; Parent: TsdIndexNode; const iLo, iHi: Integer): TsdIndexNode;
  4532. var
  4533. Lo, Hi, Mid, iResult: Integer;
  4534. Node, MidNode: TsdIndexNode;
  4535. begin
  4536. Result := nil;
  4537. Lo := iLo;
  4538. Hi := iHi;
  4539. while Lo <= Hi do
  4540. begin
  4541. Mid := (Lo + Hi) shr 1;
  4542. MidNode := Parent.Children[Mid];
  4543. iResult := CompareValue(MidNode.Value, Value);
  4544. if iResult < 0 then
  4545. Lo := Mid + 1
  4546. else
  4547. begin
  4548. Hi := Mid - 1;
  4549. if iResult = 0 then
  4550. Result := MidNode;
  4551. end;
  4552. end;
  4553. end;
  4554. function FindNode(Value: Variant; Parent: TsdIndexNode): TsdIndexNode;
  4555. begin
  4556. // 二分查找
  4557. Result := QuickFind(Value, Parent, 0, Parent.ChildCount - 1);
  4558. end;
  4559. var
  4560. iKeyCount, I: Integer;
  4561. V: Variant;
  4562. KeyNode: TsdIndexNode;
  4563. begin
  4564. Result := nil;
  4565. iKeyCount := KeyCount(KeyValues);
  4566. KeyNode := FIndexRoot;
  4567. for I := 0 to iKeyCount - 1 do
  4568. begin
  4569. if VarIsArray(KeyValues) then
  4570. V := KeyValues[I]
  4571. else
  4572. V := KeyValues;
  4573. KeyNode := FindNode(V, KeyNode);
  4574. if KeyNode = nil then
  4575. Exit;
  4576. end;
  4577. Result := KeyNode;
  4578. end;
  4579. function TsdIndex.KeyCount(KeyValues: Variant): Integer;
  4580. begin
  4581. Result := 0;
  4582. if VarIsArray(KeyValues) then
  4583. Result := VarArrayHighBound(KeyValues, 1) - VarArrayLowBound(KeyValues, 1) + 1
  4584. else
  4585. Result := 1;
  4586. if Result > LevelCount then Result := LevelCount;
  4587. end;
  4588. function TsdIndex.IsKeyField(AFieldName: string): Boolean;
  4589. var
  4590. I: Integer;
  4591. begin
  4592. Result := False;
  4593. for I := 0 to LevelCount - 1 do
  4594. if SameText(AFieldName, Fields[I].FieldName) then
  4595. begin
  4596. Result := True;
  4597. Break;
  4598. end;
  4599. end;
  4600. function TsdIndex.GetRecordCount: Integer;
  4601. begin
  4602. Result := FDataList.Count;
  4603. end;
  4604. procedure TsdIndex.Delete(ARecord: TsdDataRecord);
  4605. begin
  4606. InnerDelete(ARecord);
  4607. FChangedList.Remove(ARecord);
  4608. end;
  4609. procedure TsdIndex.AddChangedRecord(ARecord: TsdDataRecord);
  4610. begin
  4611. if FChangedList.IndexOf(ARecord) < 0 then
  4612. FChangedList.Add(ARecord);
  4613. end;
  4614. function TsdIndex.CompareIndex(ARec1, ARec2: TsdDataRecord): Integer;
  4615. begin
  4616. if ARec1.FIndex > ARec2.FIndex then Result := 1
  4617. else if ARec1.FIndex < ARec2.FIndex then Result := -1
  4618. else Result := 0;
  4619. end;
  4620. { TsdIndexList }
  4621. function TsdIndexList.Add: TsdIndex;
  4622. begin
  4623. Result := TsdIndex.Create(Self);
  4624. FList.Add(Result);
  4625. //Result.GetDebugData;
  4626. end;
  4627. procedure TsdIndexList.Check(ARecord: TsdDataRecord);
  4628. var
  4629. I: Integer;
  4630. begin
  4631. for I := 0 to FList.Count - 1 do
  4632. Items[I].Check(ARecord);
  4633. end;
  4634. procedure TsdIndexList.Clear;
  4635. var
  4636. I: Integer;
  4637. begin
  4638. while FList.Count > 0 do
  4639. begin
  4640. Items[0].Free;
  4641. FList.Delete(0);
  4642. end;
  4643. end;
  4644. procedure TsdIndexList.ClearData;
  4645. var
  4646. I: Integer;
  4647. begin
  4648. for I := 0 to FList.Count - 1 do
  4649. Items[I].Clear;
  4650. end;
  4651. constructor TsdIndexList.Create(AOwner: TsdDataSet);
  4652. begin
  4653. FOwner := AOwner;
  4654. FList := TList.Create;
  4655. end;
  4656. procedure TsdIndexList.Delete(Name: string);
  4657. var
  4658. Index: TsdIndex;
  4659. begin
  4660. Index := FindByName(Name);
  4661. FList.Remove(Index);
  4662. FreeAndNil(Index);
  4663. end;
  4664. procedure TsdIndexList.Delete(Index: TsdIndex);
  4665. begin
  4666. if FList.Remove(Index) >= 0 then
  4667. FreeAndNil(Index);
  4668. end;
  4669. procedure TsdIndexList.DeleteRecord(ARecord: TsdDataRecord);
  4670. var
  4671. I: Integer;
  4672. begin
  4673. for I := 0 to FList.Count - 1 do
  4674. Items[I].Delete(ARecord);
  4675. end;
  4676. destructor TsdIndexList.Destroy;
  4677. begin
  4678. Clear;
  4679. FList.Free;
  4680. inherited;
  4681. end;
  4682. procedure TsdIndexList.Exchange(Index1, Index2: TsdIndex);
  4683. var
  4684. idx1, idx2: Integer;
  4685. begin
  4686. idx1 := FList.IndexOf(Index1);
  4687. idx2 := FList.IndexOf(Index2);
  4688. if idx1 < 0 then
  4689. raise EsdDataSet.Create(Format('DataSet do not own field "%s"', [Index1.Name]));
  4690. if idx2 < 0 then
  4691. raise EsdDataSet.Create(Format('DataSet do not own field "%s"', [Index2.Name]));
  4692. FList.Exchange(idx1, idx2);
  4693. end;
  4694. function TsdIndexList.FindByKeyFields(KeyFields: string;
  4695. Partial: Boolean): TsdIndex;
  4696. var
  4697. I: Integer;
  4698. Index: TsdIndex;
  4699. begin
  4700. Result := nil;
  4701. for I := 0 to FList.Count - 1 do
  4702. begin
  4703. Index := Items[I];
  4704. if Partial then
  4705. begin
  4706. if Index.HasKeyFields(KeyFields) then
  4707. begin
  4708. Result := Index;
  4709. Break;
  4710. end;
  4711. end
  4712. else
  4713. if Index.SameKeyFields(KeyFields) then
  4714. begin
  4715. Result := Index;
  4716. Break;
  4717. end;
  4718. end;
  4719. end;
  4720. function TsdIndexList.FindByName(Name: string): TsdIndex;
  4721. var
  4722. I: Integer;
  4723. Index: TsdIndex;
  4724. begin
  4725. Result := nil;
  4726. if Name = '' then Exit;
  4727. for I := 0 to FList.Count - 1 do
  4728. begin
  4729. Index := Items[I];
  4730. if SameText(Name, Index.Name) then
  4731. begin
  4732. Result := Index;
  4733. Break;
  4734. end;
  4735. end;
  4736. end;
  4737. function TsdIndexList.GetCount: Integer;
  4738. begin
  4739. Result := FList.Count;
  4740. end;
  4741. function TsdIndexList.GetItems(I: Integer): TsdIndex;
  4742. begin
  4743. Result := TsdIndex(FList[I]);
  4744. end;
  4745. function TsdIndexList.IsKeyField(AFieldName: string): Boolean;
  4746. var
  4747. I: Integer;
  4748. begin
  4749. Result := False;
  4750. for I := 0 to FList.Count - 1 do
  4751. if Items[I].IsKeyField(AFieldName) then
  4752. begin
  4753. Result := True;
  4754. Break;
  4755. end;
  4756. end;
  4757. procedure TsdIndexList.Sort;
  4758. var
  4759. I: Integer;
  4760. begin
  4761. for I := 0 to FList.Count - 1 do
  4762. Items[I].Sort;
  4763. end;
  4764. { TsdField }
  4765. procedure TsdField.AddLookupCol(AViewCol: TsdViewColumn);
  4766. begin
  4767. if FLookupList.IndexOf(AViewCol) < 0 then
  4768. FLookupList.Add(AViewCol);
  4769. end;
  4770. procedure TsdField.ClearLookupDataSet;
  4771. var
  4772. I: Integer;
  4773. begin
  4774. for I := 0 to FLookupList.Count - 1 do
  4775. TsdViewColumn(FLookupList[I]).FLookupDataSet := nil;
  4776. end;
  4777. procedure TsdField.ClearLookupField;
  4778. var
  4779. I: Integer;
  4780. begin
  4781. for I := 0 to FLookupList.Count - 1 do
  4782. TsdViewColumn(FLookupList[I]).FLookupField := nil;
  4783. end;
  4784. constructor TsdField.Create(AOwner: TsdFieldList);
  4785. begin
  4786. FOwner := AOwner;
  4787. FDataType := ftUnknown;
  4788. FIsKey := False;
  4789. FNeedProcessName := False;
  4790. FInnerValidChars := [#0..#255];
  4791. FValidChars := [];
  4792. FLookupList := TList.Create;
  4793. end;
  4794. destructor TsdField.Destroy;
  4795. begin
  4796. ClearLookupField;
  4797. FLookupList.Free;
  4798. inherited;
  4799. end;
  4800. function TsdField.GetDataSet: TsdDataSet;
  4801. begin
  4802. Result := FOwner.FDataSet;
  4803. end;
  4804. function TsdField.GetDataSize: Integer;
  4805. begin
  4806. case FDataType of
  4807. ftUnknown, ftString, ftWideString, ftMemo: Result := FDataSize;
  4808. ftSmallint: Result := SizeOf(SmallInt);
  4809. ftInteger: Result := SizeOf(Integer);
  4810. ftWord: Result := SizeOf(Word);
  4811. ftBoolean: Result := SizeOf(Boolean);
  4812. ftFloat: Result := SizeOf(Double);
  4813. ftCurrency, ftBCD: Result := SizeOf(Currency);
  4814. ftFMTBCD: Result := SizeOf(TBCD);
  4815. ftDateTime: Result := SizeOf(TDateTime);
  4816. else
  4817. Result := FDataSize;
  4818. end;
  4819. end;
  4820. function TsdField.GetFieldNo: Integer;
  4821. begin
  4822. Result := FOwner.FList.IndexOf(Self);
  4823. end;
  4824. function TsdField.HasLookup: Boolean;
  4825. begin
  4826. Result := FLookupList.Count > 0;
  4827. end;
  4828. function TsdField.IsBlobField: Boolean;
  4829. begin
  4830. Result := FDataType in [ftMemo];
  4831. end;
  4832. function TsdField.IsValidChar(InputChar: Char): Boolean;
  4833. begin
  4834. if ValidChars = [] then
  4835. Result := InputChar in FInnerValidChars
  4836. else
  4837. Result := InputChar in ValidChars;
  4838. end;
  4839. function TsdField.IsVarField: Boolean;
  4840. begin
  4841. Result := FDataType in [ftString, ftWideString, ftMemo];
  4842. end;
  4843. procedure TsdField.LoadProperty(Reader: TReader);
  4844. var
  4845. PropName: string;
  4846. v: Variant;
  4847. begin
  4848. Reader.ReadListBegin;
  4849. while not Reader.EndOfList do
  4850. begin
  4851. PropName := Reader.ReadStr;
  4852. v := Reader.ReadVariant;
  4853. if SameText(PropName, 'NeedProcessName') then
  4854. NeedProcessName := v
  4855. else if SameText(PropName, 'IsKey') then
  4856. IsKey := v
  4857. else if GetPropInfo(Self, PropName) <> nil then
  4858. SetPropValue(Self, PropName, v);
  4859. end;
  4860. Reader.ReadListEnd;
  4861. end;
  4862. procedure TsdField.ProcessFieldName(FieldName: string);
  4863. begin
  4864. if (DataSet.Provider = nil) or (not NeedProcessName) then Exit;
  4865. NeedProcessName := False;
  4866. DataSet.Provider.AssignField(FieldName);
  4867. end;
  4868. procedure TsdField.RefreshLookup;
  4869. var
  4870. I: Integer;
  4871. begin
  4872. for I := 0 to FLookupList.Count - 1 do
  4873. begin
  4874. TsdViewColumn(FLookupList[I]).LookupChanged;
  4875. end;
  4876. end;
  4877. procedure TsdField.RemoveLookupCol(AViewCol: TsdViewColumn);
  4878. begin
  4879. FLookupList.Remove(AViewCol);
  4880. end;
  4881. procedure TsdField.SaveProperty(Writer: TWriter);
  4882. procedure WriteProp(const AName: string; AValue: Variant);
  4883. begin
  4884. Writer.WriteStr(AName);
  4885. Writer.WriteVariant(AValue);
  4886. end;
  4887. begin
  4888. Writer.WriteListBegin;
  4889. WriteProp('Name', Name);
  4890. WriteProp('FieldName', FieldName);
  4891. WriteProp('DataType', DataType);
  4892. WriteProp('DataSize', DataSize);
  4893. WriteProp('IsKey', IsKey);
  4894. WriteProp('NeedProcessName', NeedProcessName);
  4895. WriteProp('Precision', Precision);
  4896. WriteProp('Size', Size);
  4897. Writer.WriteListEnd;
  4898. end;
  4899. procedure TsdField.SetDataSize(const Value: Integer);
  4900. begin
  4901. FDataSize := Value;
  4902. end;
  4903. procedure TsdField.SetDataType(const Value: TFieldType);
  4904. begin
  4905. if not (Value in [ftString, ftWideString, ftSmallint, ftInteger, ftWord,
  4906. ftBoolean, ftFloat,
  4907. ftCurrency, ftBCD, ftFMTBCD, ftDateTime, ftMemo]) then
  4908. raise EsdDataSet.Create(Format('Do not support data type ''%d''', [Ord(Value)]));
  4909. if FDataType <> Value then
  4910. FDataType := Value;
  4911. if Value in [ftString, ftWideString] then
  4912. FDataSize := 255
  4913. else if Value in [ftMemo] then
  4914. FDataSize := 4000;
  4915. case DataType of
  4916. ftBoolean, ftString, ftWideString, ftMemo, ftDateTime:
  4917. ;
  4918. ftSmallint, ftInteger, ftWord:
  4919. ValidChars := ['+', '-', '0'..'9'];
  4920. ftFloat:
  4921. ValidChars := [DecimalSeparator, '+', '-', '0'..'9', 'E', 'e'];
  4922. ftCurrency, ftBCD, ftFMTBCD:
  4923. ValidChars := [DecimalSeparator, '+', '-', '0'..'9'];
  4924. end;
  4925. end;
  4926. procedure TsdField.SetFieldName(const Value: string);
  4927. begin
  4928. if NeedProcessName then
  4929. ProcessFieldName(Value)
  4930. else
  4931. begin
  4932. FFieldName := Value;
  4933. Name := Value;
  4934. end;
  4935. end;
  4936. procedure TsdField.SetPrecision(const Value: Integer);
  4937. begin
  4938. FPrecision := Value;
  4939. end;
  4940. procedure TsdField.SetSize(const Value: Integer);
  4941. begin
  4942. FSize := Value;
  4943. end;
  4944. { TsdFieldList }
  4945. function TsdFieldList.Add: TsdField;
  4946. function NewName: string;
  4947. var
  4948. I, No, iTemp, iPos, iCode: Integer;
  4949. strName, strNo: string;
  4950. begin
  4951. Result := '';
  4952. if Count = 0 then
  4953. begin
  4954. Result := 'Field1';
  4955. Exit;
  4956. end;
  4957. No := 0;
  4958. for I := 0 to Count - 1 do
  4959. begin
  4960. strName := Fields[I].Name;
  4961. iPos := Length('Field');
  4962. strNo := Copy(strName, iPos + 1, Length(strName) - iPos);
  4963. Val(strNo, iTemp, iCode);
  4964. if (iCode = 0) and (iTemp > No) then
  4965. No := iTemp;
  4966. end;
  4967. Inc(No);
  4968. Result := Format('Field%d', [No]);
  4969. end;
  4970. var
  4971. NeedActive: Boolean;
  4972. begin
  4973. NeedActive := False;
  4974. if FDataSet.IsDesigning and FDataSet.Active then
  4975. begin
  4976. FDataSet.Close;
  4977. NeedActive := True;
  4978. end
  4979. else if FDataSet.Active then
  4980. raise EsdDataSet.Create('Can not add a field on a active dataset');
  4981. Result := TsdField.Create(Self);
  4982. Result.Name := NewName;
  4983. FList.Add(Result);
  4984. if NeedActive then FDataSet.Open;
  4985. end;
  4986. function TsdFieldList.Add(const FieldName: String; DataType: TFieldType;
  4987. Size: Integer): TsdField;
  4988. var
  4989. NeedActive: Boolean;
  4990. begin
  4991. NeedActive := False;
  4992. if FDataSet.IsDesigning and FDataSet.Active then
  4993. begin
  4994. FDataSet.Close;
  4995. NeedActive := True;
  4996. end
  4997. else if FDataSet.Active then
  4998. raise EsdDataSet.Create('Can not add a field on a active dataset');
  4999. Result := TsdField.Create(Self);
  5000. Result.FieldName := FieldName;
  5001. Result.DataType := DataType;
  5002. Result.DataSize := Size;
  5003. FList.Add(Result);
  5004. if NeedActive then FDataSet.Open;
  5005. end;
  5006. procedure TsdFieldList.Clear;
  5007. var
  5008. I: Integer;
  5009. begin
  5010. for I := 0 to Count - 1 do
  5011. TsdField(Fields[I]).Free;
  5012. FList.Clear;
  5013. end;
  5014. procedure TsdFieldList.ClearLookup;
  5015. var
  5016. I: Integer;
  5017. begin
  5018. for I := 0 to Count - 1 do
  5019. Fields[I].ClearLookupDataSet;
  5020. end;
  5021. constructor TsdFieldList.Create(AOwner: TsdDataSet);
  5022. begin
  5023. FDataSet := AOwner;
  5024. FList := TList.Create;
  5025. end;
  5026. function TsdFieldList.Delete(Index: Integer): Boolean;
  5027. var
  5028. Field: TsdField;
  5029. NeedActive: Boolean;
  5030. begin
  5031. Result := False;
  5032. NeedActive := False;
  5033. if FDataSet.IsDesigning and FDataSet.Active then
  5034. begin
  5035. FDataSet.Close;
  5036. NeedActive := True;
  5037. end
  5038. else if FDataSet.Active then
  5039. raise EsdDataSet.Create('Can not delete a field on a active dataset');
  5040. if (Index >= 0) and (Index <= FList.Count - 1) then
  5041. begin
  5042. Field := Fields[Index];
  5043. if Field = nil then
  5044. raise EsdDataSet.Create(Format('Can not find field No.%d', [Index]));
  5045. FList.Remove(Field);
  5046. FreeAndNil(Field);
  5047. Result := True;
  5048. end;
  5049. if NeedActive then
  5050. begin
  5051. FDataSet.FLoadDefaultFields := False;
  5052. try
  5053. FDataSet.Open;
  5054. finally
  5055. FDataSet.FLoadDefaultFields := True;
  5056. end;
  5057. end;
  5058. end;
  5059. // debug
  5060. (*var
  5061. Field: TsdField;
  5062. n: string;
  5063. debugstrs: TStringList;
  5064. debugFile: string;
  5065. begin
  5066. Result := False;
  5067. if FDataSet.IsDesigning then
  5068. FDataSet.Close
  5069. else if FDataSet.Active then
  5070. raise EsdDataSet.Create('Can not delete a field on a active dataset');
  5071. debugFile := 'E:\SmartCost\Components\SmartDataSet\Sample\deletedebug.log';
  5072. debugstrs := TStringList.Create;
  5073. if FileExists(debugFile) then
  5074. debugstrs.LoadFromFile(debugFile);
  5075. if (Index >= 0) and (Index <= FList.Count - 1) then
  5076. begin
  5077. Field := Fields[Index];
  5078. if Field = nil then
  5079. raise EsdDataSet.Create(Format('Can not find field No.%d', [Index]));
  5080. n := Field.FieldName;
  5081. debugstrs.Add(Format('1: Count(%d) - Index(%d) - %s', [FieldCount, Index, n]));
  5082. debugstrs.SaveToFile(debugFile);
  5083. FList.Remove(Field);
  5084. debugstrs.Add(Format('2: Count(%d) - Index(%d) - %s', [FieldCount, Index, n]));
  5085. debugstrs.SaveToFile(debugFile);
  5086. FreeAndNil(Field);
  5087. debugstrs.Add(Format('3: Count(%d) - Index(%d) - %s', [FieldCount, Index, n]));
  5088. debugstrs.SaveToFile(debugFile);
  5089. debugstrs.Free;
  5090. Result := True;
  5091. end;
  5092. end; *)
  5093. destructor TsdFieldList.Destroy;
  5094. begin
  5095. ClearLookup;
  5096. Clear;
  5097. FList.Free;
  5098. inherited;
  5099. end;
  5100. procedure TsdFieldList.Exchange(Field1, Field2: TsdField);
  5101. var
  5102. idx1, idx2: Integer;
  5103. NeedActive: Boolean;
  5104. begin
  5105. NeedActive := False;
  5106. if FDataSet.IsDesigning and FDataSet.Active then
  5107. begin
  5108. FDataSet.Close;
  5109. NeedActive := True;
  5110. end
  5111. else if FDataSet.Active then
  5112. raise EsdDataSet.Create('Can not exchange fields on a active dataset');
  5113. idx1 := FList.IndexOf(Field1);
  5114. idx2 := FList.IndexOf(Field2);
  5115. if idx1 < 0 then
  5116. raise EsdDataSet.Create(Format('DataSet do not own field "%s"', [Field1.FieldName]));
  5117. if idx2 < 0 then
  5118. raise EsdDataSet.Create(Format('DataSet do not own field "%s"', [Field2.FieldName]));
  5119. FList.Exchange(idx1, idx2);
  5120. if NeedActive then FDataSet.Open;
  5121. end;
  5122. function TsdFieldList.FieldByName(FieldName: string): TsdField;
  5123. var
  5124. I: Integer;
  5125. Field: TsdField;
  5126. begin
  5127. Result := nil;
  5128. if FieldName = '' then Exit;
  5129. for I := 0 to Count - 1 do
  5130. begin
  5131. Field := TsdField(Fields[I]);
  5132. if SameText(Field.FieldName, FieldName) then
  5133. begin
  5134. Result := Field;
  5135. Break;
  5136. end;
  5137. end;
  5138. end;
  5139. function TsdFieldList.GetCount: Integer;
  5140. begin
  5141. Result := FList.Count;
  5142. end;
  5143. function TsdFieldList.GetFields(Index: Integer): TsdField;
  5144. begin
  5145. Result := nil;
  5146. if (Index >= 0) and (Index <= FList.Count - 1) then
  5147. Result := TsdField(FList[Index]);
  5148. end;
  5149. { TsdDataSet }
  5150. function TsdDataSet.Add(NeedBeginUpdate: Boolean): TsdDataRecord;
  5151. begin
  5152. CheckActive;
  5153. Result := CreateRecord;
  5154. Result.SetInserting(True, NeedBeginUpdate);
  5155. try
  5156. InitRecord(Result);
  5157. AddRecord(Result, NeedBeginUpdate);
  5158. finally
  5159. if not NeedBeginUpdate then
  5160. Result.SetInserting(False, NeedBeginUpdate);
  5161. end;
  5162. end;
  5163. procedure TsdDataSet.InitRecord(ARecord: TsdDataRecord);
  5164. begin
  5165. ARecord.FRecNo := -1;
  5166. ARecord.FNew := True and (not FIsLoading);
  5167. ARecord.FNeedNotifyIndex := True and (not FIsLoading);
  5168. ARecord.FModified := False;
  5169. ARecord.FIndex := -1;
  5170. ARecord.AddFields;
  5171. end;
  5172. function TsdDataSet.AddRecord(ARecord: TsdDataRecord; NeedBeginUpdate: Boolean): Integer;
  5173. var
  5174. Allow: Boolean;
  5175. begin
  5176. Result := -1;
  5177. if NeedBeginUpdate then
  5178. ARecord.BeginUpdate;
  5179. if not FIsLoading then
  5180. begin
  5181. FHistory.BeginAdd;
  5182. ARecord.BeginUpdate;
  5183. try
  5184. Allow := True;
  5185. DoBeforeAddRecord(ARecord, Allow);
  5186. if (not Allow) or ARecord.Canceled then
  5187. begin
  5188. ARecord.Free;
  5189. ARecord := nil;
  5190. Exit;
  5191. end;
  5192. ARecord.FIndex := FDataList.Add(ARecord);
  5193. DoAfterAddRecord(ARecord);
  5194. if ARecord.Canceled then
  5195. begin
  5196. FDataList.Remove(ARecord);
  5197. ARecord.Free;
  5198. ARecord := nil;
  5199. Exit;
  5200. end;
  5201. finally
  5202. if Assigned(ARecord) then
  5203. ARecord.EndUpdate;
  5204. FHistory.EndAdd;
  5205. end;
  5206. if not ARecord.IsUpdating then
  5207. begin
  5208. CheckIndex(ARecord);
  5209. Changed(ARecord, sroAdd);
  5210. end;
  5211. end
  5212. // 从数据库加载数据时不排序,全部加载完在外部排序索引
  5213. else
  5214. begin
  5215. ARecord.FIndex := FDataList.Add(ARecord);
  5216. //if not ARecord.IsUpdating then
  5217. // CheckIndex(ARecord, nil);
  5218. end;
  5219. Result := ARecord.FIndex;
  5220. // 缓存历史
  5221. if FUseSavePoint and (not FIsLoading) and (not FHistory.Stopping) then
  5222. FHistory.Add(ARecord);
  5223. end;
  5224. procedure TsdDataSet.ClearRecords(AClearAutoFields: Boolean);
  5225. var
  5226. I: Integer;
  5227. sdRec: TsdDataRecord;
  5228. begin
  5229. for I := 0 to FDataList.Count - 1 do
  5230. begin
  5231. sdRec := TsdDataRecord(FDataList[I]);
  5232. sdRec.Free;
  5233. end;
  5234. FDataList.Clear;
  5235. for I := 0 to FDeletedList.Count - 1 do
  5236. begin
  5237. sdRec := TsdDataRecord(FDeletedList[I]);
  5238. sdRec.Free;
  5239. end;
  5240. FDeletedList.Clear;
  5241. FChangedList.Clear;
  5242. ClearIndexData;
  5243. if AClearAutoFields and FAutoGetFields then
  5244. FFieldList.Clear;
  5245. end;
  5246. procedure TsdDataSet.Close;
  5247. begin
  5248. Active := False;
  5249. end;
  5250. constructor TsdDataSet.Create(AOwner: TComponent);
  5251. begin
  5252. inherited Create(AOwner);
  5253. FFieldList := TsdFieldList.Create(Self);
  5254. FDataList := TList.Create;
  5255. FDeletedList := TList.Create;
  5256. FChangedList := TList.Create;
  5257. FChangedLookupFields := TList.Create;
  5258. FIndexList := TsdIndexList.Create(Self);
  5259. FHistory := TsdHistoryList.Create(Self);
  5260. FAutoGetFields := False;
  5261. FRecordClass := TsdDataRecord;
  5262. FHasKey := False;
  5263. FIsLoading := False;
  5264. FUpdateLock := 0;
  5265. FViewList := TList.Create;
  5266. FLoadDefaultFields := True;
  5267. FKeepPosition := False;
  5268. FCurrentView := nil;
  5269. FEventRec := nil;
  5270. FFiltered := False;
  5271. Filter := '';
  5272. FUseSavePoint := False;
  5273. FTableName := '';
  5274. FOperationManager := nil;
  5275. FEnableValueEvents := True;
  5276. FSavedPoint := 0;
  5277. end;
  5278. function TsdDataSet.CreateRecord: TsdDataRecord;
  5279. begin
  5280. if Assigned(FOnGetRecordClass) then
  5281. FOnGetRecordClass(FRecordClass);
  5282. Result := FRecordClass.Create(Self);
  5283. end;
  5284. function TsdDataSet.Delete(AIndex: Integer): Boolean;
  5285. var
  5286. sdRec: TsdDataRecord;
  5287. begin
  5288. CheckActive;
  5289. sdRec := GetRecords(AIndex);
  5290. Result := RemoveRecord(sdRec);
  5291. end;
  5292. destructor TsdDataSet.Destroy;
  5293. begin
  5294. if Assigned(FDesigner) then
  5295. FreeAndNil(FDesigner);
  5296. if Assigned(FIndexDesigner) then
  5297. FreeAndNil(FIndexDesigner);
  5298. if Assigned(FProvider) then
  5299. FProvider.FreeNotify;
  5300. Close;
  5301. ClearViews;
  5302. FreeAndNil(FViewList);
  5303. FFieldList.Free;
  5304. FDataList.Free;
  5305. FDeletedList.Free;
  5306. FChangedList.Free;
  5307. FChangedLookupFields.Free;
  5308. FIndexList.Free;
  5309. FHistory.Free;
  5310. inherited;
  5311. end;
  5312. function TsdDataSet.GetRecordCount: Integer;
  5313. begin
  5314. Result := FDataList.Count;
  5315. end;
  5316. function TsdDataSet.GetRecords(Index: Integer): TsdDataRecord;
  5317. begin
  5318. Result := nil;
  5319. if (Index >= 0) and (Index <= FDataList.Count - 1) then
  5320. Result := TsdDataRecord(FDataList[Index]);
  5321. end;
  5322. function TsdDataSet.IndexOf(ARecord: TsdDataRecord): Integer;
  5323. begin
  5324. Result := FDataList.IndexOf(ARecord);
  5325. end;
  5326. procedure TsdDataSet.LoadRecords;
  5327. begin
  5328. FAutoGetFields := FieldCount = 0;
  5329. BeginLoad;
  5330. try
  5331. try
  5332. if Filtered and (Filter <> '') then
  5333. FProvider.SetFilter(Filter)
  5334. else
  5335. FProvider.SetFilter('');
  5336. if not FProvider.LoadRecords then
  5337. raise EsdDataSet.Create('Can not load data');
  5338. except
  5339. ClearRecords(True);
  5340. raise;
  5341. end;
  5342. finally
  5343. EndLoad;
  5344. end;
  5345. SortIndex;
  5346. end;
  5347. procedure TsdDataSet.Open;
  5348. begin
  5349. Active := True;
  5350. end;
  5351. function TsdDataSet.Remove(ARec: TsdDataRecord): Boolean;
  5352. begin
  5353. Result := RemoveRecord(ARec);
  5354. end;
  5355. function TsdDataSet.RemoveRecord(ARec: TsdDataRecord; FreeRecord: Boolean): Boolean;
  5356. var
  5357. iIndex: Integer;
  5358. Allow: Boolean;
  5359. begin
  5360. Result := False;
  5361. CheckActive;
  5362. if ARec = nil then Exit;
  5363. Allow := True;
  5364. DoBeforeDeleteRecord(ARec, Allow);
  5365. if not Allow then Exit;
  5366. iIndex := FDataList.IndexOf(ARec);
  5367. if iIndex < 0 then
  5368. raise EsdDataSet.Create(Format('Delete record error: Error index is %d', [ARec.FIndex]));
  5369. Result := FDataList.Remove(ARec) >= 0;
  5370. // 删除记录相关的索引信息
  5371. DeleteRecordIndex(ARec);
  5372. if not IsUpdating then
  5373. RenumberIndex(iIndex);
  5374. Changed(ARec, sroDelete);
  5375. DoAfterDeleteRecord(ARec);
  5376. // 是新记录,直接删除
  5377. // 是从数据库中来的记录,需要缓存起来,保存时再与数据库记录同步删除
  5378. if not ARec.New then
  5379. AddToDeletedList(ARec)
  5380. else if (FreeRecord and (not FUseSavePoint)) then
  5381. FreeAndNil(ARec);
  5382. if FUseSavePoint and (not FIsLoading) and (not FHistory.Stopping) then
  5383. FHistory.Delete(ARec);
  5384. end;
  5385. procedure TsdDataSet.RenumberIndex(AFromIndex: Integer);
  5386. var
  5387. I: Integer;
  5388. sdRec: TsdDataRecord;
  5389. begin
  5390. for I := AFromIndex to FDataList.Count - 1 do
  5391. begin
  5392. sdRec := TsdDataRecord(FDataList[I]);
  5393. sdRec.FIndex := I;
  5394. end;
  5395. end;
  5396. procedure TsdDataSet.DeleteRecNo(ARecNo: Integer);
  5397. var
  5398. I: Integer;
  5399. sdRec: TsdDataRecord;
  5400. begin
  5401. for I := 0 to FDataList.Count - 1 do
  5402. begin
  5403. sdRec := TsdDataRecord(FDataList[I]);
  5404. if sdRec.FRecNo > ARecNo then
  5405. Dec(sdRec.FRecNo);
  5406. end;
  5407. end;
  5408. procedure TsdDataSet.InsertRecNo(ARecNo: Integer);
  5409. var
  5410. I, iRecNo: Integer;
  5411. sdRec: TsdDataRecord;
  5412. begin
  5413. for I := 0 to FDataList.Count - 1 do
  5414. begin
  5415. sdRec := TsdDataRecord(FDataList[I]);
  5416. if sdRec.FRecNo >= ARecNo then
  5417. Inc(sdRec.FRecNo);
  5418. end;
  5419. for I := 0 to FDeletedList.Count - 1 do
  5420. begin
  5421. iRecNo := Integer(FDataList[I]);
  5422. if iRecNo >= ARecNo then
  5423. begin
  5424. Inc(iRecNo);
  5425. FDataList[I] := Pointer(iRecNo);
  5426. end;
  5427. end;
  5428. end;
  5429. procedure TsdDataSet.Save;
  5430. begin
  5431. SaveRecords;
  5432. end;
  5433. procedure TsdDataSet.SaveRecords;
  5434. var
  5435. strLogFile: string;
  5436. begin
  5437. if not Modified then Exit;
  5438. CheckActive;
  5439. CheckForSave;
  5440. //SortDeletedRecords;
  5441. try
  5442. FProvider.ApplyUpdates;
  5443. FSavedPoint := SavePoint;
  5444. except
  5445. strLogFile := ExtractFilePath(Application.ExeName) + 'Log';
  5446. if not DirectoryExists(strLogFile) then
  5447. CreateDir(strLogFile);
  5448. strLogFile := strLogFile + '\sdLog[' + Name + '](' + FormatDateTime('yyyy-mm-dd hh.nn.ss.zzz', Now) + ').log';
  5449. SaveToXML(strLogFile);
  5450. raise;
  5451. end;
  5452. end;
  5453. procedure TsdDataSet.SetActive(const Value: Boolean);
  5454. begin
  5455. if (csReading in ComponentState) then
  5456. begin
  5457. FStreamedActive := Value;
  5458. Exit;
  5459. end;
  5460. if Value = FActive then
  5461. Exit;
  5462. if Value then
  5463. begin
  5464. if FProvider = nil then
  5465. if not IsDesigning then
  5466. raise EsdDataSet.Create('No provider')
  5467. else
  5468. Exit;
  5469. ProcessFieldNames;
  5470. LoadRecords;
  5471. FSavedPoint := 0;
  5472. FActive := Value;
  5473. if Assigned(FAfterOpen) then
  5474. FAfterOpen(Self);
  5475. end
  5476. else
  5477. begin
  5478. FActive := Value;
  5479. FHistory.Clear;
  5480. ClearRecords(True);
  5481. if Assigned(FAfterClose) then
  5482. FAfterClose(Self);
  5483. end;
  5484. NotifyChanged(nil, sdoActive);
  5485. end;
  5486. procedure TsdDataSet.SetOnProgress(const Value: TsdOnProgressEvent);
  5487. begin
  5488. FOnProgress := Value;
  5489. end;
  5490. procedure TsdDataSet.SetRecordClass(const Value: TsdRecordClass);
  5491. begin
  5492. if Active then
  5493. raise EsdDataSet.Create('Can not set RecordClass while dataset is opened');
  5494. FRecordClass := Value;
  5495. end;
  5496. procedure TsdDataSet.SortDeletedRecords;
  5497. procedure QuickSort(iLo, iHi: Integer);
  5498. var
  5499. Lo, Hi: Integer;
  5500. iMid: Integer;
  5501. begin
  5502. Lo := iLo;
  5503. Hi := iHi;
  5504. iMid := Integer(TsdDataRecord(FDeletedList[(iLo + iHi) div 2]).FRecNo);
  5505. repeat
  5506. while Integer(TsdDataRecord(FDeletedList[Lo]).FRecNo) < iMid do
  5507. Inc(Lo);
  5508. while Integer(TsdDataRecord(FDeletedList[Hi]).FRecNo) > iMid do
  5509. Dec(Hi);
  5510. if Lo <= Hi then
  5511. begin
  5512. if Lo < Hi then
  5513. begin
  5514. FDeletedList.Exchange(Lo, Hi);
  5515. end;
  5516. Inc(Lo);
  5517. Dec(Hi);
  5518. end;
  5519. until Lo > Hi;
  5520. if Hi > iLo then QuickSort(iLo, Hi);
  5521. if Lo < iHi then QuickSort(Lo, iHi);
  5522. end;
  5523. begin
  5524. if FDeletedList.Count > 0 then
  5525. QuickSort(0, FDeletedList.Count - 1);
  5526. end;
  5527. function TsdDataSet.AddIndex(const Name, Fields: string): TsdIndex;
  5528. begin
  5529. // 检查索引是否存在
  5530. Result := nil;
  5531. if FIndexList.FindByName(Name) <> nil then
  5532. raise EsdIndex.Create(Format('Index ''%s'' exists', [Name]));
  5533. Result := FIndexList.Add;
  5534. Result.Name := Name;
  5535. Result.FieldNames := Fields;
  5536. end;
  5537. procedure TsdDataSet.SortIndex;
  5538. begin
  5539. FIndexList.Sort;
  5540. end;
  5541. procedure TsdDataSet.CheckIndex(ARec: TsdDataRecord);
  5542. begin
  5543. if not IsUpdating then
  5544. FIndexList.Check(ARec);
  5545. end;
  5546. procedure TsdDataSet.DeleteRecordIndex(ARec: TsdDataRecord);
  5547. begin
  5548. if not IsUpdating then
  5549. FIndexList.DeleteRecord(ARec);
  5550. end;
  5551. procedure TsdDataSet.ClearIndexData;
  5552. begin
  5553. FIndexList.ClearData;
  5554. end;
  5555. function TsdDataSet.FindKey(AIndexName: string;
  5556. KeyValues: Variant): TsdDataRecord;
  5557. var
  5558. Index: TsdIndex;
  5559. begin
  5560. CheckActive;
  5561. Result := nil;
  5562. Index := FIndexList.FindByName(AIndexName);
  5563. if Index = nil then
  5564. raise EsdDataSet.Create(Format('Can not find index ''%s''', [AIndexName]));
  5565. Result := Index.FindKey(KeyValues);
  5566. end;
  5567. function TsdDataSet.Locate(const KeyFields: string;
  5568. const KeyValues: Variant): TsdDataRecord;
  5569. var
  5570. Index: TsdIndex;
  5571. begin
  5572. CheckActive;
  5573. Index := FIndexList.FindByKeyFields(KeyFields, True);
  5574. if Index <> nil then
  5575. Result := Index.FindKey(KeyValues)
  5576. else
  5577. Result := InnerLocate(KeyFields, KeyValues);
  5578. end;
  5579. function TsdDataSet.InnerLocate(const KeyFields: string;
  5580. const KeyValues: Variant): TsdDataRecord;
  5581. var
  5582. KeyCount, I, J: Integer;
  5583. V: Variant;
  5584. bFound: Boolean;
  5585. NameList: TStringList;
  5586. FieldNoList: TList;
  5587. Field: TsdField;
  5588. Rec: TsdDataRecord;
  5589. Value: TsdValue;
  5590. begin
  5591. Result := nil;
  5592. if VarIsArray(KeyValues) then
  5593. KeyCount := VarArrayHighBound(KeyValues, 1) - VarArrayLowBound(KeyValues, 1) + 1
  5594. else
  5595. KeyCount := 1;
  5596. FieldNoList := TList.Create;
  5597. try
  5598. NameList := TStringList.Create;
  5599. try
  5600. NameList.Delimiter := ';';
  5601. NameList.DelimitedText := KeyFields;
  5602. if NameList.Count <> KeyCount then
  5603. raise EsdDataSet.Create('Fields do not match values');
  5604. for I := 0 to NameList.Count - 1 do
  5605. begin
  5606. Field := FFieldList.FieldByName(NameList[I]);
  5607. if Field = nil then
  5608. raise EsdDataSet.Create(Format('Can not find field ''%s''', [NameList[I]]));
  5609. FieldNoList.Add(Pointer(Field.FieldNo));
  5610. end;
  5611. finally
  5612. NameList.Free;
  5613. end;
  5614. for I := 0 to FDataList.Count - 1 do
  5615. begin
  5616. bFound := True;
  5617. Rec := Records[I];
  5618. for J := 0 to KeyCount - 1 do
  5619. begin
  5620. if VarIsArray(KeyValues) then
  5621. V := KeyValues[J]
  5622. else
  5623. V := KeyValues;
  5624. Value := Rec.Values[Integer(FieldNoList[J])];
  5625. // 字符串类型有''和Null的区别
  5626. if Value.Field.IsVarField then
  5627. begin
  5628. if VarToStr(V) <> Value.AsString then
  5629. begin
  5630. bFound := False;
  5631. Break;
  5632. end;
  5633. end
  5634. else if V <> Value.Value then
  5635. begin
  5636. bFound := False;
  5637. Break;
  5638. end;
  5639. end;
  5640. if bFound then
  5641. begin
  5642. Result := Rec;
  5643. Break;
  5644. end;
  5645. end;
  5646. finally
  5647. FieldNoList.Free;
  5648. end;
  5649. end;
  5650. function TsdDataSet.IsDesigning: Boolean;
  5651. begin
  5652. Result := csDesigning in ComponentState;
  5653. end;
  5654. function TsdDataSet.GetProvider: IsdProvider;
  5655. begin
  5656. Result := FProvider;
  5657. end;
  5658. procedure TsdDataSet.SetProvider(const Value: IsdProvider);
  5659. begin
  5660. if FProvider <> Value then
  5661. begin
  5662. FProvider := Value;
  5663. if FProvider <> nil then
  5664. FProvider.SetDataSet(Self);
  5665. end;
  5666. end;
  5667. procedure TsdDataSet.Changed(const Sender: TObject; AOperation: TsdOperation);
  5668. var
  5669. V: TsdValue;
  5670. Rec: TsdDataRecord;
  5671. Obj: TObject;
  5672. begin
  5673. V := nil;
  5674. Rec := nil;
  5675. if Sender is TsdValue then
  5676. begin
  5677. V := TsdValue(Sender);
  5678. Rec := V.FOwner;
  5679. end
  5680. else if Sender is TsdDataRecord then
  5681. Rec := TsdDataRecord(Sender);
  5682. if Sender <> nil then
  5683. begin
  5684. Obj := Sender;
  5685. if (AOperation <> sroDelete) and (not FIsLoading) and (FChangedList.IndexOf(Rec) < 0) then
  5686. FChangedList.Add(Rec)
  5687. else if AOperation = sroDelete then
  5688. FChangedList.Remove(Rec);
  5689. end
  5690. else
  5691. Obj := Self;
  5692. if not IsUpdating then
  5693. NotifyChanged(Sender, AOperation);
  5694. end;
  5695. procedure TsdDataSet.ClearChangedList;
  5696. begin
  5697. FChangedList.Clear;
  5698. end;
  5699. procedure TsdDataSet.ClearDeletedList;
  5700. var
  5701. I: Integer;
  5702. Rec: TsdDataRecord;
  5703. begin
  5704. for I := 0 to FDeletedList.Count - 1 do
  5705. begin
  5706. Rec := TsdDataRecord(FDeletedList[I]);
  5707. // 如果UseSavePoint,则要检查FHistory中没有记录该Rec才能Free
  5708. if (not UseSavePoint) or (FHistory.FindByRecord(Rec) = nil) then
  5709. Rec.Free;
  5710. end;
  5711. FDeletedList.Clear;
  5712. end;
  5713. function TsdDataSet.GetHasKey: Boolean;
  5714. var
  5715. I: Integer;
  5716. begin
  5717. Result := False;
  5718. for I := 0 to FieldCount - 1 do
  5719. if FFieldList.Fields[I].IsKey then
  5720. begin
  5721. Result := True;
  5722. Break;
  5723. end;
  5724. end;
  5725. procedure TsdDataSet.BeginLoad;
  5726. begin
  5727. FIsLoading := True;
  5728. end;
  5729. procedure TsdDataSet.EndLoad;
  5730. begin
  5731. FIsLoading := False;
  5732. end;
  5733. procedure TsdDataSet.SetAfterAddRecord(const Value: TsdRecordEvent);
  5734. begin
  5735. FAfterAddRecord := Value;
  5736. end;
  5737. procedure TsdDataSet.SetAfterDeleteRecord(const Value: TsdRecordEvent);
  5738. begin
  5739. FAfterDeleteRecord := Value;
  5740. end;
  5741. procedure TsdDataSet.SetAfterRecordChange(const Value: TsdRecordEvent);
  5742. begin
  5743. FAfterRecordChanged := Value;
  5744. end;
  5745. procedure TsdDataSet.SetBeforeAddRecord(const Value: TsdAllowRecordEvent);
  5746. begin
  5747. FBeforeAddRecord := Value;
  5748. end;
  5749. procedure TsdDataSet.SetBeforeDeleteRecord(
  5750. const Value: TsdAllowRecordEvent);
  5751. begin
  5752. FBeforeDeleteRecord := Value;
  5753. end;
  5754. procedure TsdDataSet.DoAfterRecordChanged(ARecord: TsdDataRecord);
  5755. var
  5756. I: Integer;
  5757. begin
  5758. if (not FIsLoading) and (not ARecord.IsInEvent) then
  5759. begin
  5760. ARecord.EnterEvent;
  5761. try
  5762. if (FCurrentView <> nil) and (FEventRec = ARecord) then
  5763. FCurrentView.DoAfterRecordChanged(ARecord);
  5764. if Assigned(FAfterRecordChanged) then
  5765. FAfterRecordChanged(ARecord);
  5766. finally
  5767. ARecord.ExitEvent;
  5768. end;
  5769. end;
  5770. end;
  5771. procedure TsdDataSet.ClearViews;
  5772. var
  5773. I: Integer;
  5774. lstTemp: TList;
  5775. begin
  5776. lstTemp := TList.Create;
  5777. try
  5778. lstTemp.Assign(FViewList);
  5779. for I := 0 to lstTemp.Count - 1 do
  5780. TsdDataView(lstTemp[I]).FreeNotify;
  5781. FViewList.Clear;
  5782. finally
  5783. lstTemp.Free;
  5784. end;
  5785. end;
  5786. procedure TsdDataSet.RegisterView(AView: TObject);
  5787. begin
  5788. if not (AView is TsdDataView) then
  5789. raise EsdDataSet.Create('The parameter is not a DataView');
  5790. if FViewList.IndexOf(AView) < 0 then
  5791. FViewList.Add(AView);
  5792. end;
  5793. procedure TsdDataSet.UnregisterView(AView: TObject);
  5794. begin
  5795. if FViewList.IndexOf(AView) >= 0 then
  5796. FViewList.Remove(AView);
  5797. end;
  5798. procedure TsdDataSet.NotifyChanged(const Sender: TObject;
  5799. AOperation: TsdOperation);
  5800. var
  5801. I: Integer;
  5802. begin
  5803. for I := 0 to FViewList.Count - 1 do
  5804. TsdDataView(FViewList[I]).Changed(Sender, AOperation);
  5805. end;
  5806. function TsdDataSet.FindIndex(AIndexName: string): TsdIndex;
  5807. begin
  5808. Result := FIndexList.FindByName(AIndexName);
  5809. end;
  5810. procedure TsdDataSet.AssignRecords(AList: TList);
  5811. begin
  5812. AList.Assign(FDataList);
  5813. end;
  5814. procedure TsdDataSet.DefineProperties(Filer: TFiler);
  5815. begin
  5816. inherited DefineProperties(Filer);
  5817. Filer.DefineBinaryProperty('FieldListData', ReadFields, WriteFields, FieldCount > 0);
  5818. Filer.DefineBinaryProperty('IndexListData', ReadIndexes, WriteIndexes, FIndexList.Count > 0);
  5819. end;
  5820. procedure TsdDataSet.ReadFields(Stream: TStream);
  5821. var
  5822. Field: TsdField;
  5823. Reader: TReader;
  5824. begin
  5825. Reader := TReader.Create(Stream, 1024);
  5826. try
  5827. Reader.ReadListBegin;
  5828. while not Reader.EndOfList do
  5829. begin
  5830. Field := FFieldList.Add;
  5831. Field.LoadProperty(Reader);
  5832. end;
  5833. Reader.ReadListEnd;
  5834. finally
  5835. Reader.Free;
  5836. end;
  5837. end;
  5838. procedure TsdDataSet.ReadIndexes(Stream: TStream);
  5839. var
  5840. Index: TsdIndex;
  5841. Reader: TReader;
  5842. begin
  5843. Reader := TReader.Create(Stream, 1024);
  5844. try
  5845. while not Reader.EndOfList do
  5846. begin
  5847. Index := FIndexList.Add;
  5848. Index.LoadProperty(Reader);
  5849. end;
  5850. Reader.ReadListEnd;
  5851. finally
  5852. Reader.Free;
  5853. end;
  5854. end;
  5855. procedure TsdDataSet.WriteFields(Stream: TStream);
  5856. var
  5857. I: Integer;
  5858. Field: TsdField;
  5859. Writer: TWriter;
  5860. begin
  5861. Writer := TWriter.Create(Stream, 1024);
  5862. try
  5863. Writer.WriteListBegin;
  5864. for I := 0 to FieldCount - 1 do
  5865. begin
  5866. Field := FFieldList[I];
  5867. Field.SaveProperty(Writer);
  5868. end;
  5869. Writer.WriteListEnd;
  5870. finally
  5871. Writer.Free;
  5872. end;
  5873. end;
  5874. procedure TsdDataSet.WriteIndexes(Stream: TStream);
  5875. var
  5876. I: Integer;
  5877. Index: TsdIndex;
  5878. Writer: TWriter;
  5879. begin
  5880. Writer := TWriter.Create(Stream, 1024);
  5881. try
  5882. for I := 0 to FIndexList.Count - 1 do
  5883. begin
  5884. Index := FIndexList[I];
  5885. Index.SaveProperty(Writer);
  5886. end;
  5887. Writer.WriteListEnd;
  5888. finally
  5889. Writer.Free;
  5890. end;
  5891. end;
  5892. function TsdDataSet.AddField(const FieldName: string): TsdField;
  5893. var
  5894. Field: TField;
  5895. begin
  5896. Result := nil;
  5897. if FProvider = nil then Exit;
  5898. Result := FFieldList.FieldByName(FieldName);
  5899. if Result <> nil then Exit;
  5900. Result := FFieldList.Add;
  5901. Result.FieldName := FieldName;
  5902. FProvider.AssignField(FieldName);
  5903. end;
  5904. function TsdDataSet.GetFieldCount: Integer;
  5905. begin
  5906. Result := FFieldList.Count;
  5907. end;
  5908. procedure TsdDataSet.Loaded;
  5909. begin
  5910. inherited Loaded;
  5911. try
  5912. if FStreamedActive then
  5913. Active := True;
  5914. except
  5915. if csDesigning in ComponentState then
  5916. raise;
  5917. end;
  5918. end;
  5919. procedure TsdDataSet.GetFieldNames(AFieldNames: TStringList);
  5920. var
  5921. I: Integer;
  5922. begin
  5923. AFieldNames.Clear;
  5924. for I := 0 to FieldCount - 1 do
  5925. AFieldNames.Add(FFieldList[I].FieldName);
  5926. end;
  5927. procedure TsdDataSet.ProcessFieldNames;
  5928. var
  5929. I: Integer;
  5930. begin
  5931. for I := 0 to FieldCount - 1 do
  5932. Fields[I].ProcessFieldName(Fields[I].FieldName);
  5933. end;
  5934. procedure TsdDataSet.SetOnGetRecordClass(const Value: TsdGetRecordClass);
  5935. begin
  5936. FOnGetRecordClass := Value;
  5937. end;
  5938. function TsdDataSet.ControlsDisabled: Boolean;
  5939. begin
  5940. Result := FDisableCount <> 0;
  5941. end;
  5942. procedure TsdDataSet.DisableControls;
  5943. begin
  5944. Inc(FDisableCount);
  5945. end;
  5946. procedure TsdDataSet.EnableControls;
  5947. var
  5948. I: Integer;
  5949. begin
  5950. if FDisableCount <> 0 then
  5951. begin
  5952. Dec(FDisableCount);
  5953. if FDisableCount = 0 then
  5954. for I := 0 to FViewList.Count - 1 do
  5955. TsdDataView(FViewList[I]).NotifyDataChanged;
  5956. end;
  5957. end;
  5958. procedure TsdDataSet.SetAfterClose(const Value: TNotifyEvent);
  5959. begin
  5960. FAfterClose := Value;
  5961. end;
  5962. procedure TsdDataSet.SetAfterOpen(const Value: TNotifyEvent);
  5963. begin
  5964. FAfterOpen := Value;
  5965. end;
  5966. procedure TsdDataSet.BeginUpdate;
  5967. begin
  5968. Inc(FUpdateLock);
  5969. end;
  5970. procedure TsdDataSet.EndUpdate;
  5971. begin
  5972. if FUpdateLock > 0 then
  5973. Dec(FUpdateLock);
  5974. if not IsUpdating then
  5975. begin
  5976. RenumberIndex;
  5977. FIndexList.Sort;
  5978. try
  5979. FKeepPosition := True;
  5980. NotifyChanged(nil, sdoRefresh);
  5981. finally
  5982. FKeepPosition := False;
  5983. end;
  5984. CheckChangedLookupFields(nil);
  5985. end;
  5986. end;
  5987. function TsdDataSet.IsUpdating: Boolean;
  5988. begin
  5989. Result := FUpdateLock > 0;
  5990. end;
  5991. procedure TsdDataSet.DoAfterValueChanged(AValue: TsdValue);
  5992. begin
  5993. if (not FIsLoading) and (not AValue.Owner.IsInEvent) then
  5994. begin
  5995. AValue.Owner.EnterEvent;
  5996. try
  5997. if (FCurrentView <> nil) and (FEventRec = AValue.Owner) then
  5998. FCurrentView.DoAfterValueChanged(AValue);
  5999. if Assigned(FAfterValueChanged) then
  6000. FAfterValueChanged(AValue);
  6001. finally
  6002. AValue.Owner.ExitEvent;
  6003. end;
  6004. end;
  6005. end;
  6006. procedure TsdDataSet.DoBeforeValueChange(AValue: TsdValue; const NewValue: Variant;
  6007. var Allow: Boolean);
  6008. begin
  6009. if (not FIsLoading) and (not AValue.Owner.IsInEvent) then
  6010. begin
  6011. AValue.Owner.EnterEvent;
  6012. try
  6013. if (FCurrentView <> nil) and (FEventRec = AValue.Owner) then
  6014. FCurrentView.DoBeforeValueChange(AValue, NewValue, Allow);
  6015. if Allow and Assigned(FBeforeValueChange) then
  6016. FBeforeValueChange(AValue, NewValue, Allow);
  6017. finally
  6018. AValue.Owner.ExitEvent;
  6019. end;
  6020. end;
  6021. end;
  6022. procedure TsdDataSet.SetAfterRecordChanged(const Value: TsdRecordEvent);
  6023. begin
  6024. FAfterRecordChanged := Value;
  6025. end;
  6026. procedure TsdDataSet.SetAfterValueChanged(const Value: TsdValueEvent);
  6027. begin
  6028. FAfterValueChanged := Value;
  6029. end;
  6030. procedure TsdDataSet.SetBeforeValueChange(const Value: TsdAllowValueEvent);
  6031. begin
  6032. FBeforeValueChange := Value;
  6033. end;
  6034. procedure TsdDataSet.SetAfterRecordUpdated(const Value: TsdRecordEvent);
  6035. begin
  6036. FAfterRecordUpdated := Value;
  6037. end;
  6038. procedure TsdDataSet.SetBeforeRecordUpdate(const Value: TsdRecordEvent);
  6039. begin
  6040. FBeforeRecordUpdate := Value;
  6041. end;
  6042. procedure TsdDataSet.DoAfterRecordUpdated(ARecord: TsdDataRecord);
  6043. begin
  6044. if (not FIsLoading) and (not ARecord.IsUpdating) and Assigned(FAfterRecordUpdated) then
  6045. FAfterRecordUpdated(ARecord);
  6046. end;
  6047. procedure TsdDataSet.DoBeforeRecordUpdate(ARecord: TsdDataRecord);
  6048. begin
  6049. if (not FIsLoading) and (not ARecord.IsUpdating) and Assigned(FBeforeRecordUpdate) then
  6050. FBeforeRecordUpdate(ARecord);
  6051. end;
  6052. function TsdDataSet.CurrentView: TsdDataView;
  6053. begin
  6054. Result := FCurrentView;
  6055. end;
  6056. function TsdDataSet.GetModified: Boolean;
  6057. begin
  6058. Result := (FChangedList.Count > 0) or (FDeletedList.Count > 0);
  6059. end;
  6060. procedure TsdDataSet.CheckChangedLookupFields(AField: TsdField;
  6061. ARecord: TsdDataRecord);
  6062. var
  6063. I: Integer;
  6064. begin
  6065. if (AField <> nil) and (FChangedLookupFields.IndexOf(AField) < 0) then
  6066. FChangedLookupFields.Add(AField);
  6067. if ((ARecord <> nil) and (not IsUpdating) and (not ARecord.IsUpdating)) or
  6068. ((ARecord = nil) and (not IsUpdating)) then
  6069. begin
  6070. for I := 0 to FChangedLookupFields.Count - 1 do
  6071. TsdField(FChangedLookupFields[I]).RefreshLookup;
  6072. FChangedLookupFields.Clear;
  6073. end;
  6074. end;
  6075. // 注意,此方法不触发事件
  6076. procedure TsdDataSet.DeleteAll;
  6077. var
  6078. I: Integer;
  6079. Rec: TsdDataRecord;
  6080. begin
  6081. ClearIndexData;
  6082. for I := 0 to FDataList.Count - 1 do
  6083. begin
  6084. Rec := TsdDataRecord(FDataList[I]);
  6085. if not Rec.New then
  6086. AddToDeletedList(Rec)
  6087. else
  6088. FreeAndNil(Rec);
  6089. end;
  6090. ClearChangedList;
  6091. FDataList.Clear;
  6092. NotifyChanged(nil, sdoRefresh);
  6093. end;
  6094. procedure TsdDataSet.AddToDeletedList(ARecord: TsdDataRecord);
  6095. begin
  6096. if FDeletedList.IndexOf(ARecord) < 0 then
  6097. FDeletedList.Add(ARecord);
  6098. end;
  6099. function TsdDataSet.FieldByName(AFieldName: string): TsdField;
  6100. begin
  6101. Result := FFieldList.FieldByName(AFieldName);
  6102. end;
  6103. function TsdDataSet.Lookup(const KeyFields: string;
  6104. const KeyValues: Variant; const ResultFields: string): Variant;
  6105. var
  6106. Rec: TsdDataRecord;
  6107. begin
  6108. CheckActive;
  6109. Result := Null;
  6110. Rec := Locate(KeyFields, KeyValues);
  6111. if Rec <> nil then
  6112. Result := Rec.FieldValues[ResultFields];
  6113. end;
  6114. procedure TsdDataSet.IndexDeleted(AIndexName: string);
  6115. var
  6116. I: Integer;
  6117. begin
  6118. if FViewList = nil then Exit;
  6119. for I := 0 to FViewList.Count - 1 do
  6120. if SameText(TsdDataView(FViewList[I]).IndexName, AIndexName) then
  6121. TsdDataView(FViewList[I]).IndexName := '';
  6122. end;
  6123. procedure TsdDataSet.CheckActive;
  6124. begin
  6125. if not (Active or FIsLoading) then
  6126. raise EsdDataSet.Create('Cannot perform this operation on a closed dataset');
  6127. end;
  6128. procedure TsdDataSet.LoadFromXML(AFileName: string);
  6129. var
  6130. xmlDoc: IXMLDocument;
  6131. vRoot, vFieldDef, vRecord, vField: IXMLNode;
  6132. I, J: Integer;
  6133. Rec: TsdDataRecord;
  6134. begin
  6135. ClearRecords(True);
  6136. ClearIndex;
  6137. Close;
  6138. FAutoGetFields := True;
  6139. xmlDoc := TXMLDocument.Create(nil) as IXMLDocument;
  6140. try
  6141. xmlDoc.Active := True;
  6142. xmlDoc.Encoding := 'gb2312';
  6143. xmlDoc.Options := xmlDoc.Options + [doAttrNull, doNodeAutoIndent];
  6144. xmlDoc.LoadFromFile(AFileName);
  6145. // 根据FieldDef新增字段
  6146. vFieldDef := xmlDoc.ChildNodes.FindNode('FieldDef');
  6147. if vFieldDef <> nil then
  6148. begin
  6149. // to do
  6150. end;
  6151. vRoot := xmlDoc.ChildNodes.FindNode('SmartDataSet_data_list');
  6152. if vRoot.ChildNodes.Count = 0 then Exit;
  6153. // 没有FieldDef则全部按字符串新增字段
  6154. if vFieldDef = nil then
  6155. begin
  6156. vRecord := vRoot.ChildNodes[0];
  6157. for I := 0 to vRecord.AttributeNodes.Count - 1 do
  6158. begin
  6159. vField := vRecord.AttributeNodes.Nodes[I];
  6160. FFieldList.Add(vField.NodeName, ftWideString, 255);
  6161. end;
  6162. end;
  6163. Open;
  6164. FAutoGetFields := True;
  6165. BeginLoad;
  6166. try
  6167. // 添加数据
  6168. for I := 0 to vRoot.ChildNodes.Count - 1 do
  6169. begin
  6170. vRecord := vRoot.ChildNodes[I];
  6171. Rec := Add;
  6172. for J := 0 to vRecord.AttributeNodes.Count - 1 do
  6173. begin
  6174. vField := vRecord.AttributeNodes.Nodes[J];
  6175. Rec.AddValue(vField.NodeName, vField.Text);
  6176. end;
  6177. end;
  6178. finally
  6179. EndLoad;
  6180. end;
  6181. finally
  6182. xmlDoc := nil;
  6183. end;
  6184. end;
  6185. procedure TsdDataSet.SaveToXML(AFileName: string);
  6186. var
  6187. xmlDoc: IXMLDocument;
  6188. vRoot, vItem: IXMLNode;
  6189. I, J: Integer;
  6190. Rec: TsdDataRecord;
  6191. begin
  6192. xmlDoc := TXMLDocument.Create(nil) as IXMLDocument;
  6193. try
  6194. xmlDoc.Active := True;
  6195. xmlDoc.Encoding := 'gb2312';
  6196. xmlDoc.Options := xmlDoc.Options + [doAttrNull, doNodeAutoIndent];
  6197. vRoot := xmlDoc.AddChild('SmartDataSet_data_list');
  6198. vRoot.Attributes['DataSet'] := Name;
  6199. for I := 0 to RecordCount - 1 do
  6200. begin
  6201. Rec := Records[I];
  6202. vItem := vRoot.AddChild('Record');
  6203. for J := 0 to FieldCount - 1 do
  6204. vItem.Attributes[FFieldList[J].FieldName] := Rec.Values[J].Value;
  6205. end;
  6206. xmlDoc.SaveToFile(AFileName);
  6207. finally
  6208. xmlDoc := nil;
  6209. end;
  6210. end;
  6211. procedure TsdDataSet.DoBeforeAddRecord(ARecord: TsdDataRecord;
  6212. var Allow: Boolean);
  6213. begin
  6214. if (not FIsLoading) and (not ARecord.IsInEvent) then
  6215. begin
  6216. ARecord.EnterEvent;
  6217. try
  6218. if (FCurrentView <> nil) and (FEventRec = ARecord) then
  6219. FCurrentView.DoBeforeAddRecord(ARecord, Allow);
  6220. if Allow and Assigned(FBeforeAddRecord) then
  6221. FBeforeAddRecord(ARecord, Allow);
  6222. finally
  6223. ARecord.ExitEvent;
  6224. end;
  6225. end;
  6226. end;
  6227. procedure TsdDataSet.DoAfterAddRecord(ARecord: TsdDataRecord);
  6228. begin
  6229. if (not FIsLoading) and (not ARecord.IsInEvent) then
  6230. begin
  6231. ARecord.EnterEvent;
  6232. try
  6233. if (FCurrentView <> nil) and (FEventRec = ARecord) then
  6234. FCurrentView.DoAfterAddRecord(ARecord);
  6235. if Assigned(FAfterAddRecord) then
  6236. FAfterAddRecord(ARecord);
  6237. finally
  6238. ARecord.ExitEvent;
  6239. end;
  6240. end;
  6241. end;
  6242. procedure TsdDataSet.CheckForSave;
  6243. var
  6244. I: Integer;
  6245. Rec: TsdDataRecord;
  6246. begin
  6247. for I := 0 to RecordCount - 1 do
  6248. begin
  6249. Rec := Records[I];
  6250. // 如果有意外没有EndUpdate的记录,则在这里统一EndUpdate;
  6251. if Rec.IsUpdating then
  6252. begin
  6253. if Rec.FUpdateLock > 1 then
  6254. Rec.FUpdateLock := 1;
  6255. Rec.EndUpdate;
  6256. end;
  6257. end;
  6258. end;
  6259. procedure TsdDataSet.FreeProviderNotify;
  6260. begin
  6261. Close;
  6262. FProvider := nil;
  6263. end;
  6264. function TsdDataSet.RecordsByKey(const AIndexName: string;
  6265. const KeyValues: Variant; List: TList): Integer;
  6266. var
  6267. Idx: TsdIndex;
  6268. begin
  6269. CheckActive;
  6270. Idx := FindIndex(AIndexName);
  6271. if Idx = nil then
  6272. raise EsdDataSet.Create(Format('Can not find index "%s"', [AIndexName]));
  6273. Result := Idx.RecordsByKey(KeyValues, List);
  6274. end;
  6275. procedure TsdDataSet.DoAfterDeleteRecord(ARecord: TsdDataRecord);
  6276. begin
  6277. if (not FIsLoading) and (not ARecord.IsInEvent) then
  6278. begin
  6279. ARecord.EnterEvent;
  6280. try
  6281. if (FCurrentView <> nil) and (FEventRec = ARecord) then
  6282. FCurrentView.DoAfterDeleteRecord(ARecord);
  6283. if Assigned(FAfterDeleteRecord) then
  6284. FAfterDeleteRecord(ARecord);
  6285. finally
  6286. ARecord.ExitEvent;
  6287. end;
  6288. end;
  6289. end;
  6290. procedure TsdDataSet.DoBeforeDeleteRecord(ARecord: TsdDataRecord;
  6291. var Allow: Boolean);
  6292. begin
  6293. if (not FIsLoading) and (not ARecord.IsInEvent) then
  6294. begin
  6295. ARecord.EnterEvent;
  6296. try
  6297. if (FCurrentView <> nil) and (FEventRec = ARecord) then
  6298. FCurrentView.DoBeforeDeleteRecord(ARecord, Allow);
  6299. if Allow and Assigned(FBeforeDeleteRecord) then
  6300. FBeforeDeleteRecord(ARecord, Allow);
  6301. finally
  6302. ARecord.ExitEvent;
  6303. end;
  6304. end;
  6305. end;
  6306. procedure TsdDataSet.CancelRecord(ARecord: TsdDataRecord);
  6307. var
  6308. iIndex: Integer;
  6309. begin
  6310. // 正在插入的记录直接删除
  6311. if ARecord.Inserting then
  6312. begin
  6313. iIndex := FDataList.IndexOf(ARecord);
  6314. if iIndex >= 0 then
  6315. begin
  6316. FDataList.Remove(ARecord);
  6317. // 删除记录相关的索引信息
  6318. DeleteRecordIndex(ARecord);
  6319. RenumberIndex(iIndex);
  6320. end;
  6321. if FCurrentView <> nil then
  6322. FCurrentView.FDataList.Remove(ARecord);
  6323. FreeAndNil(ARecord);
  6324. end
  6325. // 修改中回滚
  6326. else
  6327. begin
  6328. ARecord.Rollback;
  6329. ARecord.FCanceled := False;
  6330. end;
  6331. end;
  6332. procedure TsdDataSet.Reload;
  6333. begin
  6334. if not Active then Exit;
  6335. if FProvider = nil then
  6336. if not IsDesigning then
  6337. raise EsdDataSet.Create('No provider')
  6338. else
  6339. Exit;
  6340. ClearRecords(False);
  6341. LoadRecords;
  6342. NotifyChanged(nil, sdoRefresh);
  6343. end;
  6344. procedure TsdDataSet.SetFilter(const Value: string);
  6345. begin
  6346. FFilter := Value;
  6347. end;
  6348. procedure TsdDataSet.SetFiltered(const Value: Boolean);
  6349. begin
  6350. FFiltered := Value;
  6351. Reload;
  6352. end;
  6353. procedure TsdDataSet.ClearIndex;
  6354. begin
  6355. FIndexList.Clear;
  6356. end;
  6357. procedure TsdDataSet.SortByFields(const KeyFields: string; AList: TList);
  6358. var
  6359. NameList: TStringList;
  6360. function CompareIndex(ARec1, ARec2: TsdDataRecord): Integer;
  6361. begin
  6362. if ARec1.FIndex > ARec2.FIndex then Result := 1
  6363. else if ARec1.FIndex < ARec2.FIndex then Result := -1
  6364. else Result := 0;
  6365. end;
  6366. function CompareValue(AValue1, AValue2: Variant): Integer;
  6367. begin
  6368. // Result: 0: 1 = 2 >0: 1 > 2 <0: 1 < 2
  6369. if AValue1 > AValue2 then
  6370. Result := 1
  6371. else if AValue1 < AValue2 then
  6372. Result := -1
  6373. else
  6374. Result := 0;
  6375. end;
  6376. function CompareData(ARec1, ARec2: TsdDataRecord): Integer;
  6377. var
  6378. V1, V2: Variant;
  6379. iLevel: Integer;
  6380. begin
  6381. iLevel := 0;
  6382. repeat
  6383. V1 := ARec1.ValueByName(NameList[iLevel]).Value;
  6384. V2 := ARec2.ValueByName(NameList[iLevel]).Value;
  6385. Result := CompareValue(V1, V2);
  6386. // 对于不唯一的字段,作为索引的时候,如果因为其它字段被修改引发了排序,相同索引值下的记录可能会混乱
  6387. // 所以要根据一个唯一值再比较一下,这里选用Record.FIndex
  6388. if (Result = 0) and (iLevel = NameList.Count - 1) then
  6389. Result := CompareIndex(ARec1, ARec2);
  6390. Inc(iLevel);
  6391. until (Result <> 0) or (iLevel > NameList.Count - 1);
  6392. end;
  6393. procedure QuickSort(iLo, iHi: Integer);
  6394. var
  6395. Lo, Hi: Integer;
  6396. MidRec: TsdDataRecord;
  6397. begin
  6398. Lo := iLo;
  6399. Hi := iHi;
  6400. MidRec := TsdDataRecord(AList[(iLo + iHi) div 2]);
  6401. repeat
  6402. while CompareData(TsdDataRecord(AList[Lo]), MidRec) < 0 do
  6403. Inc(Lo);
  6404. while CompareData(TsdDataRecord(AList[Hi]), MidRec) > 0 do
  6405. Dec(Hi);
  6406. if Lo <= Hi then
  6407. begin
  6408. if Lo < Hi then begin
  6409. AList.Exchange(Lo, Hi);
  6410. end;
  6411. Inc(Lo);
  6412. Dec(Hi);
  6413. end;
  6414. until Lo > Hi;
  6415. if Hi > iLo then QuickSort(iLo, Hi);
  6416. if Lo < iHi then QuickSort(Lo, iHi);
  6417. end;
  6418. begin
  6419. if (AList = nil) or (RecordCount = 0) then Exit;
  6420. AList.Clear;
  6421. AList.Assign(FDataList);
  6422. NameList := TStringList.Create;
  6423. try
  6424. NameList.Delimiter := ';';
  6425. NameList.DelimitedText := KeyFields;
  6426. QuickSort(0, AList.Count - 1);
  6427. finally
  6428. NameList.Free;
  6429. end;
  6430. end;
  6431. procedure TsdDataSet.FilterBy(const AFilter: string; AList: TList;
  6432. AKeyFields: string = '');
  6433. var
  6434. FilterHelper: TsdLogicalExprs;
  6435. I: Integer;
  6436. Rec: TsdDataRecord;
  6437. begin
  6438. AList.Clear;
  6439. FilterHelper := TsdLogicalExprs.Create(Self);
  6440. try
  6441. FilterHelper.ParseExpression(AFilter);
  6442. for I := 0 to GetRecordCount - 1 do
  6443. begin
  6444. Rec := Records[I];
  6445. if FilterHelper.Calc(Rec) then
  6446. AList.Add(Rec);
  6447. end;
  6448. finally
  6449. FilterHelper.Free;
  6450. end;
  6451. if AKeyFields <> '' then
  6452. SortList(AList, AKeyFields);
  6453. end;
  6454. function TsdDataSet.GetSavePoint: Integer;
  6455. begin
  6456. Result := FHistory.SavePoint;
  6457. end;
  6458. procedure TsdDataSet.SetSavePoint(const Value: Integer);
  6459. begin
  6460. if not FUseSavePoint then
  6461. raise EsdDataSet.Create('Can not use SavePoint when UseSavePoint is False');
  6462. if not Active then
  6463. raise EsdDataSet.Create('Can not use SavePoint on a closed dataset');
  6464. FHistory.SavePoint := Value;
  6465. end;
  6466. procedure TsdDataSet.SetUseSavePoint(const Value: Boolean);
  6467. begin
  6468. FUseSavePoint := Value;
  6469. if not FUseSavePoint then
  6470. FHistory.Clear;
  6471. end;
  6472. function TsdDataSet.CompareRec(ARec1, ARec2: TsdDataRecord;
  6473. AKeyFields: string): Integer;
  6474. var
  6475. slstFields: TStringList;
  6476. I: Integer;
  6477. strField: string;
  6478. V1, V2: TsdValue;
  6479. begin
  6480. Result := 0;
  6481. slstFields := TStringList.Create;
  6482. try
  6483. slstFields.Delimiter := ';';
  6484. slstFields.DelimitedText := AKeyFields;
  6485. for I := 0 to slstFields.Count - 1 do
  6486. begin
  6487. strField := slstFields[I];
  6488. // 在外部检查字段名是否存在,这里不检查
  6489. V1 := ARec1.ValueByName(strField);
  6490. V2 := ARec2.ValueByName(strField);
  6491. if V1.Value < V2.Value then
  6492. begin
  6493. Result := -1;
  6494. Break;
  6495. end
  6496. else if V1.Value > V2.Value then
  6497. begin
  6498. Result := 1;
  6499. Break;
  6500. end;
  6501. end;
  6502. if Result = 0 then
  6503. begin
  6504. if ARec1.MainIndex < ARec2.MainIndex then
  6505. Result := -1
  6506. else if ARec1.MainIndex > ARec2.MainIndex then
  6507. Result := 1;
  6508. end;
  6509. finally
  6510. slstFields.Free;
  6511. end;
  6512. end;
  6513. procedure TsdDataSet.SortList(AList: TList; AKeyFields: string);
  6514. procedure QuickSort(iLo, iHi: Integer);
  6515. var
  6516. Lo, Hi: Integer;
  6517. MidRec: TsdDataRecord;
  6518. begin
  6519. Lo := iLo;
  6520. Hi := iHi;
  6521. MidRec := TsdDataRecord(AList[(iLo + iHi) div 2]);
  6522. repeat
  6523. while CompareRec(TsdDataRecord(AList[Lo]), MidRec, AKeyFields) < 0 do
  6524. Inc(Lo);
  6525. while CompareRec(TsdDataRecord(AList[Hi]), MidRec, AKeyFields) > 0 do
  6526. Dec(Hi);
  6527. if Lo <= Hi then
  6528. begin
  6529. if Lo < Hi then begin
  6530. AList.Exchange(Lo, Hi);
  6531. end;
  6532. Inc(Lo);
  6533. Dec(Hi);
  6534. end;
  6535. until Lo > Hi;
  6536. if Hi > iLo then QuickSort(iLo, Hi);
  6537. if Lo < iHi then QuickSort(Lo, iHi);
  6538. end;
  6539. begin
  6540. if (AList = nil) or (AList.Count = 0) then Exit;
  6541. QuickSort(0, AList.Count - 1);
  6542. end;
  6543. procedure TsdDataSet.ClearCurrentView;
  6544. begin
  6545. FCurrentView := nil;
  6546. FEventRec := nil;
  6547. end;
  6548. procedure TsdDataSet.BeginUpdateHistoryRecord(ARecord: TsdDataRecord);
  6549. begin
  6550. if UseSavePoint and (FOperationManager <> nil) then
  6551. FHistory.BeginRecordUpdate(ARecord);
  6552. end;
  6553. procedure TsdDataSet.EndUpdateHistoryRecord;
  6554. begin
  6555. if UseSavePoint and (FOperationManager <> nil) then
  6556. FHistory.EndRecordUpdate;
  6557. end;
  6558. procedure TsdDataSet.Redo(AID: Integer);
  6559. begin
  6560. if not FUseSavePoint then
  6561. raise EsdDataSet.Create('Can not use SavePoint when UseSavePoint is False');
  6562. if not Active then
  6563. raise EsdDataSet.Create('Can not use SavePoint on a closed dataset');
  6564. FHistory.Redo(AID);
  6565. end;
  6566. procedure TsdDataSet.Undo(AID: Integer);
  6567. begin
  6568. if not FUseSavePoint then
  6569. raise EsdDataSet.Create('Can not use SavePoint when UseSavePoint is False');
  6570. if not Active then
  6571. raise EsdDataSet.Create('Can not use SavePoint on a closed dataset');
  6572. FHistory.Undo(AID);
  6573. end;
  6574. procedure TsdDataSet.WriteHistoryData(AOperation: TsdOperation; AObject: IsdHistoryObject;
  6575. AData: Pointer);
  6576. begin
  6577. if Active and FUseSavePoint then
  6578. FHistory.WriteHistoryData(AOperation, AObject, AData);
  6579. end;
  6580. procedure TsdDataSet.ResumeHistory;
  6581. begin
  6582. FHistory.Resume;
  6583. end;
  6584. procedure TsdDataSet.SuspendHistory;
  6585. begin
  6586. FHistory.Suspend;
  6587. end;
  6588. { TsdViewColumn }
  6589. procedure TsdViewColumn.Assign(Source: TPersistent);
  6590. begin
  6591. if Source is TsdViewColumn then
  6592. begin
  6593. if Assigned(Collection) then Collection.BeginUpdate;
  6594. try
  6595. FieldName := TsdViewColumn(Source).FFieldName;
  6596. DisplayFormat := TsdViewColumn(Source).FDisplayFormat;
  6597. EditFormat := TsdViewColumn(Source).FEditFormat;
  6598. finally
  6599. if Assigned(Collection) then Collection.EndUpdate;
  6600. end;
  6601. end
  6602. else
  6603. inherited;
  6604. end;
  6605. procedure TsdViewColumn.CheckLookupField;
  6606. begin
  6607. if FLookupField <> nil then
  6608. begin
  6609. FLookupField.RemoveLookupCol(Self);
  6610. FLookupField := nil;
  6611. end;
  6612. if (FLookupDataSet <> nil) and (FKeyFields <> '') and (FLookupKeyFields <> '')
  6613. and (FLookupResultField <> '') then
  6614. begin
  6615. FLookupField := FLookupDataSet.Fields.FieldByName(FLookupResultField);
  6616. if FLookupField <> nil then
  6617. FLookupField.AddLookupCol(Self);
  6618. end;
  6619. end;
  6620. constructor TsdViewColumn.Create(Collection: TCollection);
  6621. begin
  6622. inherited;
  6623. FField := nil;
  6624. FLookupField := nil;
  6625. FDisplayFormat := '';
  6626. FEditFormat := '';
  6627. end;
  6628. destructor TsdViewColumn.Destroy;
  6629. begin
  6630. if FLookupField <> nil then
  6631. begin
  6632. FLookupField.RemoveLookupCol(Self);
  6633. FLookupDataSet := nil;
  6634. end;
  6635. inherited;
  6636. end;
  6637. function TsdViewColumn.FormatText(Value: TsdValue;
  6638. DisplayText: Boolean): string;
  6639. var
  6640. strFMT: string;
  6641. begin
  6642. // 如果为空,即使有格式字符串也输出空
  6643. if (not Assigned(Value)) or Value.IsNull then
  6644. begin
  6645. Result := '';
  6646. Exit;
  6647. end;
  6648. if DisplayText then
  6649. strFMT := FDisplayFormat
  6650. else
  6651. strFMT := FEditFormat;
  6652. case Value.Field.DataType of
  6653. ftSmallint, ftInteger, ftWord:
  6654. begin
  6655. if strFMT = '' then
  6656. Result := Value.Text
  6657. else
  6658. Result := FormatFloat(strFMT, Value.AsInteger);
  6659. end;
  6660. ftFloat:
  6661. begin
  6662. if strFMT = '' then
  6663. Result := Value.Text
  6664. else
  6665. Result := FormatFloat(strFMT, Value.AsFloat);
  6666. end;
  6667. ftCurrency, ftBCD:
  6668. begin
  6669. if strFMT = '' then
  6670. Result := Value.Text
  6671. else
  6672. Result := FormatCurr(strFMT, Value.AsCurrency);
  6673. end;
  6674. ftFMTBCD:
  6675. begin
  6676. if strFMT = '' then
  6677. Result := Value.Text
  6678. else
  6679. Result := FormatBcd(strFMT, Value.AsBCD);
  6680. end;
  6681. ftDateTime:
  6682. begin
  6683. if strFMT = '' then
  6684. Result := Value.Text
  6685. else
  6686. Result := FormatDateTime(strFMT, Value.AsDateTime);
  6687. end
  6688. else
  6689. Result := Value.Text;
  6690. end;
  6691. end;
  6692. function TsdViewColumn.GetDataView: TsdDataView;
  6693. begin
  6694. Result := TsdViewColumnList(Collection).DataView;
  6695. end;
  6696. function TsdViewColumn.GetDisplayName: string;
  6697. begin
  6698. Result := FFieldName;
  6699. if Result = '' then Result := inherited GetDisplayName;
  6700. end;
  6701. function TsdViewColumn.GetIsLookup: Boolean;
  6702. begin
  6703. Result := LookupResultField <> '';
  6704. end;
  6705. procedure TsdViewColumn.LookupChanged;
  6706. begin
  6707. DataView.RefreshField(Self);
  6708. end;
  6709. procedure TsdViewColumn.SetDisplayFormat(const Value: string);
  6710. begin
  6711. FDisplayFormat := Value;
  6712. end;
  6713. procedure TsdViewColumn.SetEditFormat(const Value: string);
  6714. begin
  6715. FEditFormat := Value;
  6716. end;
  6717. procedure TsdViewColumn.SetFieldName(const Value: string);
  6718. begin
  6719. FFieldName := Value;
  6720. if TsdViewColumnList(Collection).DataView.DataSet <> nil then
  6721. FField := TsdViewColumnList(Collection).DataView.DataSet.Fields.FieldByName(FFieldName)
  6722. else
  6723. FField := nil;
  6724. end;
  6725. procedure TsdViewColumn.SetKeyFields(const Value: string);
  6726. begin
  6727. if not SameText(FKeyFields, Value) then
  6728. begin
  6729. FKeyFields := Value;
  6730. CheckLookupField;
  6731. end;
  6732. end;
  6733. procedure TsdViewColumn.SetLookupDataSet(const Value: TsdDataSet);
  6734. begin
  6735. if FLookupDataSet <> Value then
  6736. begin
  6737. FLookupDataSet := Value;
  6738. CheckLookupField;
  6739. end;
  6740. end;
  6741. procedure TsdViewColumn.SetLookupKeyFields(const Value: string);
  6742. begin
  6743. if not SameText(FLookupKeyFields, Value) then
  6744. begin
  6745. FLookupKeyFields := Value;
  6746. CheckLookupField;
  6747. end;
  6748. end;
  6749. procedure TsdViewColumn.SetLookupResultField(const Value: string);
  6750. begin
  6751. if not SameText(FLookupResultField, Value) then
  6752. begin
  6753. FLookupResultField := Value;
  6754. CheckLookupField;
  6755. end;
  6756. end;
  6757. { TsdViewColumnList }
  6758. function TsdViewColumnList.Add: TsdViewColumn;
  6759. begin
  6760. Result := TsdViewColumn(inherited Add);
  6761. end;
  6762. procedure TsdViewColumnList.Assign(Source: TPersistent);
  6763. begin
  6764. inherited Assign(Source);
  6765. end;
  6766. constructor TsdViewColumnList.Create(ADataView: TsdDataView; ItemClass: TsdViewColumnClass);
  6767. begin
  6768. inherited Create(ItemClass);
  6769. FDataView := ADataView;
  6770. end;
  6771. function TsdViewColumnList.FindColumn(
  6772. const AFieldName: string): TsdViewColumn;
  6773. var
  6774. I: Integer;
  6775. begin
  6776. Result := nil;
  6777. for I := 0 to Self.Count - 1 do
  6778. if SameText(AFieldName, Items[I].FieldName) then
  6779. begin
  6780. Result := Items[I];
  6781. Break;
  6782. end;
  6783. end;
  6784. function TsdViewColumnList.GetItem(Index: Integer): TsdViewColumn;
  6785. begin
  6786. Result := TsdViewColumn(inherited Items[Index]);
  6787. end;
  6788. function TsdViewColumnList.GetOwner: TPersistent;
  6789. begin
  6790. Result := FDataView;
  6791. end;
  6792. function TsdViewColumnList.IndexByName(const AFieldName: string): Integer;
  6793. var
  6794. I: Integer;
  6795. begin
  6796. Result := -1;
  6797. for I := 0 to Self.Count - 1 do
  6798. if SameText(AFieldName, Items[I].FieldName) then
  6799. begin
  6800. Result := I;
  6801. Break;
  6802. end;
  6803. end;
  6804. procedure TsdViewColumnList.SetItem(Index: Integer;
  6805. const Value: TsdViewColumn);
  6806. begin
  6807. inherited SetItem(Index, Value);
  6808. end;
  6809. procedure TsdViewColumnList.Update(Item: TCollectionItem);
  6810. begin
  6811. {if not (csDestroying in FDataView.ComponentState) then
  6812. begin
  6813. FDataView.Changed(nil, sroModify);
  6814. end;}
  6815. end;
  6816. { TsdDataView }
  6817. procedure TsdDataView.InitRecords;
  6818. begin
  6819. if FDataSet = nil then Exit;
  6820. FDataList.Clear;
  6821. if FIndex = nil then
  6822. FDataSet.AssignRecords(FDataList)
  6823. else
  6824. FIndex.AssignRecords(FDataList);
  6825. end;
  6826. procedure TsdDataView.CancelRange;
  6827. begin
  6828. FRangeFrom := Null;
  6829. FRangeTo := Null;
  6830. FilterRecords;
  6831. NotifyControlDataViewChanged;
  6832. end;
  6833. procedure TsdDataView.Changed(const Sender: TObject; AOperation: TsdOperation);
  6834. var
  6835. iOldCurrentIndex: Integer;
  6836. OldCurrent: TsdDataRecord;
  6837. procedure InnerCheckCurrent;
  6838. begin
  6839. // 先检查FOldCurrentIndex相同时FOldCurrent是否发生变化,这是由TsdDataView.Insert触发的
  6840. // 再检查iOldCurrentIndex相同时OldCurrent是否发生变化,这是由DataSet触发的
  6841. // 再检查是否表格第一条记录
  6842. if ((FOldCurrentIndex = CurrentIndex) and (FOldCurrent <> Current))
  6843. or ((iOldCurrentIndex = CurrentIndex) and (OldCurrent <> Current)) then
  6844. CheckCurrent(True);
  6845. FOldCurrentIndex := -1;
  6846. FOldCurrent := nil;
  6847. end;
  6848. var
  6849. V: TsdValue;
  6850. Rec: TsdDataRecord;
  6851. RecIndex: Integer;
  6852. begin
  6853. RecIndex := -1;
  6854. V := nil;
  6855. Rec := nil;
  6856. if Sender <> nil then
  6857. begin
  6858. if Sender is TsdValue then
  6859. begin
  6860. V := TsdValue(Sender);
  6861. Rec := V.FOwner;
  6862. end
  6863. else if Sender is TsdDataRecord then
  6864. Rec := TsdDataRecord(Sender);
  6865. end
  6866. else if AOperation in [sroAdd, sroModify, sroDelete] then
  6867. raise EsdDataView.Create('RecordChanged needs a sender');
  6868. iOldCurrentIndex := CurrentIndex;
  6869. OldCurrent := Current;
  6870. case AOperation of
  6871. sroAdd:
  6872. begin
  6873. CheckRange(Rec);
  6874. RecIndex := FDataList.IndexOf(Rec);
  6875. InnerCheckCurrent;
  6876. end;
  6877. sroModify:
  6878. begin
  6879. CheckRange(Rec, V);
  6880. RecIndex := FDataList.IndexOf(Rec);
  6881. InnerCheckCurrent;
  6882. end;
  6883. sroDelete:
  6884. begin
  6885. DoBeforeCurrentChange(nil);
  6886. FDataList.Remove(Rec);
  6887. CheckCurrent(True);
  6888. end;
  6889. sdoActive:
  6890. if not DataSet.Active then
  6891. Active := False;
  6892. sdoRefresh:
  6893. begin
  6894. DoBeforeCurrentChange(Current);
  6895. RefreshRange;
  6896. CheckCurrent;
  6897. end;
  6898. sdoReset:
  6899. begin
  6900. // 特殊情况,有时有记录但当前记录在undo/redo中清空成-1了,处理一下
  6901. if (RecordCount > 0) and (CurrentIndex = -1) then
  6902. FCurrentIndex := 0;
  6903. DoBeforeCurrentChange(Current);
  6904. RefreshRange;
  6905. // 特殊情况,有时有记录但当前记录在undo/redo中清空成-1了,处理一下
  6906. if (RecordCount > 0) and (CurrentIndex = -1) then
  6907. FCurrentIndex := 0;
  6908. CheckCurrent(True);
  6909. end;
  6910. end;
  6911. NotifyDataChanged(RecIndex);
  6912. end;
  6913. constructor TsdDataView.Create(AOwner: TComponent);
  6914. begin
  6915. inherited;
  6916. FControlList := TInterfaceList.Create;
  6917. FActive := False;
  6918. FFilterHelper := TsdLogicalExprs.Create(Self);
  6919. FFilter := '';
  6920. FFiltered := False;
  6921. FColumns := TsdViewColumnList.Create(Self, TsdViewColumn);
  6922. FDataList := TList.Create;
  6923. FRangeFrom := Null;
  6924. FRangeTo := Null;
  6925. FRangeLock := 0;
  6926. FCurrentIndex := -1;
  6927. FCurrent := nil;
  6928. FDetailList := TList.Create;
  6929. FNewCurrent := nil;
  6930. FCurrentChanging := False;
  6931. FOldCurrentIndex := -1;
  6932. FOldCurrent := nil;
  6933. FAutoGetFields := False;
  6934. end;
  6935. function TsdDataView.Delete(Index: Integer): Boolean;
  6936. var
  6937. Rec: TsdDataRecord;
  6938. begin
  6939. Rec := Records[Index];
  6940. Result := Remove(Rec);
  6941. end;
  6942. destructor TsdDataView.Destroy;
  6943. var
  6944. I: Integer;
  6945. begin
  6946. // 从通知主
  6947. if FMasterDataView <> nil then
  6948. FMasterDataView.UnRegisterDetail(Self);
  6949. // 主通知从
  6950. for I := 0 to FDetailList.Count - 1 do
  6951. TsdDataView(FDetailList[I]).ClearMasterDataView;
  6952. FDetailList.Free;
  6953. FDataList.Free;
  6954. for I := 0 to FControlList.Count - 1 do
  6955. IsdViewControl(FControlList[I]).FreeNotify;
  6956. FControlList.Free;
  6957. if FDataSet <> nil then
  6958. FDataSet.UnregisterView(Self);
  6959. FColumns.Free;
  6960. FFilterHelper.Free;
  6961. inherited;
  6962. end;
  6963. procedure TsdDataView.FilterRecords;
  6964. var
  6965. I: Integer;
  6966. Rec: TsdDataRecord;
  6967. List: TList;
  6968. begin
  6969. if not Active then Exit;
  6970. if RangeLocked then Exit;
  6971. InitRecords;
  6972. if not FFiltered then
  6973. begin
  6974. DoCustomSort(FDataList);
  6975. if not DataSet.FKeepPosition then
  6976. begin
  6977. ResetCurrent;
  6978. CurrentIndex := 0;
  6979. end;
  6980. Exit;
  6981. end;
  6982. ParseFilter;
  6983. List := TList.Create;
  6984. try
  6985. List.Assign(FDataList);
  6986. FDataList.Clear;
  6987. for I := 0 to List.Count - 1 do
  6988. begin
  6989. Rec := TsdDataRecord(List[I]);
  6990. if FilterRecord(Rec) then
  6991. FDataList.Add(Rec);
  6992. end;
  6993. finally
  6994. List.Free;
  6995. end;
  6996. DoCustomSort(FDataList);
  6997. if not DataSet.FKeepPosition then
  6998. begin
  6999. ResetCurrent;
  7000. CurrentIndex := 0;
  7001. end;
  7002. NotifyControlDataViewChanged;
  7003. NotifyDataChanged;
  7004. end;
  7005. function TsdDataView.GetDisplayText(RecIndex, Col: Integer): string;
  7006. var
  7007. V: TsdValue;
  7008. Column: TsdViewColumn;
  7009. begin
  7010. Result := '';
  7011. Column := FColumns.Items[Col];
  7012. if Column = nil then Exit;
  7013. V := GetValue(RecIndex, Col);
  7014. if (V <> nil) and (Column <> nil) then
  7015. Result := Column.FormatText(V, True);
  7016. DoOnGetText(Result, GetRecord(RecIndex), V, Column, True);
  7017. end;
  7018. function TsdDataView.GetFieldCount: Integer;
  7019. begin
  7020. Result := FColumns.Count;
  7021. end;
  7022. function TsdDataView.GetIndex: TsdIndex;
  7023. begin
  7024. Result := FIndex;
  7025. end;
  7026. function TsdDataView.GetRecord(Index: Integer): TsdDataRecord;
  7027. begin
  7028. Result := nil;
  7029. if (Index >= 0) and (Index <= RecordCount - 1) then
  7030. Result := TsdDataRecord(FDataList[Index]);
  7031. end;
  7032. function TsdDataView.GetRecordCount: Integer;
  7033. begin
  7034. Result := 0;
  7035. if Active then
  7036. Result := FDataList.Count;
  7037. end;
  7038. function TsdDataView.GetText(RecIndex, Col: Integer): string;
  7039. var
  7040. V: TsdValue;
  7041. Column: TsdViewColumn;
  7042. begin
  7043. Result := '';
  7044. V := GetValue(RecIndex, Col);
  7045. Column := FColumns.Items[Col];
  7046. if (V <> nil) and (Column <> nil) then
  7047. begin
  7048. Result := Column.FormatText(V, False);
  7049. end;
  7050. DoOnGetText(Result, GetRecord(RecIndex), V, Column, False);
  7051. end;
  7052. function TsdDataView.GetValue(RecIndex, Col: Integer): TsdValue;
  7053. var
  7054. bNeedLookupRecord: Boolean;
  7055. begin
  7056. Result := GetValue(RecIndex, Col, bNeedLookupRecord);
  7057. end;
  7058. function TsdDataView.GetValue(RecIndex, Col: Integer; var NeedLookupRecord: Boolean): TsdValue;
  7059. var
  7060. Rec, LookupRec: TsdDataRecord;
  7061. Column: TsdViewColumn;
  7062. begin
  7063. Result := nil;
  7064. Rec := Records[RecIndex];
  7065. NeedLookupRecord := False;
  7066. if Rec <> nil then
  7067. begin
  7068. Column := FColumns.Items[Col];
  7069. if not Column.IsLookup then
  7070. begin
  7071. {to do: 为什么会有为nil的情况? 为什么打开没有东西}
  7072. if Column.Field <> nil then
  7073. Result := Rec.Values[Column.Field.FieldNo];
  7074. end
  7075. else
  7076. begin
  7077. if (Column.LookupDataSet = nil) or (not Column.LookupDataSet.Active) then Exit;
  7078. LookupRec := Column.LookupDataSet.Locate(Column.LookupKeyFields, Rec.FieldValues[Column.KeyFields]);
  7079. if LookupRec <> nil then
  7080. Result := LookupRec.ValueByName(Column.LookupResultField)
  7081. else
  7082. NeedLookupRecord := True;
  7083. end;
  7084. end;
  7085. end;
  7086. function TsdDataView.Append(NeedBeginUpdate: Boolean): TsdDataRecord;
  7087. begin
  7088. Result := Insert(RecordCount, NeedBeginUpdate);
  7089. end;
  7090. procedure TsdDataView.LoadDefaultColumns;
  7091. var
  7092. I: Integer;
  7093. Column: TsdViewColumn;
  7094. begin
  7095. if FDataSet = nil then Exit;
  7096. FColumns.Clear;
  7097. for I := 0 to FDataSet.FieldCount - 1 do
  7098. begin
  7099. Column := FColumns.Add;
  7100. Column.FieldName := FDataSet.Fields[I].FieldName;
  7101. end;
  7102. end;
  7103. procedure TsdDataView.SetActive(const Value: Boolean);
  7104. begin
  7105. if (csReading in ComponentState) then
  7106. begin
  7107. FStreamedActive := Value;
  7108. Exit;
  7109. end;
  7110. if DataSet = nil then Exit;
  7111. if FActive = Value then Exit;
  7112. FActive := Value;
  7113. if Active then
  7114. begin
  7115. if not DataSet.Active then DataSet.Open;
  7116. FAutoGetFields := FColumns.Count = 0;
  7117. if FAutoGetFields then
  7118. LoadDefaultColumns;
  7119. ResetIndex;
  7120. FilterRecords;
  7121. //CurrentIndex := 0;
  7122. if IsDetail then
  7123. MasterChanged(FMasterDataView.Current);
  7124. if Assigned(FAfterOpen) then
  7125. FAfterOpen(Self);
  7126. end
  7127. else
  7128. begin
  7129. FCurrentIndex := 0;
  7130. FDataList.Clear;
  7131. FIndex := nil;
  7132. if FAutoGetFields then
  7133. FColumns.Clear;
  7134. if Assigned(FAfterClose) then
  7135. FAfterClose(Self);
  7136. end;
  7137. //LocateInControl(Records[0]);
  7138. NotifyControlActiveChanged;
  7139. end;
  7140. procedure TsdDataView.SetDataSet(const Value: TsdDataSet);
  7141. begin
  7142. if FDataSet = Value then Exit;
  7143. if Active then Active := False;
  7144. if FDataSet <> nil then FDataSet.UnregisterView(Self);
  7145. FDataSet := Value;
  7146. if FDataSet <> nil then
  7147. begin
  7148. if not (csReading in ComponentState) then
  7149. ReloadFields;
  7150. FDataSet.RegisterView(Self);
  7151. end;
  7152. NotifyControlDataViewChanged;
  7153. end;
  7154. procedure TsdDataView.SetFiltered(const Value: Boolean);
  7155. begin
  7156. FFiltered := Value;
  7157. FilterRecords;
  7158. NotifyControlDataViewChanged;
  7159. end;
  7160. procedure TsdDataView.SetIndexName(const Value: string);
  7161. begin
  7162. if SameText(Value, FIndexName) and (not ((Value <> '') and (FIndex = nil))) then Exit;
  7163. FIndexName := Value;
  7164. if (csReading in ComponentState) and (FDataSet = nil) then
  7165. Exit;
  7166. FIndex := FDataSet.FindIndex(FIndexName);
  7167. if Active then
  7168. FilterRecords;
  7169. NotifyControlDataViewChanged;
  7170. end;
  7171. procedure TsdDataView.SetOnFilterRecord(const Value: TsdAllowRecordEvent);
  7172. begin
  7173. FOnFilterRecord := Value;
  7174. end;
  7175. procedure TsdDataView.SetOnGetText(const Value: TsdColumnGetTextEvent);
  7176. begin
  7177. FOnGetText := Value;
  7178. end;
  7179. procedure TsdDataView.SetOnSetText(const Value: TsdColumnSetTextEvent);
  7180. begin
  7181. FOnSetText := Value;
  7182. end;
  7183. procedure TsdDataView.SetRange(const StartValues,
  7184. EndValues: array of const);
  7185. function VarRecByType(VarRec: TVarRec; FieldType: TFieldType): Variant;
  7186. begin
  7187. Result := Null;
  7188. case VarRec.VType of
  7189. vtBoolean:
  7190. Result := VarRec.VBoolean;
  7191. vtString:
  7192. Result := VarRec.VString^;
  7193. vtAnsiString:
  7194. Result := AnsiString(VarRec.VAnsiString);
  7195. vtWideString:
  7196. Result := WideString(VarRec.VWideString);
  7197. vtInteger:
  7198. Result := VarRec.VInteger;
  7199. vtExtended:
  7200. Result := VarRec.VExtended^;
  7201. vtCurrency:
  7202. Result := VarRec.VCurrency^;
  7203. vtVariant:
  7204. Result := VarRec.VVariant^;
  7205. end;
  7206. end;
  7207. var
  7208. I, iHigh: Integer;
  7209. List: TList;
  7210. begin
  7211. if not Active then Exit;
  7212. if FIndex = nil then
  7213. raise EsdDataView.Create('Can not set range without an index');
  7214. iHigh := High(StartValues);
  7215. if iHigh <> High(EndValues) then
  7216. raise EsdDataView.Create('Parameter number not matched');
  7217. { if iHigh = 1 then
  7218. begin
  7219. FRangeFrom := VarRecByType(StartValues[0], FIndex.Fields[0].DataType);
  7220. FRangeTo := VarRecByType(EndValues[0], FIndex.Fields[0].DataType);
  7221. end
  7222. else
  7223. begin }
  7224. if iHigh > FIndex.LevelCount - 1 then
  7225. iHigh := FIndex.LevelCount - 1;
  7226. FRangeFrom := VarArrayCreate([0, iHigh], varVariant);
  7227. for I := 0 to iHigh do
  7228. VarArrayPut(FRangeFrom, VarRecByType(StartValues[I], FIndex.Fields[I].DataType), [I]);
  7229. FRangeTo := VarArrayCreate([0, iHigh], varVariant);
  7230. for I := 0 to iHigh do
  7231. VarArrayPut(FRangeTo, VarRecByType(EndValues[I], FIndex.Fields[I].DataType), [I]);
  7232. // end;
  7233. if DataSet.RecordCount = 0 then
  7234. begin
  7235. ResetCurrent;
  7236. CurrentIndex := 0;
  7237. Exit;
  7238. end;
  7239. RefreshRange;
  7240. end;
  7241. procedure TsdDataView.SetText(RecIndex, Col: Integer; const Value: string);
  7242. var
  7243. V: TsdValue;
  7244. strValue: string;
  7245. bAllow, bNeedLookupRecord: Boolean;
  7246. begin
  7247. strValue := Value;
  7248. FDataSet.FCurrentView := Self;
  7249. V := GetValue(RecIndex, Col, bNeedLookupRecord);
  7250. try
  7251. if Assigned(V) then
  7252. begin
  7253. if Assigned(FDataSet.FEventRec) and (FDataSet.FEventRec <> V.Owner) then
  7254. raise EsdDataView.Create('DataSet.FEventRec is assigned');
  7255. FDataSet.FEventRec := V.Owner;
  7256. end;
  7257. SetValueText(V, Records[RecIndex], strValue, Columns[Col]);
  7258. if (not Assigned(V)) and bNeedLookupRecord then
  7259. AddLookupRecord(RecIndex, Col, strValue);
  7260. finally
  7261. if (V = nil) or (not V.Owner.IsUpdating) then
  7262. begin
  7263. FDataSet.FCurrentView := nil;
  7264. FDataSet.FEventRec := nil;
  7265. end;
  7266. end;
  7267. end;
  7268. procedure TsdDataView.FreeNotify;
  7269. begin
  7270. DataSet := nil;
  7271. end;
  7272. // zhangyin 2014-10-21 SetRange时,全部范围用前一个0,后一个MaxInt
  7273. procedure TsdDataView.RefreshRange;
  7274. var
  7275. I, iFrom, iTo: Integer;
  7276. List: TList;
  7277. Rec: TsdDataRecord;
  7278. Flag: TsdIndexFlag;
  7279. begin
  7280. if RangeLocked then Exit;
  7281. Flag := sifNull;
  7282. InitRecords;
  7283. if FIndex = nil then
  7284. begin
  7285. iFrom := 0;
  7286. iTo := RecordCount - 1;
  7287. end
  7288. else
  7289. begin
  7290. if VarIsNull(FRangeFrom) then
  7291. iFrom := 0
  7292. else
  7293. begin
  7294. // sifLessThanMin: 比最前一个节点更靠前,则从-1开始
  7295. // sifMoreThanMax:开始点到比最后节点更靠后,则将iTo设为-1
  7296. Flag := FIndex.FindNearestKeyIndex(FRangeFrom, iFrom);
  7297. case Flag of
  7298. sifLessThanMin:
  7299. iFrom := 0;
  7300. end;
  7301. end;
  7302. if Flag = sifMoreThanMax then
  7303. iTo := -1
  7304. else
  7305. begin
  7306. if VarIsNull(FRangeTo) then
  7307. iTo := RecordCount - 1
  7308. else
  7309. // 这里要把索引节点自身包含的记录算上,注意要考虑没找到节点的情况
  7310. FIndex.FindNearestKeyIndex(FRangeTo, iTo, True);
  7311. end;
  7312. end;
  7313. List := TList.Create;
  7314. try
  7315. List.Assign(FDataList);
  7316. FDataList.Clear;
  7317. if iFrom >= 0 then
  7318. for I := iFrom to iTo do
  7319. begin
  7320. Rec := TsdDataRecord(List[I]);
  7321. if FilterRecord(Rec) then
  7322. FDataList.Add(Rec);
  7323. end;
  7324. finally
  7325. List.Free;
  7326. end;
  7327. DoCustomSort(FDataList);
  7328. if not DataSet.FKeepPosition then
  7329. begin
  7330. ResetCurrent;
  7331. CurrentIndex := 0;
  7332. end;
  7333. NotifyControlDataViewChanged;
  7334. NotifyDataChanged;
  7335. end;
  7336. function TsdDataView.CheckRange(ARecord: TsdDataRecord; AValue: TsdValue): Integer;
  7337. var
  7338. I, iFrom, iTo, iIndex, iPos: Integer;
  7339. Rec: TsdDataRecord;
  7340. Flag: TsdIndexFlag;
  7341. begin
  7342. Result := -1;
  7343. if RangeLocked then Exit;
  7344. if not Active then Exit;
  7345. if (AValue <> nil) and (FIndex <> nil) and (not FIndex.IsKeyField(AValue.FieldName)) then
  7346. Exit;
  7347. if FIndex = nil then
  7348. begin
  7349. if FDataList.IndexOf(ARecord) < 0 then
  7350. begin
  7351. if FilterRecord(ARecord) then
  7352. Result := FDataList.Add(ARecord);
  7353. end
  7354. else if FilterRecord(ARecord) then
  7355. Result := FDataList.IndexOf(ARecord)
  7356. else
  7357. FDataList.Remove(ARecord);
  7358. Exit;
  7359. end;
  7360. Flag := sifNull;
  7361. if VarIsNull(FRangeFrom) then
  7362. iFrom := 0
  7363. else
  7364. begin
  7365. // sifLessThanMin: 比最前一个节点更靠前,则从-1开始
  7366. // sifMoreThanMax:开始点到比最后节点更靠后,则将iTo设为-1
  7367. Flag := FIndex.FindNearestKeyIndex(FRangeFrom, iFrom);
  7368. case Flag of
  7369. sifLessThanMin:
  7370. iFrom := -1;
  7371. end;
  7372. end;
  7373. if Flag = sifMoreThanMax then
  7374. iTo := -1
  7375. else
  7376. begin
  7377. if VarIsNull(FRangeTo) then
  7378. // 为空需要放在最后,所以这里RecordCount不减1
  7379. iTo := FIndex.RecordCount
  7380. else
  7381. // 这里要把索引节点自身包含的记录算上,注意要考虑没找到节点的情况
  7382. FIndex.FindNearestKeyIndex(FRangeTo, iTo, True);
  7383. end;
  7384. iIndex := FIndex.IndexOf(ARecord);
  7385. //已存在先删除
  7386. if FDataList.IndexOf(ARecord) >= 0 then
  7387. FDataList.Remove(ARecord);
  7388. if (iIndex >= iFrom) and (iIndex <= iTo) then
  7389. begin
  7390. // 过滤
  7391. if not FilterRecord(ARecord) then Exit;
  7392. // 没有记录
  7393. if FDataList.Count = 0 then
  7394. begin
  7395. Result := FDataList.Add(ARecord);
  7396. // 新增记录 已指定CurrentIndex,则强制触发CurrentChanged事件
  7397. if ARecord.Inserting then
  7398. begin
  7399. if FCurrentIndex = -1 then
  7400. FCurrentIndex := 0;
  7401. if FCurrentIndex = 0 then
  7402. CheckCurrent(True);
  7403. end;
  7404. NotifyDataChanged;
  7405. Exit;
  7406. end;
  7407. // 是符合条件的第一条记录
  7408. Rec := Records[0];
  7409. if FIndex.CompareData(ARecord, Rec) <= 0 then
  7410. begin
  7411. FDataList.Insert(0, ARecord);
  7412. DoCustomSort(FDataList);
  7413. NotifyDataChanged;
  7414. Result := 0;
  7415. Exit;
  7416. end;
  7417. // 是符合条件的最后一条记录
  7418. Rec := Records[FDataList.Count - 1];
  7419. if FIndex.CompareData(Rec, ARecord) < 0 then
  7420. begin
  7421. Result := FDataList.Add(ARecord);
  7422. DoCustomSort(FDataList);
  7423. NotifyDataChanged;
  7424. Exit;
  7425. end;
  7426. iPos := -1;
  7427. I := iIndex - 1;
  7428. repeat
  7429. Rec := FIndex.Records[I];
  7430. if IndexOf(Rec) >= 0 then
  7431. begin
  7432. iPos := IndexOf(Rec);
  7433. Break;
  7434. end;
  7435. Dec(I);
  7436. until I < 0;
  7437. FDataList.Insert(iPos + 1, ARecord);
  7438. Result := iPos;
  7439. DoCustomSort(FDataList);
  7440. NotifyDataChanged;
  7441. (*Rec := FIndex.Records[iTo];
  7442. if Rec <> nil then
  7443. Result := FDataList.IndexOf(Rec);
  7444. if Result = -1 then
  7445. Result := FDataList.Count;
  7446. FDataList.Insert(Result, ARecord);*)
  7447. end;
  7448. end;
  7449. procedure TsdDataView.RegisterControl(Control: IsdViewControl);
  7450. begin
  7451. if FControlList.IndexOf(Control) < 0 then
  7452. FControlList.Add(Control);
  7453. end;
  7454. function TsdDataView.FindColumn(const AFieldName: string): TsdViewColumn;
  7455. begin
  7456. Result := FColumns.FindColumn(AFieldName);
  7457. end;
  7458. function TsdDataView.FilterRecord(ARecord: TsdDataRecord): Boolean;
  7459. begin
  7460. Result := True;
  7461. if FFiltered and (FFilter <> '') then
  7462. Result := FFilterHelper.Calc(ARecord);
  7463. if FFiltered and Assigned(FOnFilterRecord) then
  7464. FOnFilterRecord(ARecord, Result);
  7465. end;
  7466. function TsdDataView.Insert(Index: Integer; NeedBeginUpdate: Boolean): TsdDataRecord;
  7467. var
  7468. Rec: TsdDataRecord;
  7469. begin
  7470. Result := nil;
  7471. FDataSet.FCurrentView := Self;
  7472. try
  7473. Rec := DataSet.CreateRecord;
  7474. FDataSet.FEventRec := Rec;
  7475. Rec.SetInserting(True, NeedBeginUpdate);
  7476. Rec.BeginUpdate;
  7477. DataSet.InitRecord(Rec);
  7478. try
  7479. if DataSet.AddRecord(Rec, False) < 0 then
  7480. Exit;
  7481. // 保存当前记录以备后面检查当前记录是否改变
  7482. FOldCurrentIndex := CurrentIndex;
  7483. FOldCurrent := Current;
  7484. if FIndex <> nil then
  7485. FDataList.Insert(Index, Rec)
  7486. else
  7487. FDataList.Add(Rec);
  7488. // 注意Insert的记录必须在此事件中处理索引字段值
  7489. DoBeforeSortAddedRecord(Rec);
  7490. { // EndUpdate中已经处理
  7491. if not Rec.IsUpdating then
  7492. begin
  7493. DataSet.CheckIndex(Rec, nil);
  7494. DataSet.Changed(Rec, sroAdd);
  7495. end; }
  7496. finally
  7497. // 如需BeginUpadte,则在外部EndUpdate
  7498. if not NeedBeginUpdate then
  7499. Rec.EndUpdate;
  7500. end;
  7501. // if Assigned(FAfterAddRecord) then
  7502. // FAfterAddRecord(Rec);
  7503. Result := Rec;
  7504. finally
  7505. if not Rec.IsUpdating then
  7506. begin
  7507. FDataSet.FCurrentView := nil;
  7508. FDataSet.FEventRec := nil;
  7509. end;
  7510. if not NeedBeginUpdate then
  7511. Rec.SetInserting(False, NeedBeginUpdate);
  7512. end;
  7513. end;
  7514. procedure TsdDataView.SetAfterAddRecord(const Value: TsdRecordEvent);
  7515. begin
  7516. FAfterAddRecord := Value;
  7517. end;
  7518. procedure TsdDataView.SetAfterDeleteRecord(const Value: TsdRecordEvent);
  7519. begin
  7520. FAfterDeleteRecord := Value;
  7521. end;
  7522. procedure TsdDataView.SetAfterValueChanged(const Value: TsdValueEvent);
  7523. begin
  7524. FAfterValueChanged := Value;
  7525. end;
  7526. procedure TsdDataView.SetBeforeAddRecord(const Value: TsdAllowRecordEvent);
  7527. begin
  7528. FBeforeAddRecord := Value;
  7529. end;
  7530. procedure TsdDataView.SetBeforeDeleteRecord(
  7531. const Value: TsdAllowRecordEvent);
  7532. begin
  7533. FBeforeDeleteRecord := Value;
  7534. end;
  7535. procedure TsdDataView.SetBeforeValueChange(
  7536. const Value: TsdAllowValueEvent);
  7537. begin
  7538. FBeforeValueChange := Value;
  7539. end;
  7540. procedure TsdDataView.SetBeforeSortAddedRecord(
  7541. const Value: TsdRecordEvent);
  7542. begin
  7543. FBeforeSortAddedRecord := Value;
  7544. end;
  7545. function TsdDataView.IndexOf(ARecord: TsdDataRecord): Integer;
  7546. begin
  7547. Result := FDataList.IndexOf(ARecord);
  7548. end;
  7549. procedure TsdDataView.GetFieldNames(AFieldNames: TStringList);
  7550. var
  7551. I: Integer;
  7552. begin
  7553. AFieldNames.Clear;
  7554. for I := 0 to FColumns.Count - 1 do
  7555. AFieldNames.Add(FColumns[I].FieldName);
  7556. end;
  7557. procedure TsdDataView.SetColumns(const Value: TsdViewColumnList);
  7558. begin
  7559. FColumns.Assign(Value);
  7560. end;
  7561. procedure TsdDataView.Loaded;
  7562. begin
  7563. inherited Loaded;
  7564. try
  7565. ReloadFields;
  7566. IndexName := FIndexName;
  7567. if FStreamedActive then
  7568. Active := True;
  7569. except
  7570. if csDesigning in ComponentState then
  7571. raise;
  7572. end;
  7573. end;
  7574. procedure TsdDataView.ReloadFields;
  7575. var
  7576. I: Integer;
  7577. begin
  7578. for I := 0 to Columns.Count - 1 do
  7579. Columns[I].FieldName := Columns[I].FieldName;
  7580. end;
  7581. procedure TsdDataView.UnRegisterControl(Control: IsdViewControl);
  7582. begin
  7583. FControlList.Remove(Control);
  7584. end;
  7585. procedure TsdDataView.Close;
  7586. begin
  7587. Active := False;
  7588. end;
  7589. procedure TsdDataView.Open;
  7590. begin
  7591. Active := True;
  7592. end;
  7593. procedure TsdDataView.RefreshFilter;
  7594. begin
  7595. Filtered := False;
  7596. Filtered := True;
  7597. end;
  7598. procedure TsdDataView.NotifyDataChanged(RecIndex: Integer);
  7599. begin
  7600. if not DataSet.ControlsDisabled then
  7601. NotifyControlDataChanged(RecIndex);
  7602. end;
  7603. procedure TsdDataView.SetAfterClose(const Value: TNotifyEvent);
  7604. begin
  7605. FAfterClose := Value;
  7606. end;
  7607. procedure TsdDataView.SetAfterOpen(const Value: TNotifyEvent);
  7608. begin
  7609. FAfterOpen := Value;
  7610. end;
  7611. procedure TsdDataView.DoAfterValueChanged(AValue: TsdValue);
  7612. begin
  7613. if Assigned(FAfterValueChanged) then
  7614. FAfterValueChanged(AValue);
  7615. end;
  7616. procedure TsdDataView.DoBeforeValueChange(AValue: TsdValue; const NewValue: Variant;
  7617. var Allow: Boolean);
  7618. begin
  7619. if Assigned(FBeforeValueChange) then
  7620. FBeforeValueChange(AValue, NewValue, Allow);
  7621. end;
  7622. procedure TsdDataView.DoOnGetText(var Text: string; ARecord: TsdDataRecord;
  7623. AValue: TsdValue; AColumn: TsdViewColumn; DisplayText: Boolean);
  7624. begin
  7625. if Assigned(ARecord) and (not ARecord.IsInEvent) and Assigned(FOnGetText) then
  7626. begin
  7627. ARecord.EnterEvent;
  7628. try
  7629. FOnGetText(Text, ARecord, AValue, AColumn, DisplayText);
  7630. finally
  7631. ARecord.ExitEvent;
  7632. end;
  7633. end;
  7634. end;
  7635. procedure TsdDataView.DoOnSetText(var Text: string; ARecord: TsdDataRecord;
  7636. AValue: TsdValue; AColumn: TsdViewColumn; var Allow: Boolean);
  7637. begin
  7638. if (not ARecord.IsInEvent) and Assigned(FOnSetText) then
  7639. begin
  7640. ARecord.EnterEvent;
  7641. try
  7642. FOnSetText(Text, ARecord, AValue, AColumn, Allow);
  7643. finally
  7644. ARecord.ExitEvent;
  7645. end;
  7646. end;
  7647. end;
  7648. function TsdDataView.LocateInControl(ARecord: TsdDataRecord): Boolean;
  7649. var
  7650. I: Integer;
  7651. begin
  7652. Result := False;
  7653. I := IndexOf(ARecord);
  7654. // zhangyin 2016-09-25
  7655. // 很多地方需要刷新当前记录的子项,并且TDataSet.Locate也是不管有没有变化的
  7656. // 所以这里屏蔽掉判断
  7657. //if (I <> CurrentIndex) or (ARecord <> Current) then
  7658. begin
  7659. CurrentIndex := I;
  7660. Result := Current <> nil;
  7661. end;
  7662. end;
  7663. function TsdDataView.LocateInControl(const KeyFields: string;
  7664. const KeyValues: Variant): Boolean;
  7665. var
  7666. Rec: TsdDataRecord;
  7667. begin
  7668. Rec := Locate(KeyFields, KeyValues);
  7669. Result := (Rec <> nil);
  7670. if Result then
  7671. Result := LocateInControl(Rec);
  7672. end;
  7673. function TsdDataView.GetCurrent: TsdDataRecord;
  7674. begin
  7675. Result := Records[CurrentIndex];
  7676. end;
  7677. {var
  7678. C: IsdViewControl;
  7679. begin
  7680. Result := nil;
  7681. if FControlList.Count = 0 then Exit;
  7682. C := IsdViewControl(FControlList[0]);
  7683. if C <> nil then
  7684. begin
  7685. Result := Records[C.ActiveRecord];
  7686. end;
  7687. end; }
  7688. procedure TsdDataView.SetOnCurrentChanged(const Value: TsdRecordEvent);
  7689. begin
  7690. FOnCurrentChanged := Value;
  7691. end;
  7692. procedure TsdDataView.RefreshField(AViewColumn: TsdViewColumn);
  7693. begin
  7694. NotifyControlFieldChanged(AViewColumn.FieldName);
  7695. end;
  7696. function TsdDataView.Remove(ARecord: TsdDataRecord): Boolean;
  7697. begin
  7698. FDataSet.FCurrentView := Self;
  7699. FDataSet.FEventRec := ARecord;
  7700. try
  7701. Result := FDataSet.RemoveRecord(ARecord);
  7702. finally
  7703. FDataSet.FCurrentView := nil;
  7704. FDataSet.FEventRec := nil;
  7705. end;
  7706. end;
  7707. procedure TsdDataView.AddLookupRecord(ARecIndex, ACol: Integer; Text: string);
  7708. var
  7709. Rec, LookupRec: TsdDataRecord;
  7710. Column: TsdViewColumn;
  7711. begin
  7712. Rec := Records[ARecIndex];
  7713. if Rec <> nil then
  7714. begin
  7715. Column := FColumns.Items[ACol];
  7716. if Column.IsLookup and Assigned(FOnNeedLookupRecord) then
  7717. FOnNeedLookupRecord(Rec, Column, Text);
  7718. end;
  7719. end;
  7720. procedure TsdDataView.SetOnNeedLookupRecord(
  7721. const Value: TsdNeedLookupRecordEvent);
  7722. begin
  7723. FOnNeedLookupRecord := Value;
  7724. end;
  7725. procedure TsdDataView.NotifyControlActiveChanged;
  7726. var
  7727. I: Integer;
  7728. begin
  7729. for I := 0 to FControlList.Count - 1 do
  7730. IsdViewControl(FControlList[I]).ActiveChanged;
  7731. end;
  7732. procedure TsdDataView.NotifyControlActiveRecordChanged(RecIndex: Integer);
  7733. var
  7734. I: Integer;
  7735. begin
  7736. for I := 0 to FControlList.Count - 1 do
  7737. IsdViewControl(FControlList[I]).ActiveRecordChanged(RecIndex);
  7738. end;
  7739. procedure TsdDataView.NotifyControlDataViewChanged;
  7740. var
  7741. I: Integer;
  7742. begin
  7743. for I := 0 to FControlList.Count - 1 do
  7744. IsdViewControl(FControlList[I]).DataViewChanged;
  7745. end;
  7746. procedure TsdDataView.NotifyControlFieldChanged(AFieldName: string);
  7747. var
  7748. I: Integer;
  7749. begin
  7750. for I := 0 to FControlList.Count - 1 do
  7751. IsdViewControl(FControlList[I]).FieldChanged(AFieldName);
  7752. end;
  7753. procedure TsdDataView.NotifyControlDataChanged(RecIndex: Integer);
  7754. var
  7755. I: Integer;
  7756. begin
  7757. for I := 0 to FControlList.Count - 1 do
  7758. IsdViewControl(FControlList[I]).DataChanged(RecIndex);
  7759. end;
  7760. procedure TsdDataView.SetValueText(AValue: TsdValue; ARecord: TsdDataRecord; var Text: string; AColumn: TsdViewColumn);
  7761. var
  7762. bAllow: Boolean;
  7763. pData, pCache: Pointer;
  7764. vValue: Variant;
  7765. iLength: Integer;
  7766. bNoNull: Boolean;
  7767. bIsLookup: Boolean;
  7768. begin
  7769. bAllow := True;
  7770. // 让没有字段对应的列也能触发SetText事件
  7771. if AValue = nil then
  7772. begin
  7773. DoOnSetText(Text, ARecord, AValue, AColumn, bAllow);
  7774. Exit;
  7775. end;
  7776. pData := nil;
  7777. pCache := AValue.CopyCache;
  7778. try
  7779. bIsLookup := AValue.Owner <> ARecord;
  7780. // 这样保证Lookup字段也能触发当前DataView事件
  7781. if bIsLookup then
  7782. AValue.Owner.Owner.FCurrentView := Self;
  7783. // 节约内存,有变化时才缓存原始值
  7784. AValue.CacheOriginalValue;
  7785. // 考虑有Lookup的情况存在,必须将DataView中对应的Record传进DoOnSetText
  7786. DoOnSetText(Text, ARecord, AValue, AColumn, bAllow);
  7787. if not bAllow then
  7788. begin
  7789. AValue.Owner.Owner.FCurrentView := nil;
  7790. Exit;
  7791. end;
  7792. AValue.ConvertDataBeforeWriteData(Text, pData, vValue, iLength, bNoNull);
  7793. if not AValue.CanWriteData(pData, pCache, iLength, bNoNull) then
  7794. begin
  7795. // 多个字段写入时,由EndUpdate负责这一句
  7796. if not AValue.Owner.IsUpdating then
  7797. AValue.Owner.Owner.FCurrentView := nil;
  7798. Exit;
  7799. end;
  7800. bAllow := True;
  7801. AValue.Owner.Owner.DoBeforeValueChange(AValue, vValue, bAllow);
  7802. if not bAllow then
  7803. begin
  7804. AValue.Owner.Owner.FCurrentView := nil;
  7805. Exit;
  7806. end;
  7807. AValue.InnerWriteData(pData, vValue, iLength, bNoNull);
  7808. AValue.Owner.Owner.DoAfterValueChanged(AValue);
  7809. AValue.Owner.Changed(AValue);
  7810. finally
  7811. if bIsLookup then
  7812. AValue.Owner.Owner.FCurrentView := nil;
  7813. if Assigned(pData) then
  7814. FreeMem(pData);
  7815. AValue.ClearCache(pCache);
  7816. end;
  7817. end;
  7818. function TsdDataView.GetColumns(Index: Integer): TsdViewColumn;
  7819. begin
  7820. Result := Columns[Index];
  7821. end;
  7822. procedure TsdDataView.SaveToXML(AFileName: string);
  7823. var
  7824. xmlDoc: IXMLDocument;
  7825. vRoot, vItem: IXMLNode;
  7826. I, J: Integer;
  7827. Rec: TsdDataRecord;
  7828. begin
  7829. xmlDoc := TXMLDocument.Create(nil) as IXMLDocument;
  7830. try
  7831. xmlDoc.Active := True;
  7832. xmlDoc.Encoding := 'gb2312';
  7833. xmlDoc.Options := xmlDoc.Options + [doAttrNull, doNodeAutoIndent];
  7834. vRoot := xmlDoc.AddChild('SmartDataView_data_list');
  7835. vRoot.Attributes['DataSet'] := Name;
  7836. for I := 0 to RecordCount - 1 do
  7837. begin
  7838. Rec := Records[I];
  7839. vItem := vRoot.AddChild('Record');
  7840. for J := 0 to FieldCount - 1 do
  7841. vItem.Attributes[Columns[J].FieldName] := Rec.Values[Columns[J].Field.FieldNo].Value;
  7842. end;
  7843. xmlDoc.SaveToFile(AFileName);
  7844. finally
  7845. xmlDoc := nil;
  7846. end;
  7847. end;
  7848. procedure TsdDataView.BeginLockRange;
  7849. begin
  7850. Inc(FRangeLock);
  7851. end;
  7852. procedure TsdDataView.EndLockRange(ARefresh: Boolean);
  7853. begin
  7854. if FRangeLock > 0 then
  7855. Dec(FRangeLock);
  7856. if ARefresh and (FRangeLock = 0) then
  7857. RefreshRange;
  7858. end;
  7859. function TsdDataView.GetRangeLocked: Boolean;
  7860. begin
  7861. Result := FRangeLock > 0;
  7862. end;
  7863. procedure TsdDataView.DoBeforeAddRecord(ARecord: TsdDataRecord;
  7864. var Allow: Boolean);
  7865. begin
  7866. if Assigned(FBeforeAddRecord) then
  7867. FBeforeAddRecord(ARecord, Allow);
  7868. end;
  7869. procedure TsdDataView.DoAfterAddRecord(ARecord: TsdDataRecord);
  7870. begin
  7871. if Assigned(FAfterAddRecord) then
  7872. FAfterAddRecord(ARecord);
  7873. end;
  7874. procedure TsdDataView.SetAfterRecordChanged(const Value: TsdRecordEvent);
  7875. begin
  7876. FAfterRecordChanged := Value;
  7877. end;
  7878. procedure TsdDataView.DoAfterRecordChanged(ARecord: TsdDataRecord);
  7879. begin
  7880. if Assigned(FAfterRecordChanged) then
  7881. FAfterRecordChanged(ARecord);
  7882. end;
  7883. function TsdDataView.Locate(const KeyFields: string;
  7884. const KeyValues: Variant): TsdDataRecord;
  7885. var
  7886. KeyCount, I, J: Integer;
  7887. Value: TsdValue;
  7888. V, VR: Variant;
  7889. bFound: Boolean;
  7890. NameList: TStringList;
  7891. FieldNoList: TList;
  7892. Col: TsdViewColumn;
  7893. Field: TsdField;
  7894. Rec: TsdDataRecord;
  7895. begin
  7896. Result := nil;
  7897. if VarIsArray(KeyValues) then
  7898. KeyCount := VarArrayHighBound(KeyValues, 1) - VarArrayLowBound(KeyValues, 1) + 1
  7899. else
  7900. KeyCount := 1;
  7901. FieldNoList := TList.Create;
  7902. try
  7903. NameList := TStringList.Create;
  7904. try
  7905. NameList.Delimiter := ';';
  7906. NameList.DelimitedText := KeyFields;
  7907. if NameList.Count <> KeyCount then
  7908. raise EsdDataView.Create('Fields do not match values');
  7909. for I := 0 to NameList.Count - 1 do
  7910. begin
  7911. Col := FindColumn(NameList[I]);
  7912. if Col = nil then
  7913. raise EsdDataView.Create(Format('Can not find column ''%s''', [NameList[I]]));
  7914. Field := Col.FField;
  7915. if Field = nil then
  7916. raise EsdDataView.Create(Format('Can not find field ''%s''', [NameList[I]]));
  7917. FieldNoList.Add(Pointer(Field.FieldNo));
  7918. end;
  7919. finally
  7920. NameList.Free;
  7921. end;
  7922. for I := 0 to FDataList.Count - 1 do
  7923. begin
  7924. bFound := True;
  7925. Rec := Records[I];
  7926. for J := 0 to KeyCount - 1 do
  7927. begin
  7928. if VarIsArray(KeyValues) then
  7929. V := KeyValues[J]
  7930. else
  7931. V := KeyValues;
  7932. Value := Rec.Values[Integer(FieldNoList[J])];
  7933. if Value.Field.IsVarField then
  7934. begin
  7935. if VarIsNull(V) then
  7936. V := '';
  7937. if Value.IsNull then
  7938. VR := ''
  7939. else
  7940. VR := Value.Value;
  7941. end
  7942. else
  7943. VR := Value.Value;
  7944. if V <> VR then
  7945. begin
  7946. bFound := False;
  7947. Break;
  7948. end;
  7949. end;
  7950. if bFound then
  7951. begin
  7952. Result := Rec;
  7953. Break;
  7954. end;
  7955. end;
  7956. finally
  7957. FieldNoList.Free;
  7958. end;
  7959. end;
  7960. function TsdDataView.Exchange(const Index1, Index2: Integer): Integer;
  7961. var
  7962. Rec1, Rec2: TsdDataRecord;
  7963. begin
  7964. Result := -1;
  7965. if FIndex = nil then Exit;
  7966. Rec1 := Records[Index1];
  7967. Rec2 := Records[Index2];
  7968. Result := FIndex.Exchange(Rec1, Rec2);
  7969. if FCurrentIndex = Index1 then
  7970. FCurrentIndex := Index2
  7971. else if FCurrentIndex = Index2 then
  7972. FCurrentIndex := Index1;
  7973. ChangeCurrent;
  7974. end;
  7975. procedure TsdDataView.Edit(ARecord: TsdDataRecord);
  7976. begin
  7977. DataSet.FCurrentView := Self;
  7978. DataSet.FEventRec := ARecord;
  7979. end;
  7980. procedure TsdDataView.ChangeCurrent;
  7981. var
  7982. I: Integer;
  7983. begin
  7984. for I := 0 to FDetailList.Count - 1 do
  7985. TsdDataView(FDetailList[I]).MasterChanged(Current);
  7986. // to do: 一个DataView有多个DBA时,每个DBA都会触发这个方法,需优化。但这种情况不多,暂不花精力。
  7987. DoOnCurrentChanged(Current);
  7988. end;
  7989. procedure TsdDataView.DoBeforeSortAddedRecord(ARecord: TsdDataRecord);
  7990. begin
  7991. if Assigned(ARecord) and (not ARecord.IsInEvent) and Assigned(FBeforeSortAddedRecord) then
  7992. begin
  7993. ARecord.EnterEvent;
  7994. try
  7995. FBeforeSortAddedRecord(ARecord);
  7996. finally
  7997. ARecord.ExitEvent;
  7998. end;
  7999. end;
  8000. end;
  8001. function TsdDataView.GetCurrentIndex: Integer;
  8002. begin
  8003. Result := FCurrentIndex;
  8004. end;
  8005. procedure TsdDataView.SetCurrentIndex(const Value: Integer);
  8006. var
  8007. bChanged: Boolean;
  8008. begin
  8009. bChanged := False;
  8010. if Active and (FCurrentIndex <> Value) then
  8011. begin
  8012. DoBeforeCurrentChange(Current);
  8013. FCurrentIndex := Value;
  8014. bChanged := True;
  8015. //ChangeCurrent;
  8016. end;
  8017. // 不管有没有变化都通知,以防出现DataView和IDTree不同步的情况
  8018. if Active then
  8019. NotifyControlActiveRecordChanged(FCurrentIndex);
  8020. // zhangyin 2021-01-8 先通知控件,再触发CurrentChanged事件,保证在事件中使用树时能获得正确的当前节点
  8021. if bChanged then
  8022. ChangeCurrent;
  8023. end;
  8024. procedure TsdDataView.CheckCurrent(AReset: Boolean);
  8025. var
  8026. iCurrent: Integer;
  8027. begin
  8028. if RecordCount > 0 then
  8029. begin
  8030. // 此套逻辑是为树结构准备,因为DataView不知道树结构,删除当前行时无法给出合理的新当前行
  8031. // 所以必须由树结构在删除记录前调用PrepareNewCurrent通知DataView新当前行
  8032. if FNewCurrent <> nil then
  8033. begin
  8034. iCurrent := IndexOf(FNewCurrent);
  8035. FNewCurrent := nil;
  8036. ResetCurrent;
  8037. CurrentIndex := iCurrent;
  8038. end
  8039. else if FCurrentIndex >= RecordCount then
  8040. CurrentIndex := RecordCount - 1
  8041. else if AReset then
  8042. ChangeCurrent;
  8043. end
  8044. else
  8045. CurrentIndex := -1;
  8046. end;
  8047. procedure TsdDataView.PrepareNewCurrent(ARecord: TsdDataRecord);
  8048. begin
  8049. FNewCurrent := ARecord;
  8050. end;
  8051. procedure TsdDataView.ResetCurrent;
  8052. begin
  8053. FCurrentIndex := -1;
  8054. end;
  8055. procedure TsdDataView.MasterChanged(ACurrent: TsdDataRecord);
  8056. var
  8057. MasterValue: Variant;
  8058. begin
  8059. if not Active then Exit;
  8060. if not IsDetail then Exit;
  8061. if ACurrent = nil then
  8062. SetRange([Null], [Null])
  8063. else if (FMasterField <> '') and (ACurrent.ValueByName(FMasterField) <> nil) then
  8064. begin
  8065. MasterValue := ACurrent.ValueByName(FMasterField).Value;
  8066. SetRange([MasterValue], [MasterValue]);
  8067. end;
  8068. end;
  8069. procedure TsdDataView.SetKeyField(const Value: string);
  8070. begin
  8071. FKeyField := Value;
  8072. end;
  8073. procedure TsdDataView.SetMasterDataView(const Value: TsdDataView);
  8074. begin
  8075. if FMasterDataView <> Value then
  8076. begin
  8077. if FMasterDataView <> nil then
  8078. FMasterDataView.UnRegisterDetail(Self);
  8079. FMasterDataView := Value;
  8080. FMasterDataView.RegisterDetail(Self);
  8081. if Active then MasterChanged(FMasterDataView.Current);
  8082. end;
  8083. end;
  8084. procedure TsdDataView.SetMasterField(const Value: string);
  8085. begin
  8086. FMasterField := Value;
  8087. end;
  8088. procedure TsdDataView.RegisterDetail(ADetail: TsdDataView);
  8089. begin
  8090. if FDetailList.IndexOf(ADetail) < 0 then
  8091. FDetailList.Add(ADetail);
  8092. end;
  8093. procedure TsdDataView.UnRegisterDetail(ADetail: TsdDataView);
  8094. begin
  8095. if FDetailList.IndexOf(ADetail) >= 0 then
  8096. FDetailList.Remove(ADetail);
  8097. end;
  8098. procedure TsdDataView.ClearMasterDataView;
  8099. begin
  8100. FMasterDataView := nil;
  8101. end;
  8102. function TsdDataView.IsDetail: Boolean;
  8103. begin
  8104. Result := (FMasterDataView <> nil) and (FIndex <> nil)
  8105. and FIndex.HasKeyFields(FKeyField);
  8106. end;
  8107. procedure TsdDataView.SetFilter(const Value: string);
  8108. begin
  8109. FFilter := Value;
  8110. end;
  8111. procedure TsdDataView.ParseFilter;
  8112. begin
  8113. FFilterHelper.ParseExpression(FFilter);
  8114. end;
  8115. procedure TsdDataView.DoAfterDeleteRecord(ARecord: TsdDataRecord);
  8116. begin
  8117. if Assigned(FAfterDeleteRecord) then
  8118. FAfterDeleteRecord(ARecord);
  8119. end;
  8120. procedure TsdDataView.DoBeforeDeleteRecord(ARecord: TsdDataRecord;
  8121. var Allow: Boolean);
  8122. begin
  8123. if Assigned(FBeforeDeleteRecord) then
  8124. FBeforeDeleteRecord(ARecord, Allow);
  8125. end;
  8126. procedure TsdDataView.First;
  8127. begin
  8128. if RecordCount > 0 then
  8129. CurrentIndex := 0;
  8130. end;
  8131. procedure TsdDataView.Last;
  8132. begin
  8133. if RecordCount > 0 then
  8134. CurrentIndex := RecordCount - 1;
  8135. end;
  8136. procedure TsdDataView.DoCustomSort(RecordList: TList);
  8137. begin
  8138. if Assigned(FOnCustomSort) then
  8139. FOnCustomSort(RecordList);
  8140. end;
  8141. procedure TsdDataView.SetOnCustomSort(const Value: TsdCustomSortEvent);
  8142. begin
  8143. FOnCustomSort := Value;
  8144. end;
  8145. procedure TsdDataView.DoOnCurrentChanged(ARecord: TsdDataRecord);
  8146. begin
  8147. FCurrentChanging := False;
  8148. if Assigned(FOnCurrentChanged) then
  8149. FOnCurrentChanged(ARecord);
  8150. end;
  8151. procedure TsdDataView.DoBeforeCurrentChange(ARecord: TsdDataRecord);
  8152. begin
  8153. if (not FCurrentChanging) and Assigned(FBeforeCurrentChange) then
  8154. begin
  8155. FBeforeCurrentChange(ARecord);
  8156. FCurrentChanging := True;
  8157. end;
  8158. end;
  8159. procedure TsdDataView.SetBeforeCurrentChange(const Value: TsdRecordEvent);
  8160. begin
  8161. FBeforeCurrentChange := Value;
  8162. end;
  8163. procedure TsdDataView.ResetIndex;
  8164. begin
  8165. if (csReading in ComponentState) and (FDataSet = nil) then
  8166. Exit;
  8167. FIndex := FDataSet.FindIndex(FIndexName);
  8168. end;
  8169. procedure TsdDataView.AssignRecords(AList: TList);
  8170. begin
  8171. AList.Assign(FDataList);
  8172. end;
  8173. { TsdAggregator }
  8174. function TsdAggregator.Aggregate(const KeyValues: Variant; const FieldName: string): Variant;
  8175. var
  8176. List: TList;
  8177. I: Integer;
  8178. Field: TsdField;
  8179. Rec: TsdDataRecord;
  8180. begin
  8181. Result := 0;
  8182. if (FDataSet = nil) or (not FDataSet.Active) then Exit;
  8183. FIndex := FDataSet.FindIndex(FIndexName);
  8184. if FIndex = nil then Exit;
  8185. List := TList.Create;
  8186. try
  8187. if FIndex.RecordsByKey(KeyValues, List) > 0 then
  8188. begin
  8189. Field := FDataSet.Fields.FieldByName(FieldName);
  8190. for I := 0 to List.Count - 1 do
  8191. begin
  8192. Rec := TsdDataRecord(List[I]);
  8193. Result := Result + Rec.Values[Field.FieldNo].AsVariant;
  8194. end;
  8195. end;
  8196. finally
  8197. List.Free;
  8198. end;
  8199. end;
  8200. constructor TsdAggregator.Create(AOwner: TComponent);
  8201. begin
  8202. inherited;
  8203. end;
  8204. destructor TsdAggregator.Destroy;
  8205. begin
  8206. inherited;
  8207. end;
  8208. procedure TsdAggregator.SetDataSet(const Value: TsdDataSet);
  8209. begin
  8210. FDataSet := Value;
  8211. end;
  8212. procedure TsdAggregator.SetIndexName(const Value: string);
  8213. begin
  8214. FIndexName := Value;
  8215. end;
  8216. { TsdDetailList }
  8217. procedure TsdDetailList.Add(ARecord: TsdDataRecord);
  8218. begin
  8219. FList.Add(ARecord);
  8220. end;
  8221. constructor TsdDetailList.Create(AMasterItem: TsdMasterItem);
  8222. begin
  8223. FMasterItem := AMasterItem;
  8224. FList := TList.Create;
  8225. end;
  8226. destructor TsdDetailList.Destroy;
  8227. begin
  8228. FList.Free;
  8229. inherited;
  8230. end;
  8231. function TsdDetailList.GetCount: Integer;
  8232. begin
  8233. Result := FList.Count;
  8234. end;
  8235. function TsdDetailList.GetRecords(Index: Integer): TsdDataRecord;
  8236. begin
  8237. Result := TsdDataRecord(FList[Index]);
  8238. end;
  8239. { TsdMasterItem }
  8240. procedure TsdMasterItem.AddDetailRec(ARecord: TsdDataRecord);
  8241. begin
  8242. FList.Add(ARecord);
  8243. end;
  8244. constructor TsdMasterItem.Create(AMap: TsdMasterDetailMap);
  8245. begin
  8246. FMap := AMap;
  8247. FList := TsdDetailList.Create(Self);
  8248. FMap.FList.Add(Self);
  8249. end;
  8250. destructor TsdMasterItem.Destroy;
  8251. begin
  8252. FList.Free;
  8253. inherited;
  8254. end;
  8255. function TsdMasterItem.GetCount: Integer;
  8256. begin
  8257. Result := FList.Count;
  8258. end;
  8259. function TsdMasterItem.GetRecords(Index: Integer): TsdDataRecord;
  8260. begin
  8261. Result := FList[Index];
  8262. end;
  8263. { TsdMasterDetailMap }
  8264. function TsdMasterDetailMap.CheckDetailIndex: Boolean;
  8265. begin
  8266. Result := False;
  8267. end;
  8268. function TsdMasterDetailMap.CheckMasterIndex: Boolean;
  8269. begin
  8270. Result := False;
  8271. end;
  8272. constructor TsdMasterDetailMap.Create;
  8273. begin
  8274. FList := TList.Create;
  8275. end;
  8276. procedure TsdMasterDetailMap.CreateMap;
  8277. var
  8278. I, J, iIndex, iMasterCount, iDetailCount: Integer;
  8279. MasterRec, DetailRec: TsdDataRecord;
  8280. MasterValue, DetailValue: Variant;
  8281. MasterItem: TsdMasterItem;
  8282. iResult: Integer;
  8283. begin
  8284. if FMasterField = '' then
  8285. raise EsdMasterDetailMap.Create('MasterField is null');
  8286. if FDetailField = '' then
  8287. raise EsdMasterDetailMap.Create('DetailField is null');
  8288. if not CheckMasterIndex then
  8289. raise EsdMasterDetailMap.Create('Can not find MasterIndex');
  8290. if not CheckDetailIndex then
  8291. raise EsdMasterDetailMap.Create('Can not find DetailIndex');
  8292. for I := 0 to Count - 1 do
  8293. Items[I].Free;
  8294. FList.Clear;
  8295. // 有序双列表遍历算法,一次遍历完成映射表
  8296. iIndex := 0;
  8297. iMasterCount := GetMasterRecordCount;
  8298. iDetailCount := GetDetailRecordCount;
  8299. for I := 0 to iMasterCount - 1 do
  8300. begin
  8301. MasterItem := TsdMasterItem.Create(Self);
  8302. MasterRec := GetMasterRecords(I);
  8303. MasterValue := MasterRec.ValueByName(FMasterField).Value;
  8304. MasterItem.FRec := MasterRec;
  8305. for J := iIndex to iDetailCount - 1 do
  8306. begin
  8307. DetailRec := GetDetailRecords(J);
  8308. CompareValues(MasterRec, DetailRec, iResult);
  8309. // 找到对应从表记录
  8310. if iResult = 0 then
  8311. MasterItem.AddDetailRec(DetailRec)
  8312. // 找过头了
  8313. else if iResult < 0 then
  8314. begin
  8315. iIndex := J;
  8316. Break;
  8317. end;
  8318. // 注意主表当前记录比从表大,则从表直接循环
  8319. end;
  8320. end;
  8321. end;
  8322. destructor TsdMasterDetailMap.Destroy;
  8323. begin
  8324. FList.Free;
  8325. inherited;
  8326. end;
  8327. procedure TsdMasterDetailMap.CompareValues(MasterRecord,
  8328. DetailRecord: TsdDataRecord; var AResult: Integer);
  8329. var
  8330. MasterValue, DetailValue: Variant;
  8331. begin
  8332. // 有事件则使用事件的对比
  8333. if Assigned(FOnCompareValues) then
  8334. FOnCompareValues(MasterRecord, DetailRecord, AResult)
  8335. else
  8336. begin
  8337. MasterValue := MasterRecord.ValueByName(FMasterField).Value;
  8338. DetailValue := DetailRecord.ValueByName(FDetailField).Value;
  8339. if MasterValue < DetailValue then
  8340. AResult := -1
  8341. else if MasterValue > DetailValue then
  8342. AResult := 1
  8343. else
  8344. AResult := 0;
  8345. end;
  8346. end;
  8347. function TsdMasterDetailMap.GetCount: Integer;
  8348. begin
  8349. Result := FList.Count;
  8350. end;
  8351. function TsdMasterDetailMap.GetItems(Index: Integer): TsdMasterItem;
  8352. begin
  8353. Result := TsdMasterItem(FList[Index]);
  8354. end;
  8355. procedure TsdMasterDetailMap.SetDetailField(const Value: string);
  8356. begin
  8357. FDetailField := Value;
  8358. end;
  8359. procedure TsdMasterDetailMap.SetMasterField(const Value: string);
  8360. begin
  8361. FMasterField := Value;
  8362. end;
  8363. procedure TsdMasterDetailMap.SetOnCompareValues(
  8364. const Value: TsdCompareValuesEvent);
  8365. begin
  8366. FOnCompareValues := Value;
  8367. end;
  8368. function TsdMasterDetailMap.ItemByRecord(
  8369. ARecord: TsdDataRecord): TsdMasterItem;
  8370. var
  8371. I, iIndex: Integer;
  8372. Item: TsdMasterItem;
  8373. begin
  8374. Result := nil;
  8375. if FMasterIndex <> nil then
  8376. begin
  8377. iIndex := FMasterIndex.IndexOf(ARecord);
  8378. Result := GetItems(iIndex);
  8379. end
  8380. else
  8381. begin
  8382. for I := 0 to FList.Count - 1 do
  8383. begin
  8384. Item := TsdMasterItem(FList[I]);
  8385. if Item.Rec = ARecord then
  8386. begin
  8387. Result := Item;
  8388. Break;
  8389. end;
  8390. end;
  8391. end;
  8392. end;
  8393. function TsdMasterDetailMap.ItemByDetailRecord(
  8394. ARecord: TsdDataRecord): TsdMasterItem;
  8395. var
  8396. Item: TsdMasterItem;
  8397. I: Integer;
  8398. begin
  8399. Result := nil;
  8400. for I := 0 to FList.Count - 1 do
  8401. begin
  8402. Item := TsdMasterItem(FList[I]);
  8403. if Item.Rec.ValueByName(FMasterField).Value =
  8404. ARecord.ValueByName(FDetailField).Value then
  8405. begin
  8406. Result := Item;
  8407. Break;
  8408. end;
  8409. end;
  8410. end;
  8411. function TsdMasterDetailMap.RecordByDetailRecord(
  8412. ARecord: TsdDataRecord): TsdDataRecord;
  8413. var
  8414. Item: TsdMasterItem;
  8415. begin
  8416. Result := nil;
  8417. Item := ItemByDetailRecord(ARecord);
  8418. if Item <> nil then
  8419. Result := Item.Rec;
  8420. end;
  8421. { TsdDataSetMasterDetailMap }
  8422. function TsdDataSetMasterDetailMap.CheckDetailIndex: Boolean;
  8423. begin
  8424. if FDetailDataSet = nil then
  8425. raise EsdMasterDetailMap.Create('DetailDataSet is nil');
  8426. FDetailIndex := FDetailDataSet.IndexList.FindByKeyFields(DetailField, True);
  8427. Result := FDetailIndex <> nil;
  8428. end;
  8429. function TsdDataSetMasterDetailMap.CheckMasterIndex: Boolean;
  8430. begin
  8431. if FMasterDataSet = nil then
  8432. raise EsdMasterDetailMap.Create('MasterDataSet is nil');
  8433. FMasterIndex := FMasterDataSet.IndexList.FindByKeyFields(MasterField, True);
  8434. Result := FMasterIndex <> nil;
  8435. end;
  8436. function TsdDataSetMasterDetailMap.GetDetailRecordCount: Integer;
  8437. begin
  8438. Result := FDetailDataSet.RecordCount;
  8439. end;
  8440. function TsdDataSetMasterDetailMap.GetDetailRecords(
  8441. AIndex: Integer): TsdDataRecord;
  8442. begin
  8443. Result := FDetailIndex.Records[AIndex];
  8444. end;
  8445. function TsdDataSetMasterDetailMap.GetMasterRecordCount: Integer;
  8446. begin
  8447. Result := FMasterDataSet.RecordCount;
  8448. end;
  8449. function TsdDataSetMasterDetailMap.GetMasterRecords(
  8450. AIndex: Integer): TsdDataRecord;
  8451. begin
  8452. Result := FMasterIndex.Records[AIndex];
  8453. end;
  8454. procedure TsdDataSetMasterDetailMap.SetDetailDataSet(
  8455. const Value: TsdDataSet);
  8456. begin
  8457. FDetailDataSet := Value;
  8458. end;
  8459. procedure TsdDataSetMasterDetailMap.SetMasterDataSet(
  8460. const Value: TsdDataSet);
  8461. begin
  8462. FMasterDataSet := Value;
  8463. end;
  8464. { TsdDataViewMasterDetailMap }
  8465. function TsdDataViewMasterDetailMap.CheckDetailIndex: Boolean;
  8466. begin
  8467. if FDetailDataView = nil then
  8468. raise EsdMasterDetailMap.Create('DetailDataView is nil');
  8469. FDetailIndex := nil;
  8470. if FDetailDataView.FIndex.HasKeyFields(DetailField) then
  8471. FDetailIndex := FDetailDataView.FIndex;
  8472. Result := FDetailIndex <> nil;
  8473. end;
  8474. function TsdDataViewMasterDetailMap.CheckMasterIndex: Boolean;
  8475. begin
  8476. if FMasterDataView = nil then
  8477. raise EsdMasterDetailMap.Create('DetailDataView is nil');
  8478. FMasterIndex := nil;
  8479. if FMasterDataView.FIndex.HasKeyFields(MasterField) then
  8480. FMasterIndex := FMasterDataView.FIndex;
  8481. Result := FMasterIndex <> nil;
  8482. end;
  8483. function TsdDataViewMasterDetailMap.GetDetailRecordCount: Integer;
  8484. begin
  8485. if FDetailIndex <> nil then
  8486. Result := FDetailDataView.RecordCount
  8487. else
  8488. Result := 0;
  8489. end;
  8490. function TsdDataViewMasterDetailMap.GetDetailRecords(
  8491. AIndex: Integer): TsdDataRecord;
  8492. begin
  8493. if FDetailIndex <> nil then
  8494. Result := FDetailDataView[AIndex]
  8495. else
  8496. Result := nil;
  8497. end;
  8498. function TsdDataViewMasterDetailMap.GetMasterRecordCount: Integer;
  8499. begin
  8500. if FMasterIndex <> nil then
  8501. Result := FMasterDataView.RecordCount
  8502. else
  8503. Result := 0;
  8504. end;
  8505. function TsdDataViewMasterDetailMap.GetMasterRecords(
  8506. AIndex: Integer): TsdDataRecord;
  8507. begin
  8508. if FMasterIndex <> nil then
  8509. Result := FMasterDataView[AIndex]
  8510. else
  8511. Result := nil;
  8512. end;
  8513. procedure TsdDataViewMasterDetailMap.SetDetailDataView(
  8514. const Value: TsdDataView);
  8515. begin
  8516. FDetailDataView := Value;
  8517. end;
  8518. procedure TsdDataViewMasterDetailMap.SetMasterDataView(
  8519. const Value: TsdDataView);
  8520. begin
  8521. FMasterDataView := Value;
  8522. end;
  8523. { TsdListMasterDetailMap }
  8524. function TsdListMasterDetailMap.CheckDetailIndex: Boolean;
  8525. begin
  8526. FDetailIndex := nil;
  8527. Result := True;
  8528. end;
  8529. function TsdListMasterDetailMap.CheckMasterIndex: Boolean;
  8530. begin
  8531. FMasterIndex := nil;
  8532. Result := True;
  8533. end;
  8534. function TsdListMasterDetailMap.GetDetailRecordCount: Integer;
  8535. begin
  8536. Result := FDetailList.Count;
  8537. end;
  8538. function TsdListMasterDetailMap.GetDetailRecords(
  8539. AIndex: Integer): TsdDataRecord;
  8540. begin
  8541. Result := TsdDataRecord(FDetailList[AIndex]);
  8542. end;
  8543. function TsdListMasterDetailMap.GetMasterRecordCount: Integer;
  8544. begin
  8545. Result := FMasterList.Count;
  8546. end;
  8547. function TsdListMasterDetailMap.GetMasterRecords(
  8548. AIndex: Integer): TsdDataRecord;
  8549. begin
  8550. Result := TsdDataRecord(FMasterList[AIndex]);
  8551. end;
  8552. procedure TsdListMasterDetailMap.SetDetailList(const Value: TList);
  8553. begin
  8554. FDetailList := Value;
  8555. end;
  8556. procedure TsdListMasterDetailMap.SetMasterList(const Value: TList);
  8557. begin
  8558. FMasterList := Value;
  8559. end;
  8560. { TsdOperationManager }
  8561. constructor TsdOperationManager.Create;
  8562. begin
  8563. FActive := True;
  8564. FItems := TList.Create;
  8565. FDataSets := TList.Create;
  8566. // 默认Undo 3次
  8567. FLimitedCount := 10;
  8568. FSavePoint := 0;
  8569. FSnapShooting := False;
  8570. FNeedConfirmSnapShoot := False;
  8571. end;
  8572. destructor TsdOperationManager.Destroy;
  8573. var
  8574. I: Integer;
  8575. begin
  8576. for I := 0 to FItems.Count - 1 do
  8577. TsdOperationItem(FItems[I]).Free;
  8578. FItems.Free;
  8579. FDataSets.Free;
  8580. inherited;
  8581. end;
  8582. function TsdOperationManager.FindItem(AID: Integer): TsdOperationItem;
  8583. var
  8584. I: Integer;
  8585. Item: TsdOperationItem;
  8586. begin
  8587. Result := nil;
  8588. for I := 0 to FItems.Count - 1 do
  8589. begin
  8590. Item := TsdOperationItem(FItems[I]);
  8591. if Item.ID = AID then
  8592. begin
  8593. Result := Item;
  8594. Break;
  8595. end;
  8596. end;
  8597. end;
  8598. function TsdOperationManager.GetCount: Integer;
  8599. begin
  8600. Result := FItems.Count;
  8601. end;
  8602. function TsdOperationManager.GetItems(I: Integer): TsdOperationItem;
  8603. begin
  8604. Result := TsdOperationItem(FItems[I]);
  8605. end;
  8606. procedure TsdOperationManager.RegisterDataSet(ADataSet: TsdDataSet);
  8607. begin
  8608. ADataSet.UseSavePoint := True;
  8609. if FDataSets.IndexOf(ADataSet) < 0 then
  8610. begin
  8611. FDataSets.Add(ADataSet);
  8612. ADataSet.FOperationManager := Self;
  8613. end;
  8614. end;
  8615. // undo是对FSavePoint前一条记录,redo是对FSavePoint当前记录
  8616. procedure TsdOperationManager.Undo(AID: Integer);
  8617. var
  8618. I: Integer;
  8619. Item, PrevItem: TsdOperationItem;
  8620. begin
  8621. if not Active then Exit;
  8622. // 防止出错
  8623. EndSnapShoot;
  8624. if Count = 0 then Exit;
  8625. SaveHistory('D:\Code\temp\UndoTest\Operations\DataSetBeforeUndo' + FloatToStr(Now) + '.log');
  8626. BeginLog('D:\Code\temp\UndoTest\Operations\UndoLog' + FloatToStr(Now) + '.log');
  8627. try
  8628. // SavePoint是最新的时候要先处理最后一个Item
  8629. Item := FItems[FItems.Count - 1];
  8630. if Item.ID = FSavePoint - 1 then
  8631. Item.EndSnap;
  8632. if AID = -1 then
  8633. begin
  8634. Item := FindPrev(SavePoint);
  8635. if Item <> nil then
  8636. begin
  8637. Item.Undo;
  8638. FSavePoint := Item.ID;
  8639. end;
  8640. end
  8641. else
  8642. begin
  8643. if AID > FSavePoint then
  8644. raise EsdHistory.Create('Can not undo to newer record');
  8645. // 如果中间有多次记录,要依次Undo
  8646. // 1,2,3,4,5 SavePoint = 4, Undo到2, 执行操作集3、2 Undo, SavePoint = 3
  8647. for I := Count - 1 downto 0 do
  8648. begin
  8649. Item := TsdOperationItem(FItems[I]);
  8650. if (Item.ID >= AID) and (Item.ID < FSavePoint) then
  8651. begin
  8652. Item.Undo;
  8653. if Item.ID = AID then
  8654. begin
  8655. FSavePoint := AID;
  8656. Break;
  8657. end;
  8658. end;
  8659. end;
  8660. end;
  8661. finally
  8662. EndLog;
  8663. end;
  8664. end;
  8665. // undo是对FSavePoint前一条记录,redo是对FSavePoint当前记录
  8666. procedure TsdOperationManager.Redo(AID: Integer);
  8667. var
  8668. I: Integer;
  8669. Item, NextItem: TsdOperationItem;
  8670. begin
  8671. if not Active then Exit;
  8672. // 防止出错
  8673. EndSnapShoot;
  8674. if Count = 0 then Exit;
  8675. SaveHistory('D:\Code\temp\UndoTest\Operations\DataSetBeforeRedo' + FloatToStr(Now) + '.log');
  8676. BeginLog('D:\Code\temp\UndoTest\Operations\RedoLog' + FloatToStr(Now) + '.log');
  8677. try
  8678. if AID = -1 then
  8679. begin
  8680. Item := FindItem(SavePoint);
  8681. if Item <> nil then
  8682. begin
  8683. Item.Redo;
  8684. NextItem := FindNext(Item.ID);
  8685. if NextItem <> nil then
  8686. FSavePoint := NextItem.ID
  8687. else
  8688. FSavePoint := Item.ID + 1;
  8689. end;
  8690. end
  8691. else
  8692. begin
  8693. if AID < FSavePoint then
  8694. raise EsdHistory.Create('Can not redo to older record');
  8695. // 中间有多次记录,要依次Redo
  8696. // 1,2,3,4,5 SavePoint = 2, Redo到4, 执行操作集3、4 Redo, SavePoint = 5
  8697. for I := 0 to Count - 1 do
  8698. begin
  8699. Item := TsdOperationItem(FItems[I]);
  8700. if (Item.ID <= AID) and (Item.ID >= FSavePoint) then
  8701. begin
  8702. Item.Redo;
  8703. if Item.ID = AID then
  8704. begin
  8705. FSavePoint := AID + 1;
  8706. Break;
  8707. end;
  8708. end;
  8709. end;
  8710. end;
  8711. finally
  8712. EndLog;
  8713. end;
  8714. end;
  8715. function TsdOperationManager.SnapShoot(AName: string; BeginSnapShoot, NeedConfirm: Boolean): Integer;
  8716. var
  8717. I: Integer;
  8718. Item: TsdOperationItem;
  8719. begin
  8720. Result := -1;
  8721. if not Active then Exit;
  8722. if FSnapShooting then
  8723. begin
  8724. Result := -2;
  8725. Exit;
  8726. end;
  8727. // 还未Confirm的操作先Confirm
  8728. if FNeedConfirmSnapShoot then Confirm;
  8729. FSnapShooting := BeginSnapShoot;
  8730. if FDataSets.Count = 0 then Exit;
  8731. ClearNewerItems;
  8732. // 处理前一个Item
  8733. if FItems.Count > 0 then
  8734. begin
  8735. Item := FItems[FItems.Count - 1];
  8736. if Item <> nil then
  8737. Item.EndSnap;
  8738. end;
  8739. // 创建新Item
  8740. Item := TsdOperationItem.Create(Self, SavePoint, AName);
  8741. Item.SnapShoot;
  8742. FItems.Add(Item);
  8743. // 无需Confirm则清除旧项目
  8744. FNeedConfirmSnapShoot := NeedConfirm;
  8745. if not NeedConfirm then
  8746. while FItems.Count > FLimitedCount do
  8747. begin
  8748. Item := FItems[0];
  8749. Item.Free;
  8750. FItems.Delete(0);
  8751. // 清理旧的Item中记录的需要删除的DataRecord
  8752. Item := FItems[0];
  8753. if Item <> nil then
  8754. Item.ClearOlderHistoryRecord;
  8755. end;
  8756. // 当前SavePoint是虚拟ID,比最大项ID大1
  8757. FSavePoint := NewID;
  8758. end;
  8759. procedure TsdOperationManager.EndSnapShoot;
  8760. begin
  8761. FSnapShooting := False;
  8762. end;
  8763. procedure TsdOperationManager.UnRegisterDataSet(ADataSet: TsdDataSet);
  8764. begin
  8765. FDataSets.Remove(ADataSet);
  8766. ADataSet.FOperationManager := nil;
  8767. // 还应该清理FItems,但是好像用不到本方法,暂不管
  8768. end;
  8769. function TsdOperationManager.GetDataSet(I: Integer): TsdDataSet;
  8770. begin
  8771. Result := TsdDataSet(FDataSets[I]);
  8772. end;
  8773. function TsdOperationManager.GetDataSetCount: Integer;
  8774. begin
  8775. Result := FDataSets.Count;
  8776. end;
  8777. procedure TsdOperationManager.SetLimitedCount(const Value: Integer);
  8778. begin
  8779. FLimitedCount := Value;
  8780. end;
  8781. function TsdOperationManager.NewID: Integer;
  8782. var
  8783. I: Integer;
  8784. Item: TsdOperationItem;
  8785. begin
  8786. Result := 0;
  8787. if FItems.Count > 0 then
  8788. begin
  8789. for I := 0 to FItems.Count - 1 do
  8790. begin
  8791. Item := TsdOperationItem(FItems[I]);
  8792. Result := Max(Result, Item.ID);
  8793. end;
  8794. Inc(Result);
  8795. end;
  8796. end;
  8797. procedure TsdOperationManager.SetDataSetAfterUndo(const Value: TsdOperationDataSetAfterEvent);
  8798. begin
  8799. FDataSetAfterUndo := Value;
  8800. end;
  8801. procedure TsdOperationManager.SetDataSetBeforeUndo(
  8802. const Value: TsdOperationDataSetBeforeEvent);
  8803. begin
  8804. FDataSetBeforeUndo := Value;
  8805. end;
  8806. procedure TsdOperationManager.DoDataSetAfterUndo(ADataSet: TsdDataSet;
  8807. ARecord: TsdDataRecord; AOperation: TsdOperation; ADataRec: TsdDataRecord;
  8808. AFields: TStrings; AData: Pointer);
  8809. begin
  8810. if Assigned(FDataSetAfterUndo) then
  8811. FDataSetAfterUndo(ADataSet, ARecord, AOperation, ADataRec, AFields, AData);
  8812. end;
  8813. procedure TsdOperationManager.DoDataSetBeforeUndo(ADataSet: TsdDataSet;
  8814. ARecord: TsdDataRecord; AOperation: TsdOperation; ADataRec: TsdDataRecord;
  8815. AFields: TStrings; AData: Pointer; var CanDo: Boolean);
  8816. begin
  8817. if Assigned(FDataSetBeforeUndo) then
  8818. FDataSetBeforeUndo(ADataSet, ARecord, AOperation, ADataRec, AFields, AData, CanDo);
  8819. end;
  8820. function TsdOperationManager.FindNext(AID: Integer): TsdOperationItem;
  8821. var
  8822. I, Idx: Integer;
  8823. Item: TsdOperationItem;
  8824. begin
  8825. Result := nil;
  8826. if Count = 0 then Exit;
  8827. Idx := IndexByID(AID);
  8828. if Idx < 0 then Exit;
  8829. if Idx + 1 >= Count then Exit;
  8830. Result := TsdOperationItem(FItems[Idx + 1]);
  8831. end;
  8832. function TsdOperationManager.FindPrev(AID: Integer): TsdOperationItem;
  8833. var
  8834. I, Idx: Integer;
  8835. Item: TsdOperationItem;
  8836. begin
  8837. Result := nil;
  8838. if Count = 0 then Exit;
  8839. // 最新的ID是虚拟ID(最大ID+ 1)
  8840. if AID = TsdOperationItem(FItems[Count - 1]).ID + 1 then
  8841. begin
  8842. Result := TsdOperationItem(FItems[Count - 1]);
  8843. Exit;
  8844. end;
  8845. Idx := IndexByID(AID);
  8846. if Idx < 0 then Exit;
  8847. if Idx - 1 < 0 then Exit;
  8848. Result := TsdOperationItem(FItems[Idx - 1]);
  8849. end;
  8850. procedure TsdOperationManager.OperationList(AList: TStrings; Undo: Boolean);
  8851. var
  8852. I: Integer;
  8853. Item: TsdOperationItem;
  8854. begin
  8855. AList.Clear;
  8856. if Undo then
  8857. for I := FItems.Count - 1 downto 0 do
  8858. begin
  8859. Item := TsdOperationItem(FItems[I]);
  8860. if Item.ID < FSavePoint then
  8861. AList.AddObject(Item.Name, Pointer(Item.ID));
  8862. end
  8863. else
  8864. for I := 0 to FItems.Count - 1 do
  8865. begin
  8866. Item := TsdOperationItem(FItems[I]);
  8867. if Item.ID >= FSavePoint then
  8868. AList.AddObject(Item.Name, Pointer(Item.ID));
  8869. end;
  8870. end;
  8871. function TsdOperationManager.IndexByID(AID: Integer): Integer;
  8872. var
  8873. I: Integer;
  8874. Item: TsdOperationItem;
  8875. begin
  8876. Result := -1;
  8877. for I := 0 to FItems.Count - 1 do
  8878. begin
  8879. Item := TsdOperationItem(FItems[I]);
  8880. if Item.ID = AID then
  8881. begin
  8882. Result := I;
  8883. Break;
  8884. end;
  8885. end;
  8886. end;
  8887. procedure TsdOperationManager.DoDataSetAfterRedo(ADataSet: TsdDataSet;
  8888. ARecord: TsdDataRecord; AOperation: TsdOperation; ADataRec: TsdDataRecord;
  8889. AFields: TStrings; AData: Pointer);
  8890. begin
  8891. if Assigned(FDataSetAfterRedo) then
  8892. FDataSetAfterRedo(ADataSet, ARecord, AOperation, ADataRec, AFields, AData);
  8893. end;
  8894. procedure TsdOperationManager.DoDataSetBeforeRedo(ADataSet: TsdDataSet;
  8895. ARecord: TsdDataRecord; AOperation: TsdOperation; ADataRec: TsdDataRecord;
  8896. AFields: TStrings; AData: Pointer; var CanDo: Boolean);
  8897. begin
  8898. if Assigned(FDataSetBeforeRedo) then
  8899. FDataSetBeforeRedo(ADataSet, ARecord, AOperation, ADataRec, AFields, AData, CanDo);
  8900. end;
  8901. procedure TsdOperationManager.SetDataSetAfterRedo(const Value: TsdOperationDataSetAfterEvent);
  8902. begin
  8903. FDataSetAfterRedo := Value;
  8904. end;
  8905. procedure TsdOperationManager.SetDataSetBeforeRedo(
  8906. const Value: TsdOperationDataSetBeforeEvent);
  8907. begin
  8908. FDataSetBeforeRedo := Value;
  8909. end;
  8910. function TsdOperationManager.RedoCount: Integer;
  8911. var
  8912. I: Integer;
  8913. Item: TsdOperationItem;
  8914. begin
  8915. Result := 0;
  8916. for I := 0 to FItems.Count - 1 do
  8917. begin
  8918. Item := TsdOperationItem(FItems[I]);
  8919. if Item.ID >= FSavePoint then
  8920. Inc(Result);
  8921. end;
  8922. end;
  8923. function TsdOperationManager.UndoCount: Integer;
  8924. var
  8925. I: Integer;
  8926. Item: TsdOperationItem;
  8927. begin
  8928. Result := 0;
  8929. for I := 0 to FItems.Count - 1 do
  8930. begin
  8931. Item := TsdOperationItem(FItems[I]);
  8932. if Item.ID < FSavePoint then
  8933. Inc(Result);
  8934. end;
  8935. end;
  8936. function TsdOperationManager.CurrentRedoName: string;
  8937. var
  8938. I: Integer;
  8939. Item: TsdOperationItem;
  8940. begin
  8941. Result := '';
  8942. if FItems.Count = 0 then Exit;
  8943. Item := FItems[FItems.Count - 1];
  8944. // 当前最新,则没有Redo
  8945. if Item.ID < FSavePoint then Exit;
  8946. for I := 0 to FItems.Count - 1 do
  8947. begin
  8948. Item := TsdOperationItem(FItems[I]);
  8949. if Item.ID = FSavePoint then
  8950. begin
  8951. Result := Item.Name;
  8952. Break;
  8953. end;
  8954. end;
  8955. end;
  8956. function TsdOperationManager.CurrentUndoName: string;
  8957. var
  8958. I: Integer;
  8959. Item: TsdOperationItem;
  8960. begin
  8961. Result := '';
  8962. if FItems.Count = 0 then Exit;
  8963. Item := FItems[0];
  8964. // 已全部Undo完
  8965. if Item.ID = FSavePoint then Exit;
  8966. for I := 0 to FItems.Count - 1 do
  8967. begin
  8968. Item := TsdOperationItem(FItems[I]);
  8969. // 当前Undo是前一个操作
  8970. if (Item.ID = (FSavePoint - 1)) then
  8971. begin
  8972. Result := Item.Name;
  8973. Break;
  8974. end;
  8975. end;
  8976. end;
  8977. procedure TsdOperationManager.ClearNewerItems;
  8978. var
  8979. I: Integer;
  8980. Item: TsdOperationItem;
  8981. begin
  8982. if FItems.Count = 0 then Exit;
  8983. for I := FItems.Count - 1 downto 0 do
  8984. begin
  8985. Item := FItems[I];
  8986. if Item.ID >= FSavePoint then
  8987. begin
  8988. FItems.Remove(Item);
  8989. Item.ClearNewerHistoryRecord;
  8990. Item.Free;
  8991. end;
  8992. end;
  8993. end;
  8994. procedure TsdOperationManager.SaveHistory(AFileName: string);
  8995. var
  8996. I, J, K, L: Integer;
  8997. slLogs: TStringList;
  8998. Item: TsdOperationItem;
  8999. pInfo: PsdHistoryInfo;
  9000. DataSet: TsdDataSet;
  9001. HList: TsdHistoryList;
  9002. HRec: TsdHistoryRecord;
  9003. HValue: TsdHistoryValue;
  9004. V: TsdValue;
  9005. F, FOrg: TsdField;
  9006. strIndent, strRec: string;
  9007. Dir: string;
  9008. begin
  9009. Dir := ExtractFileDir(AFileName);
  9010. if not DirectoryExists(Dir) then Exit;
  9011. slLogs := TStringList.Create;
  9012. V := TsdValue.Create(nil);
  9013. F := TsdField.Create(nil);
  9014. V.FField := F;
  9015. try
  9016. for I := 0 to Count - 1 do
  9017. begin
  9018. Item := Items[I];
  9019. slLogs.Add(Format('Operation: %s; SavePoint: %d', [Item.Name, SavePoint]));
  9020. for J := 0 to Item.FInfos.Count - 1 do
  9021. begin
  9022. pInfo := Item.FInfos[J];
  9023. DataSet := pInfo^.DataSet;
  9024. strIndent := ' ';
  9025. slLogs.Add(Format('%sDataSet: %s; SavePoint: %d StartPoint: %d; EndPoint: %d', [strIndent, DataSet.Name, DataSet.SavePoint, pInfo^.StartPoint, pInfo^.EndPoint]));
  9026. HList := DataSet.FHistory;
  9027. strIndent := ' ';
  9028. for K := 0 to HList.FRecList.Count - 1 do
  9029. begin
  9030. HRec := TsdHistoryRecord(HList.FRecList[K]);
  9031. case HRec.Operation of
  9032. sroAdd: strRec := strIndent + 'Add: ';
  9033. sroDelete: strRec := strIndent + 'Delete: ';
  9034. sroModify: strRec := strIndent + 'Modify: ';
  9035. end;
  9036. for L := 0 to HRec.Count - 1 do
  9037. begin
  9038. HValue := HRec.Values[L];
  9039. FOrg := DataSet.FieldByName(HValue.FieldName);
  9040. F.FDataType := FOrg.FDataType;
  9041. HValue.CopyTo(V);
  9042. strRec := strRec + Format('%s=%s; ', [HValue.FieldName, V.AsString]);
  9043. end;
  9044. slLogs.Add(strRec);
  9045. end;
  9046. end;
  9047. end;
  9048. slLogs.SaveToFile(AFileName);
  9049. finally
  9050. slLogs.Free;
  9051. V.Free;
  9052. F.Free;
  9053. end;
  9054. end;
  9055. procedure TsdOperationManager.RenameCurrentItem(AName: string);
  9056. var
  9057. Item: TsdOperationItem;
  9058. begin
  9059. if FSnapShooting then Exit;
  9060. if FItems.Count = 0 then Exit;
  9061. Item := FItems[FItems.Count - 1];
  9062. Item.FName := AName;
  9063. end;
  9064. procedure TsdOperationManager.Reset;
  9065. begin
  9066. // 防止出错
  9067. EndSnapShoot;
  9068. ClearNewerItems;
  9069. end;
  9070. procedure TsdOperationManager.ResetWhenNecessary;
  9071. begin
  9072. if FSavePoint < NewID then
  9073. Reset;
  9074. end;
  9075. procedure TsdOperationManager.Cancel;
  9076. var
  9077. Item: TsdOperationItem;
  9078. begin
  9079. // 防止出错
  9080. EndSnapShoot;
  9081. if not FNeedConfirmSnapShoot then Exit;
  9082. FNeedConfirmSnapShoot := False;
  9083. // 取消则删除当前操作
  9084. if FItems.Count = 0 then Exit;
  9085. Item := FItems[FItems.Count - 1];
  9086. // 撤销
  9087. Item.Undo;
  9088. // 删除本操作
  9089. FItems.Remove(Item);
  9090. Item.ClearNewerHistoryRecord;
  9091. Item.Free;
  9092. FSavePoint := NewID;
  9093. end;
  9094. procedure TsdOperationManager.Confirm;
  9095. var
  9096. Item: TsdOperationItem;
  9097. begin
  9098. EndSnapShoot;
  9099. if not FNeedConfirmSnapShoot then Exit;
  9100. FNeedConfirmSnapShoot := False;
  9101. // 确认则清除超出限制的旧操作
  9102. while FItems.Count > FLimitedCount do
  9103. begin
  9104. Item := FItems[0];
  9105. Item.Free;
  9106. FItems.Delete(0);
  9107. // 清理旧的Item中记录的需要删除的DataRecord
  9108. Item := FItems[0];
  9109. if Item <> nil then
  9110. Item.ClearOlderHistoryRecord;
  9111. end;
  9112. end;
  9113. procedure TsdOperationManager.BeginSnapShoot;
  9114. begin
  9115. if not Active then Exit;
  9116. FSnapShooting := True;
  9117. end;
  9118. procedure TsdOperationManager.Resume;
  9119. var
  9120. I: Integer;
  9121. sdsData: TsdDataSet;
  9122. begin
  9123. for I := 0 to DataSetCount - 1 do
  9124. begin
  9125. sdsData := DataSet[I];
  9126. sdsData.FHistory.Resume;
  9127. end;
  9128. end;
  9129. procedure TsdOperationManager.Suspend;
  9130. var
  9131. I: Integer;
  9132. sdsData: TsdDataSet;
  9133. begin
  9134. for I := 0 to DataSetCount - 1 do
  9135. begin
  9136. sdsData := DataSet[I];
  9137. sdsData.FHistory.Suspend;
  9138. end;
  9139. end;
  9140. procedure TsdOperationManager.SetActive(const Value: Boolean);
  9141. begin
  9142. FActive := Value;
  9143. end;
  9144. procedure TsdOperationManager.SetAfterRedo(
  9145. const Value: TsdOperationAfterEvent);
  9146. begin
  9147. FAfterRedo := Value;
  9148. end;
  9149. procedure TsdOperationManager.SetAfterUndo(
  9150. const Value: TsdOperationAfterEvent);
  9151. begin
  9152. FAfterUndo := Value;
  9153. end;
  9154. procedure TsdOperationManager.SetBeforeRedo(
  9155. const Value: TsdOperationBeforeEvent);
  9156. begin
  9157. FBeforeRedo := Value;
  9158. end;
  9159. procedure TsdOperationManager.SetBeforeUndo(
  9160. const Value: TsdOperationBeforeEvent);
  9161. begin
  9162. FBeforeUndo := Value;
  9163. end;
  9164. procedure TsdOperationManager.DoAfterRedo(AItem: TsdOperationItem);
  9165. begin
  9166. if Assigned(FAfterRedo) then
  9167. FAfterRedo(AItem);
  9168. end;
  9169. procedure TsdOperationManager.DoAfterUndo(AItem: TsdOperationItem);
  9170. begin
  9171. if Assigned(FAfterUndo) then
  9172. FAfterUndo(AItem);
  9173. end;
  9174. procedure TsdOperationManager.DoBeforeRedo(AItem: TsdOperationItem;
  9175. var CanDo: Boolean);
  9176. begin
  9177. if Assigned(FBeforeRedo) then
  9178. FBeforeRedo(AItem, CanDo);
  9179. end;
  9180. procedure TsdOperationManager.DoBeforeUndo(AItem: TsdOperationItem;
  9181. var CanDo: Boolean);
  9182. begin
  9183. if Assigned(FBeforeUndo) then
  9184. FBeforeUndo(AItem, CanDo);
  9185. end;
  9186. function TsdOperationManager.GetModified: Boolean;
  9187. var
  9188. I: Integer;
  9189. DataSet: TsdDataSet;
  9190. begin
  9191. Result := False;
  9192. for I := 0 to FDataSets.Count - 1 do
  9193. begin
  9194. DataSet := TsdDataSet(FDataSets[I]);
  9195. if DataSet.Modified then
  9196. begin
  9197. Result := True;
  9198. Break;
  9199. end;
  9200. end;
  9201. end;
  9202. { TsdOperationItem }
  9203. procedure TsdOperationItem.SnapShoot;
  9204. var
  9205. I: Integer;
  9206. sdsData: TsdDataSet;
  9207. pInfo: PsdHistoryInfo;
  9208. begin
  9209. for I := 0 to FOwner.DataSetCount - 1 do
  9210. begin
  9211. sdsData := FOwner.DataSet[I];
  9212. New(pInfo);
  9213. pInfo^.DataSet := sdsData;
  9214. pInfo^.StartPoint := sdsData.SavePoint;
  9215. pInfo^.EndPoint := -1;
  9216. // 开始新操作,清理所有新操作记录
  9217. sdsData.FHistory.ClearNewerRecord(sdsData.SavePoint);
  9218. FInfos.Add(pInfo);
  9219. end;
  9220. end;
  9221. constructor TsdOperationItem.Create(AOwner: TsdOperationManager; AID: Integer; AName: string);
  9222. begin
  9223. FOwner := AOwner;
  9224. FID := AID;
  9225. FName := AName;
  9226. FInfos := TList.Create;
  9227. end;
  9228. destructor TsdOperationItem.Destroy;
  9229. begin
  9230. Clear;
  9231. FInfos.Free;
  9232. inherited;
  9233. end;
  9234. procedure TsdOperationItem.Clear;
  9235. var
  9236. I: Integer;
  9237. pInfo: PsdHistoryInfo;
  9238. begin
  9239. for I := 0 to FInfos.Count - 1 do
  9240. begin
  9241. pInfo := PsdHistoryInfo(FInfos[I]);
  9242. Dispose(pInfo);
  9243. end;
  9244. FInfos.Clear;
  9245. end;
  9246. procedure TsdOperationItem.Redo;
  9247. var
  9248. I: Integer;
  9249. sdsData: TsdDataSet;
  9250. pInfo: PsdHistoryInfo;
  9251. bCanDo: Boolean;
  9252. begin
  9253. bCanDo := True;
  9254. FOwner.DoBeforeRedo(Self, bCanDo);
  9255. if bCanDo then
  9256. begin
  9257. try
  9258. for I := 0 to FInfos.Count - 1 do
  9259. begin
  9260. pInfo := PsdHistoryInfo(FInfos[I]);
  9261. sdsData := pInfo^.DataSet;
  9262. sdsData.Redo(pInfo^.EndPoint);
  9263. end;
  9264. finally
  9265. FOwner.DoAfterRedo(Self);
  9266. end;
  9267. end;
  9268. end;
  9269. procedure TsdOperationItem.Undo;
  9270. var
  9271. I: Integer;
  9272. sdsData: TsdDataSet;
  9273. pInfo: PsdHistoryInfo;
  9274. bCanDo: Boolean;
  9275. begin
  9276. bCanDo := True;
  9277. FOwner.DoBeforeUndo(Self, bCanDo);
  9278. if bCanDo then
  9279. begin
  9280. try
  9281. for I := 0 to FInfos.Count - 1 do
  9282. begin
  9283. pInfo := PsdHistoryInfo(FInfos[I]);
  9284. sdsData := pInfo^.DataSet;
  9285. sdsData.Undo(pInfo^.StartPoint);
  9286. end;
  9287. finally
  9288. FOwner.DoAfterUndo(Self);
  9289. end;
  9290. end;
  9291. end;
  9292. procedure TsdOperationItem.EndSnap;
  9293. var
  9294. I: Integer;
  9295. sdsData: TsdDataSet;
  9296. pInfo: PsdHistoryInfo;
  9297. begin
  9298. for I := FInfos.Count - 1 downto 0 do
  9299. begin
  9300. pInfo := PsdHistoryInfo(FInfos[I]);
  9301. sdsData := pInfo^.DataSet;
  9302. // 如果StartPoint=EndPoint,说明这次操作中该DataSet没有变化,删掉
  9303. if pInfo^.StartPoint = sdsData.SavePoint then
  9304. FInfos.Delete(I)
  9305. else
  9306. pInfo^.EndPoint := sdsData.SavePoint;
  9307. end;
  9308. end;
  9309. procedure TsdOperationItem.ClearOlderHistoryRecord;
  9310. var
  9311. I: Integer;
  9312. sdsData: TsdDataSet;
  9313. pInfo: PsdHistoryInfo;
  9314. begin
  9315. for I := 0 to FInfos.Count - 1 do
  9316. begin
  9317. pInfo := FInfos[I];
  9318. sdsData := pInfo^.DataSet;
  9319. sdsData.FHistory.ClearOlderRecord(pInfo^.StartPoint);
  9320. end;
  9321. end;
  9322. procedure TsdOperationItem.ClearNewerHistoryRecord;
  9323. var
  9324. I: Integer;
  9325. sdsData: TsdDataSet;
  9326. pInfo: PsdHistoryInfo;
  9327. begin
  9328. for I := 0 to FInfos.Count - 1 do
  9329. begin
  9330. pInfo := FInfos[I];
  9331. sdsData := pInfo^.DataSet;
  9332. sdsData.FHistory.ClearNewerRecord(pInfo^.StartPoint);
  9333. end;
  9334. end;
  9335. { TsdHistoryList }
  9336. procedure TsdHistoryList.Add(ARecord: TsdDataRecord);
  9337. var
  9338. HistoryRec: TsdHistoryRecord;
  9339. begin
  9340. if IsUpdatingRecord then
  9341. raise EsdHistory.Create('添加操作不支持批量处理');
  9342. // 若OperationManager.SavePiont不是最新则Reset
  9343. FDataSet.OperationManager.ResetWhenNecessary;
  9344. HistoryRec := TsdHistoryRecord.Create(Self);
  9345. HistoryRec.FID := LastID + 1;
  9346. FRecList.Add(HistoryRec);
  9347. HistoryRec.Add(ARecord);
  9348. FSavePoint := HistoryRec.FID + 1;
  9349. end;
  9350. procedure TsdHistoryList.BeginAdd;
  9351. begin
  9352. FAdding := True;
  9353. end;
  9354. procedure TsdHistoryList.BeginRecordUpdate(ARecord: TsdDataRecord);
  9355. var
  9356. HistoryRec: TsdHistoryRecord;
  9357. begin
  9358. // 若OperationManager.SavePiont不是最新则Reset
  9359. FDataSet.OperationManager.ResetWhenNecessary;
  9360. Inc(FUpdateRecordLock);
  9361. HistoryRec := TsdHistoryRecord.Create(Self);
  9362. HistoryRec.FID := LastID + 1;
  9363. HistoryRec.FRec := ARecord;
  9364. FRecList.Add(HistoryRec);
  9365. FSavePoint := HistoryRec.FID + 1;
  9366. end;
  9367. procedure TsdHistoryList.Clear;
  9368. var
  9369. I: Integer;
  9370. begin
  9371. ClearAllDataRecords;
  9372. for I := 0 to FRecList.Count - 1 do
  9373. TsdHistoryRecord(FRecList[I]).Free;
  9374. FRecList.Clear;
  9375. end;
  9376. // 清除新的记录,包括自己
  9377. procedure TsdHistoryList.ClearNewerRecord(AID: Integer);
  9378. var
  9379. I, iIdx: Integer;
  9380. Rec: TsdHistoryRecord;
  9381. begin
  9382. iIdx := IndexByID(AID);
  9383. if iIdx < 0 then Exit;
  9384. for I := FRecList.Count - 1 downto iIdx do
  9385. begin
  9386. Rec := TsdHistoryRecord(FRecList[I]);
  9387. FRecList.Delete(I);
  9388. // 新增操作、且是新增记录或已保存过的删除记录,FRec才释放
  9389. if (Rec.Operation = sroAdd) and (Rec.FRec.New or (FDataSet.FDeletedList.IndexOf(Rec.FRec) < 0)) and Rec.FNeedFreeCheck then
  9390. Rec.FRec.Free;
  9391. Rec.Free;
  9392. end;
  9393. end;
  9394. // 清除旧的记录,不包括自己
  9395. procedure TsdHistoryList.ClearOlderRecord(AID: Integer);
  9396. var
  9397. I, iIdx: Integer;
  9398. Rec: TsdHistoryRecord;
  9399. begin
  9400. iIdx := IndexByID(AID);
  9401. if iIdx < 0 then Exit;
  9402. for I := iIdx - 1 downto 0 do
  9403. begin
  9404. Rec := TsdHistoryRecord(FRecList[I]);
  9405. FRecList.Delete(I);
  9406. // 删除操作、且是新增记录或已保存过的删除记录,FRec才释放
  9407. if (Rec.Operation = sroDelete) and (Rec.FRec.New or (FDataSet.FDeletedList.IndexOf(Rec.FRec) < 0)) and Rec.FNeedFreeCheck then
  9408. Rec.FRec.Free;
  9409. Rec.Free;
  9410. end;
  9411. end;
  9412. constructor TsdHistoryList.Create(ADataSet: TsdDataSet);
  9413. begin
  9414. FDataSet := ADataSet;
  9415. FRecList := TList.Create;
  9416. FLastHistoryRecords := TList.Create;
  9417. FSavePoint := 0;
  9418. FUpdateRecordLock := 0;
  9419. FAdding := False;
  9420. FStopping := 0;
  9421. end;
  9422. procedure TsdHistoryList.Delete(ARecord: TsdDataRecord);
  9423. var
  9424. HistoryRec: TsdHistoryRecord;
  9425. begin
  9426. if IsUpdatingRecord then
  9427. raise EsdHistory.Create('删除操作不支持批量处理');
  9428. // 若OperationManager.SavePiont不是最新则Reset
  9429. if FDataSet.OperationManager <> nil then
  9430. FDataSet.OperationManager.ResetWhenNecessary;
  9431. HistoryRec := TsdHistoryRecord.Create(Self);
  9432. HistoryRec.FID := LastID + 1;
  9433. FRecList.Add(HistoryRec);
  9434. HistoryRec.Delete(ARecord);
  9435. FSavePoint := HistoryRec.FID + 1;
  9436. end;
  9437. destructor TsdHistoryList.Destroy;
  9438. var
  9439. I: Integer;
  9440. begin
  9441. Clear;
  9442. FRecList.Free;
  9443. for I := 0 to FLastHistoryRecords.Count - 1 do
  9444. TsdHistoryRecord(FLastHistoryRecords[I]).Free;
  9445. FLastHistoryRecords.Free;
  9446. inherited;
  9447. end;
  9448. procedure TsdHistoryList.EndAdd;
  9449. begin
  9450. FAdding := False;
  9451. end;
  9452. procedure TsdHistoryList.EndRecordUpdate;
  9453. begin
  9454. if FUpdateRecordLock > 0 then
  9455. Dec(FUpdateRecordLock);
  9456. end;
  9457. function TsdHistoryList.IndexByID(AID: Integer): Integer;
  9458. var
  9459. I: Integer;
  9460. HistoryRec: TsdHistoryRecord;
  9461. begin
  9462. Result := -1;
  9463. for I := 0 to FRecList.Count - 1 do
  9464. begin
  9465. HistoryRec := TsdHistoryRecord(FRecList[I]);
  9466. if AID = HistoryRec.ID then
  9467. begin
  9468. Result := I;
  9469. Break;
  9470. end;
  9471. end;
  9472. end;
  9473. function TsdHistoryList.GetSavePoint: Integer;
  9474. begin
  9475. // SavePoint是当前值,所以在历史记录中还不存在
  9476. Result := FSavePoint;
  9477. end;
  9478. function TsdHistoryList.IsUpdatingRecord: Boolean;
  9479. begin
  9480. Result := FUpdateRecordLock > 0;
  9481. end;
  9482. function TsdHistoryList.LastID: Integer;
  9483. var
  9484. HistoryRec: TsdHistoryRecord;
  9485. begin
  9486. Result := -1;
  9487. if FRecList.Count > 0 then
  9488. begin
  9489. HistoryRec := TsdHistoryRecord(FRecList.Last);
  9490. Result := HistoryRec.ID;
  9491. end;
  9492. end;
  9493. procedure TsdHistoryList.Modify(AValue: TsdValue);
  9494. var
  9495. HistoryRec: TsdHistoryRecord;
  9496. begin
  9497. // 插入记录未完成,前面的操作无需记录
  9498. if FAdding then Exit;
  9499. if IsUpdatingRecord then
  9500. begin
  9501. HistoryRec := TsdHistoryRecord(FRecList.Last);
  9502. if HistoryRec.FRec <> AValue.Owner then
  9503. raise EsdHistory.Create('Can update 2 record once');
  9504. end
  9505. else
  9506. begin
  9507. // 若OperationManager.SavePiont不是最新则Reset
  9508. FDataSet.OperationManager.ResetWhenNecessary;
  9509. HistoryRec := TsdHistoryRecord.Create(Self);
  9510. HistoryRec.FID := LastID + 1;
  9511. HistoryRec.FRec := AValue.Owner;
  9512. FRecList.Add(HistoryRec);
  9513. FSavePoint := HistoryRec.FID + 1;
  9514. end;
  9515. HistoryRec.Modify(AValue);
  9516. end;
  9517. procedure TsdHistoryList.Redo(AID: Integer);
  9518. function FindDelRec(AIndex: Integer; CurRec: TsdDataRecord): TsdDataRecord;
  9519. var
  9520. I: Integer;
  9521. HRec: TsdHistoryRecord;
  9522. begin
  9523. Result := nil;
  9524. for I := AIndex to FRecList.Count - 1 do
  9525. begin
  9526. HRec := TsdHistoryRecord(FRecList[I]);
  9527. if HRec.ID > AID then
  9528. Break;
  9529. if (HRec.Operation = sroDelete) and (CurRec = HRec.FRec) then
  9530. begin
  9531. Result := HRec.FRec;
  9532. Break;
  9533. end;
  9534. end;
  9535. end;
  9536. var
  9537. I: Integer;
  9538. HistoryRec: TsdHistoryRecord;
  9539. AddRec, DelRec: TsdDataRecord;
  9540. begin
  9541. if (AID < 0) or (AID - 1 > LastID) then Exit;
  9542. AddLog(Format('DataSet: %s; SavePoint: %d', [DataSet.Name, DataSet.SavePoint]));
  9543. Suspend;
  9544. try
  9545. AddRec := nil;
  9546. DelRec := nil;
  9547. // 1,2,3,4,5 SavePoint = 2, Redo到4, 执行操作集3、4 Redo, SavePoint = 5
  9548. for I := 0 to FRecList.Count - 1 do
  9549. begin
  9550. HistoryRec := TsdHistoryRecord(FRecList[I]);
  9551. // 注意DataSet.SavePoint最新值都是虚拟值,所以这里不能等于目标值,要小于
  9552. if (HistoryRec.ID < AID) and (HistoryRec.ID >= FSavePoint) then
  9553. begin
  9554. // Delete操作前面的全部略过,因为Redo直接删除记录就好了
  9555. DelRec := FindDelRec(I, HistoryRec.FRec);
  9556. // Add操作的Rec要传入Redo
  9557. if HistoryRec.Operation = sroAdd then
  9558. AddRec := HistoryRec.FRec;
  9559. // 1.add操作的undo不会改动记录,所以add操作后面的操作可以略过
  9560. // 2.del操作前面的操作全部略过,redo直接删除就好了
  9561. // 2023/10/24 暂屏蔽,不一步步全部Undo的话,LastValue缓存不全,对应Redo也要一步步全部操作
  9562. //if (not ((AddRec <> nil) and (AddRec = HistoryRec.FRec) and (HistoryRec.Operation = sroModify)))
  9563. // and (not ((DelRec <> nil) and (DelRec = HistoryRec.FRec) and (HistoryRec.Operation = sroModify))) then
  9564. begin
  9565. HistoryRec.Redo(AddRec);
  9566. if HistoryRec.ID = AID - 1 then
  9567. begin
  9568. FSavePoint := AID;
  9569. Break;
  9570. end;
  9571. end;
  9572. end;
  9573. end;
  9574. finally
  9575. Resume;
  9576. DataSet.FKeepPosition := True;
  9577. try
  9578. DataSet.NotifyChanged(nil, sdoReset);
  9579. finally
  9580. DataSet.FKeepPosition := False;
  9581. end;
  9582. end;
  9583. end;
  9584. procedure TsdHistoryList.SetSavePoint(const Value: Integer);
  9585. begin
  9586. Undo(Value);
  9587. end;
  9588. procedure TsdHistoryList.Undo(AID: Integer);
  9589. function FindAddRec(AIndex: Integer): TsdDataRecord;
  9590. var
  9591. I: Integer;
  9592. HRec: TsdHistoryRecord;
  9593. begin
  9594. Result := nil;
  9595. for I := AIndex downto 0 do
  9596. begin
  9597. HRec := TsdHistoryRecord(FRecList[I]);
  9598. if HRec.ID < AID then
  9599. Break;
  9600. if HRec.Operation = sroAdd then
  9601. begin
  9602. Result := HRec.FRec;
  9603. Break;
  9604. end;
  9605. end;
  9606. end;
  9607. var
  9608. I: Integer;
  9609. HistoryRec: TsdHistoryRecord;
  9610. Rec: TsdDataRecord;
  9611. begin
  9612. if (AID < 0) or (AID > LastID) then Exit;
  9613. Suspend;
  9614. AddLog(Format('DataSet: %s; SavePoint: %d', [DataSet.Name, DataSet.SavePoint]));
  9615. try
  9616. // 1,2,3,4,5 SavePoint = 4, Undo到2, 执行操作集3、2 Undo, SavePoint = 3
  9617. for I := FRecList.Count - 1 downto 0 do
  9618. begin
  9619. HistoryRec := TsdHistoryRecord(FRecList[I]);
  9620. if (HistoryRec.ID >= AID) and (HistoryRec.ID < FSavePoint) then
  9621. begin
  9622. // 最新的undo前要清空LastRecords;
  9623. if I = FRecList.Count - 1 then
  9624. ClearLastRecords;
  9625. // 2025/03/4 找到Add操作的记录传入HistoryRec.Undo,在里面Add操作后面的全部略过,因为Undo直接删除记录就好了
  9626. // 但是LastValue仍要一步步缓存,以便Redo时读取
  9627. Rec := FindAddRec(I);
  9628. HistoryRec.Undo(Rec);
  9629. if HistoryRec.ID = AID then
  9630. begin
  9631. FSavePoint := AID;
  9632. Break;
  9633. end;
  9634. end;
  9635. end;
  9636. finally
  9637. Resume;
  9638. DataSet.FKeepPosition := True;
  9639. try
  9640. DataSet.NotifyChanged(nil, sdoReset);
  9641. finally
  9642. DataSet.FKeepPosition := False;
  9643. end;
  9644. end;
  9645. end;
  9646. procedure TsdHistoryList.ClearAllDataRecords;
  9647. var
  9648. I: Integer;
  9649. Rec: TsdHistoryRecord;
  9650. begin
  9651. for I := 0 to FRecList.Count - 1 do
  9652. begin
  9653. Rec := TsdHistoryRecord(FRecList[I]);
  9654. if Rec.FRec <> nil then
  9655. begin
  9656. // 释放条件:1.如果不是关闭DataSet的过程中,则所有删除操作的记录都释放;
  9657. // 2.如果是关闭DataSet的过程中,且是新增记录,FRec才释放
  9658. // 因为关闭DataSet时会释放除新增记录外所有删除的记录,而正常保存不会先释放任何记录
  9659. if (Rec.Operation = sroDelete) and (FDataSet.Active or (FDataSet.FDeletedList.IndexOf(Rec.FRec) < 0) or Rec.FRec.New) then
  9660. Rec.FRec.Free;
  9661. end;
  9662. end;
  9663. end;
  9664. function TsdHistoryList.FindLastRecord(ARecord: TsdDataRecord): TsdHistoryRecord;
  9665. var
  9666. I: Integer;
  9667. begin
  9668. // 先查找FLastHistoryRecords中是否有对应记录
  9669. Result := nil;
  9670. for I := 0 to FLastHistoryRecords.Count - 1 do
  9671. begin
  9672. if TsdHistoryRecord(FLastHistoryRecords[I]).FRec = ARecord then
  9673. begin
  9674. Result := TsdHistoryRecord(FLastHistoryRecords[I]);
  9675. Break;
  9676. end;
  9677. end;
  9678. end;
  9679. procedure TsdHistoryList.CacheLastRecord(AValue: TsdValue);
  9680. var
  9681. I, J: Integer;
  9682. HRec: TsdHistoryRecord;
  9683. begin
  9684. // 先查找FLastHistoryRecords中是否有对应记录
  9685. HRec := FindLastRecord(AValue.Owner);
  9686. if HRec <> nil then
  9687. begin
  9688. // 已Cache过的退出
  9689. if HRec.FindValue(AValue) <> nil then
  9690. Exit;
  9691. end
  9692. else
  9693. begin
  9694. // TsdHistoryRecord.Create的参数仅在Undo/Redo中使用,所以这里可以为nil
  9695. HRec := TsdHistoryRecord.Create(nil);
  9696. FLastHistoryRecords.Add(HRec);
  9697. end;
  9698. HRec.Modify(AValue);
  9699. end;
  9700. procedure TsdHistoryList.CopyLastValue(AID: Integer;
  9701. AValue: TsdValue);
  9702. var
  9703. I: Integer;
  9704. HRec: TsdHistoryRecord;
  9705. bHasValue: Boolean;
  9706. V: TsdHistoryValue;
  9707. begin
  9708. bHasValue := False;
  9709. // 先检查AID以后的记录中有没有缓存该值,有则用此值Redo
  9710. for I := 0 to FRecList.Count - 1 do
  9711. begin
  9712. HRec := FRecList[I];
  9713. if (HRec.FRec = AValue.Owner) and (HRec.ID > AID) then
  9714. begin
  9715. V := HRec.FindValue(AValue);
  9716. if V <> nil then
  9717. begin
  9718. V.CopyTo(AValue);
  9719. bHasValue := True;
  9720. Break;
  9721. end;
  9722. end;
  9723. end;
  9724. // 没有则用LastRecord的缓存Redo, Redo完删除
  9725. if not bHasValue then
  9726. begin
  9727. HRec := FindLastRecord(AValue.Owner);
  9728. // 找不到则说明前面Undo时没有正确缓存LastRecord,报错
  9729. if not Assigned(HRec) then
  9730. raise EsdHistory.Create('Can not find last record after undo');
  9731. V := HRec.FindValue(AValue);
  9732. V.CopyTo(AValue);
  9733. HRec.RemoveValue(AValue);
  9734. if HRec.Count = 0 then
  9735. FLastHistoryRecords.Remove(HRec);
  9736. end;
  9737. end;
  9738. function TsdHistoryList.FindLastValue(AValue: TsdValue): TsdHistoryValue;
  9739. var
  9740. I, J: Integer;
  9741. HRec: TsdHistoryRecord;
  9742. begin
  9743. for I := 0 to FLastHistoryRecords.Count - 1 do
  9744. begin
  9745. HRec := FLastHistoryRecords[I];
  9746. if HRec.FRec = AValue.Owner then
  9747. begin
  9748. Result := HRec.FindValue(AValue);
  9749. Break;
  9750. end;
  9751. end;
  9752. end;
  9753. function TsdHistoryList.FindByRecord(
  9754. ARecord: TsdDataRecord): TsdHistoryRecord;
  9755. var
  9756. I: Integer;
  9757. HRec: TsdHistoryRecord;
  9758. begin
  9759. Result := nil;
  9760. for I := 0 to FRecList.Count - 1 do
  9761. begin
  9762. HRec := FRecList[I];
  9763. if HRec.FRec = ARecord then
  9764. begin
  9765. Result := HRec;
  9766. Break;
  9767. end;
  9768. end;
  9769. end;
  9770. procedure TsdHistoryList.ClearLastRecords;
  9771. var
  9772. I: Integer;
  9773. begin
  9774. for I := 0 to FLastHistoryRecords.Count - 1 do
  9775. TsdHistoryRecord(FLastHistoryRecords[I]).Free;
  9776. FLastHistoryRecords.Clear;
  9777. end;
  9778. function TsdHistoryList.GetStopping: Boolean;
  9779. begin
  9780. Result := ((FDataSet.OperationManager = nil) or FDataSet.OperationManager.Active) and (FStopping > 0);
  9781. end;
  9782. procedure TsdHistoryList.Resume;
  9783. begin
  9784. if FStopping = 0 then
  9785. Exit
  9786. else
  9787. Dec(FStopping);
  9788. end;
  9789. procedure TsdHistoryList.Suspend;
  9790. begin
  9791. Inc(FStopping);
  9792. end;
  9793. procedure TsdHistoryList.WriteHistoryData(AOperation: TsdOperation; AObject: IsdHistoryObject; AData: Pointer);
  9794. var
  9795. HistoryRec: TsdHistoryRecord;
  9796. begin
  9797. if IsUpdatingRecord then
  9798. raise EsdHistory.Create('外部记录操作不支持批量处理');
  9799. // 若OperationManager.SavePiont不是最新则Reset
  9800. FDataSet.OperationManager.ResetWhenNecessary;
  9801. HistoryRec := TsdHistoryRecord.Create(Self);
  9802. HistoryRec.FID := LastID + 1;
  9803. FRecList.Add(HistoryRec);
  9804. HistoryRec.FHistoryObject := AObject;
  9805. HistoryRec.FData := AData;
  9806. HistoryRec.Operation := AOperation;
  9807. FSavePoint := HistoryRec.FID + 1;
  9808. end;
  9809. { TsdHistoryRecord }
  9810. procedure TsdHistoryRecord.Add(ARecord: TsdDataRecord);
  9811. begin
  9812. FOperation := sroAdd;
  9813. // 新增时缓存新增的记录,以便Rollback时删除
  9814. FRec := ARecord;
  9815. FModified := False;
  9816. end;
  9817. constructor TsdHistoryRecord.Create(AOwner: TsdHistoryList);
  9818. begin
  9819. FID := -1;
  9820. FRec := nil;
  9821. FHistoryObject := nil;
  9822. FData := nil;
  9823. FOwner := AOwner;
  9824. FValueList := TList.Create;
  9825. // 仅用sdoActive作为初始值
  9826. FOperation := sdoActive;
  9827. FModified := False;
  9828. FNeedFreeCheck := False;
  9829. end;
  9830. procedure TsdHistoryRecord.Delete(ARecord: TsdDataRecord);
  9831. begin
  9832. FOperation := sroDelete;
  9833. // 删除时缓存删除前的记录,注意DataSet中不能释放
  9834. FRec := ARecord;
  9835. FModified := ARecord.Modified;
  9836. end;
  9837. destructor TsdHistoryRecord.Destroy;
  9838. var
  9839. I: Integer;
  9840. begin
  9841. for I := 0 to FValueList.Count - 1 do
  9842. TsdHistoryValue(FValueList[I]).Free;
  9843. FValueList.Free;
  9844. if Assigned(FHistoryObject) then
  9845. FHistoryObject := nil;
  9846. if Assigned(FData) then
  9847. Dispose(FData);
  9848. inherited;
  9849. end;
  9850. function TsdHistoryRecord.FindValue(AValue: TsdValue): TsdHistoryValue;
  9851. var
  9852. I: Integer;
  9853. begin
  9854. Result := nil;
  9855. for I := 0 to FValueList.Count - 1 do
  9856. begin
  9857. if SameText(AValue.FieldName, Values[I].FieldName) then
  9858. begin
  9859. Result := Values[I];
  9860. Break;
  9861. end;
  9862. end;
  9863. end;
  9864. function TsdHistoryRecord.GetCount: Integer;
  9865. begin
  9866. Result := FValueList.Count;
  9867. end;
  9868. function TsdHistoryRecord.GetValues(I: Integer): TsdHistoryValue;
  9869. begin
  9870. Result := TsdHistoryValue(FValueList[I]);
  9871. end;
  9872. procedure TsdHistoryRecord.Modify(AValue: TsdValue);
  9873. var
  9874. Item: TsdHistoryValue;
  9875. begin
  9876. if FOperation = sdoActive then
  9877. FOperation := sroModify;
  9878. Item := FindValue(AValue);
  9879. if Item = nil then
  9880. begin
  9881. Item := TsdHistoryValue.Create;
  9882. FValueList.Add(Item);
  9883. if not Assigned(FRec) then
  9884. FRec := AValue.Owner;
  9885. end;
  9886. Item.CopyFrom(AValue);
  9887. FModified := AValue.Owner.Modified;
  9888. end;
  9889. procedure TsdHistoryRecord.Redo(ADataRecord: TsdDataRecord);
  9890. var
  9891. DataSet: TsdDataSet;
  9892. iIndex, I: Integer;
  9893. CacheValue: TsdHistoryValue;
  9894. DataValue: TsdValue;
  9895. slstFields: TStringList;
  9896. CanDo: Boolean;
  9897. begin
  9898. DataSet := FOwner.DataSet;
  9899. CanDo := True;
  9900. if Assigned(DataSet.FOperationManager) then
  9901. begin
  9902. DataSet.FOperationManager.DoDataSetBeforeRedo(DataSet, FRec, FOperation, ADataRecord, nil, FData, CanDo);
  9903. if not CanDo then
  9904. Exit;
  9905. end;
  9906. if FHistoryObject = nil then
  9907. begin
  9908. case FOperation of
  9909. sroAdd:
  9910. begin
  9911. // 插入到正确的位置
  9912. if (FRec.FIndex >= 0) and (FRec.FIndex <= DataSet.RecordCount) then
  9913. DataSet.FDataList.Insert(FRec.FIndex, FRec)
  9914. else
  9915. FRec.FIndex := DataSet.FDataList.Add(FRec);
  9916. // 计算索引
  9917. FRec.ForceNotifyIndex;
  9918. DataSet.CheckIndex(FRec);
  9919. // 从FDeletedList中删除
  9920. DataSet.FDeletedList.Remove(FRec);
  9921. if FRec.ValueByName('ID') <> nil then
  9922. AddLog(Format(' Add: ID=%s', [FRec.ValueByName('ID').AsString]))
  9923. else if FRec.ValueByName('GLJID') <> nil then
  9924. AddLog(Format(' Add: GLJID=%s', [FRec.ValueByName('GLJID').AsString]))
  9925. else
  9926. AddLog(' Add: ID=-1');
  9927. if Assigned(DataSet.FOperationManager) then
  9928. DataSet.FOperationManager.DoDataSetAfterRedo(DataSet, FRec, FOperation, nil, nil, nil);
  9929. end;
  9930. sroDelete:
  9931. begin
  9932. iIndex := DataSet.FDataList.IndexOf(FRec);
  9933. if iIndex < 0 then
  9934. raise EsdDataSet.Create(Format('Redo delete record error: Error index is %d', [FRec.FIndex]));
  9935. if FRec.ValueByName('ID') <> nil then
  9936. AddLog(Format(' Delete: ID=%s', [FRec.ValueByName('ID').AsString]))
  9937. else if FRec.ValueByName('GLJID') <> nil then
  9938. AddLog(Format(' Delete: GLJID=%s', [FRec.ValueByName('GLJID').AsString]))
  9939. else
  9940. AddLog(' Add: ID=-1');
  9941. DataSet.FDataList.Remove(FRec);
  9942. // 删除记录相关的索引信息
  9943. DataSet.DeleteRecordIndex(FRec);
  9944. DataSet.RenumberIndex(iIndex);
  9945. // 从FChangedList中删除
  9946. DataSet.FChangedList.Remove(FRec);
  9947. // 检查FDeletedList
  9948. if (not FRec.New) and (DataSet.FDeletedList.IndexOf(FRec) < 0) then
  9949. DataSet.FDeletedList.Add(FRec);
  9950. if Assigned(DataSet.FOperationManager) then
  9951. DataSet.FOperationManager.DoDataSetAfterRedo(DataSet, FRec, FOperation, nil, nil, nil);
  9952. FNeedFreeCheck := True;
  9953. end;
  9954. sroModify:
  9955. begin
  9956. slstFields := TStringList.Create;
  9957. try
  9958. for I := 0 to FValueList.Count - 1 do
  9959. begin
  9960. CacheValue := TsdHistoryValue(FValueList[I]);
  9961. DataValue := FRec.ValueByName(CacheValue.FieldName);
  9962. slstFields.Add(CacheValue.FFieldName);
  9963. if DataValue = nil then
  9964. raise EsdHistory.Create(Format('Can not find Field "%s"', [CacheValue.FieldName]));
  9965. // 获取新值
  9966. FOwner.CopyLastValue(FID, DataValue);
  9967. if FRec.ValueByName('ID') <> nil then
  9968. AddLog(Format(' Modify: Count=%d; I=%d; ID=%d; %s=%s', [FValueList.Count, I, DataValue.Owner.ValueByName('ID').AsInteger, DataValue.FieldName, DataValue.AsString]))
  9969. else if FRec.ValueByName('GLJID') <> nil then
  9970. AddLog(Format(' Modify: Count=%d; I=%d; ID=%d; %s=%s', [FValueList.Count, I, DataValue.Owner.ValueByName('GLJID').AsInteger, DataValue.FieldName, DataValue.AsString]))
  9971. else
  9972. AddLog(Format(' Modify: Count=%d; I=%d; ID=%d; %s=%s', [FValueList.Count, I, -1, DataValue.FieldName, DataValue.AsString]));
  9973. // 处理变化
  9974. FRec.NotifyIndex(DataValue);
  9975. FRec.FOwner.CheckIndex(FRec);
  9976. FRec.FOwner.NotifyChanged(DataValue, sroModify);
  9977. FRec.NotifyLookup(DataValue.Field);
  9978. if DataSet.FChangedList.IndexOf(FRec) < 0 then
  9979. DataSet.FChangedList.Add(FRec);
  9980. end;
  9981. if Assigned(DataSet.FOperationManager) then
  9982. DataSet.FOperationManager.DoDataSetAfterRedo(DataSet, FRec, FOperation, ADataRecord, slstFields, nil);
  9983. finally
  9984. slstFields.Free;
  9985. end;
  9986. end;
  9987. end;
  9988. end
  9989. else
  9990. begin
  9991. FHistoryObject.Undo(FData);
  9992. if Assigned(DataSet.FOperationManager) then
  9993. DataSet.FOperationManager.DoDataSetAfterRedo(DataSet, FRec, FOperation, ADataRecord, slstFields, FData);
  9994. end;
  9995. end;
  9996. procedure TsdHistoryRecord.RemoveValue(AValue: TsdValue);
  9997. var
  9998. I: Integer;
  9999. V: TsdHistoryValue;
  10000. begin
  10001. for I := 0 to FValueList.Count - 1 do
  10002. begin
  10003. V := FValueList[I];
  10004. if SameText(AValue.FieldName, V.FieldName) then
  10005. begin
  10006. FValueList.Remove(V);
  10007. Break;
  10008. end;
  10009. end;
  10010. end;
  10011. procedure TsdHistoryRecord.Undo(ADataRecord: TsdDataRecord);
  10012. var
  10013. DataSet: TsdDataSet;
  10014. iIndex, I: Integer;
  10015. CacheValue: TsdHistoryValue;
  10016. DataValue: TsdValue;
  10017. slstFields: TStringList;
  10018. Cando: Boolean;
  10019. begin
  10020. DataSet := FOwner.DataSet;
  10021. Cando := True;
  10022. if Assigned(DataSet.FOperationManager) then
  10023. begin
  10024. DataSet.FOperationManager.DoDataSetBeforeUndo(DataSet, FRec, FOperation, ADataRecord, nil, FData, Cando);
  10025. if not Cando then
  10026. Exit;
  10027. end;
  10028. if FHistoryObject = nil then
  10029. begin
  10030. case FOperation of
  10031. sroAdd:
  10032. begin
  10033. iIndex := DataSet.FDataList.IndexOf(FRec);
  10034. if iIndex < 0 then
  10035. raise EsdDataSet.Create(Format('Undo add record error: Error index is %d', [FRec.FIndex]));
  10036. DataSet.FDataList.Remove(FRec);
  10037. // 删除记录相关的索引信息
  10038. DataSet.DeleteRecordIndex(FRec);
  10039. DataSet.RenumberIndex(iIndex);
  10040. // 从FChangedList中删除
  10041. DataSet.FChangedList.Remove(FRec);
  10042. // 检查FDeletedList
  10043. if (not FRec.New) and (DataSet.FDeletedList.IndexOf(FRec) < 0) then
  10044. DataSet.FDeletedList.Add(FRec);
  10045. if FRec.ValueByName('ID') <> nil then
  10046. AddLog(Format(' Add: ID=%s', [FRec.ValueByName('ID').AsString]))
  10047. else if FRec.ValueByName('GLJID') <> nil then
  10048. AddLog(Format(' Add: GLJID=%s', [FRec.ValueByName('GLJID').AsString]))
  10049. else
  10050. AddLog(' Add: ID=-1');
  10051. if Assigned(DataSet.FOperationManager) then
  10052. DataSet.FOperationManager.DoDataSetAfterUndo(DataSet, FRec, FOperation, nil, nil, nil);
  10053. // 增减必须立即通知DataView
  10054. //DataSet.NotifyChanged(FRec, sroDelete);
  10055. // 因为是新增记录,直接释放 // 改到清理时释放
  10056. FNeedFreeCheck := True;
  10057. //FreeAndNil(FRec);
  10058. end;
  10059. sroDelete:
  10060. begin
  10061. // 插入到正确的位置
  10062. if (FRec.FIndex >= 0) and (FRec.FIndex <= DataSet.RecordCount) then
  10063. DataSet.FDataList.Insert(FRec.FIndex, FRec)
  10064. else
  10065. FRec.FIndex := DataSet.FDataList.Add(FRec);
  10066. if FRec.ValueByName('ID') <> nil then
  10067. AddLog(Format(' Delete: ID=%s', [FRec.ValueByName('ID').AsString]))
  10068. else if FRec.ValueByName('GLJID') <> nil then
  10069. AddLog(Format(' Delete: GLJID=%s', [FRec.ValueByName('GLJID').AsString]))
  10070. else
  10071. AddLog(' Add: ID=-1');
  10072. // 计算索引
  10073. FRec.ForceNotifyIndex;
  10074. DataSet.CheckIndex(FRec);
  10075. // 回滚后从FDeletedList删除本记录
  10076. if DataSet.FDeletedList.IndexOf(FRec) >= 0 then
  10077. DataSet.FDeletedList.Remove(FRec);
  10078. // 保存过再撤销删除,要重新将整条记录设置为新记录,才能正常保存
  10079. if DataSet.SavedPoint > ID then
  10080. begin
  10081. FRec.FNew := True;
  10082. DataSet.FChangedList.Add(FRec);
  10083. for I := 0 to FRec.Count - 1 do
  10084. if FRec.FChangedValueList.IndexOf(FRec[I]) < 0 then
  10085. FRec.FChangedValueList.Add(FRec[I]);
  10086. end
  10087. // 未保存就撤销删除,需要检查是否需要重新添加到FChangedList
  10088. else if FModified and (DataSet.FChangedList.IndexOf(FRec) < 0) then
  10089. DataSet.FChangedList.Add(FRec);
  10090. // 增减必须立即通知DataView
  10091. //DataSet.NotifyChanged(FRec, sroAdd);
  10092. if Assigned(DataSet.FOperationManager) then
  10093. DataSet.FOperationManager.DoDataSetAfterUndo(DataSet, FRec, FOperation, nil, nil, nil);
  10094. //FRec := nil;
  10095. end;
  10096. sroModify:
  10097. begin
  10098. slstFields := TStringList.Create;
  10099. try
  10100. for I := 0 to FValueList.Count - 1 do
  10101. begin
  10102. CacheValue := TsdHistoryValue(FValueList[I]);
  10103. DataValue := FRec.ValueByName(CacheValue.FieldName);
  10104. // 缓存LastValue以备Redo
  10105. FOwner.CacheLastRecord(DataValue);
  10106. // -------------------2025-03-04 zhangyin-------------------------//
  10107. // ADataRecord <> nil表示正在撤销Add记录的操作,所以这里只需缓存原值以备Redo,无需进行undo操作。
  10108. // 原因:新添加的记录值都是null,如果撤销会导致ID也变成null,这样在保存时无法根据ID找到这条记录,无法正确删除这条记录
  10109. // -------------------2025-03-04 zhangyin-------------------------//
  10110. if (ADataRecord = nil) or (ADataRecord <> FRec) then
  10111. begin
  10112. slstFields.Add(CacheValue.FFieldName);
  10113. if DataValue = nil then
  10114. raise EsdHistory.Create(Format('Can not find Field "%s"', [CacheValue.FieldName]));
  10115. CacheValue.CopyTo(DataValue);
  10116. if FRec.ValueByName('ID') <> nil then
  10117. AddLog(Format(' Modify: Count=%d; I=%d; ID=%d; %s=%s', [FValueList.Count, I, DataValue.Owner.ValueByName('ID').AsInteger, DataValue.FieldName, DataValue.AsString]))
  10118. else if FRec.ValueByName('GLJID') <> nil then
  10119. AddLog(Format(' Modify: Count=%d; I=%d; ID=%d; %s=%s', [FValueList.Count, I, DataValue.Owner.ValueByName('GLJID').AsInteger, DataValue.FieldName, DataValue.AsString]))
  10120. else
  10121. AddLog(Format(' Modify: Count=%d; I=%d; ID=%d; %s=%s', [FValueList.Count, I, -1, DataValue.FieldName, DataValue.AsString]));
  10122. // 处理变化
  10123. FRec.NotifyIndex(DataValue);
  10124. FRec.FOwner.CheckIndex(FRec);
  10125. FRec.FOwner.NotifyChanged(DataValue, sroModify);
  10126. FRec.NotifyLookup(DataValue.Field);
  10127. // 保存过再撤销
  10128. if DataSet.SavedPoint > ID then
  10129. begin
  10130. // 需要重新加入ChangedList
  10131. if DataSet.FChangedList.IndexOf(FRec) < 0 then
  10132. DataSet.FChangedList.Add(FRec);
  10133. // 将Value重新加入FChangedValueList
  10134. if FRec.FChangedValueList.IndexOf(DataValue) < 0 then
  10135. FRec.FChangedValueList.Add(DataValue);
  10136. end
  10137. // 未保存过,检查是否需要从FChangedList中删除
  10138. else if not FModified then
  10139. DataSet.FChangedList.Remove(FRec);
  10140. end;
  10141. end;
  10142. if (ADataRecord = nil) and Assigned(DataSet.FOperationManager) then
  10143. DataSet.FOperationManager.DoDataSetAfterUndo(DataSet, FRec, FOperation, ADataRecord, slstFields, nil);
  10144. finally
  10145. slstFields.Free;
  10146. end;
  10147. end;
  10148. end;
  10149. end
  10150. else
  10151. begin
  10152. FHistoryObject.Undo(FData);
  10153. if Assigned(DataSet.FOperationManager) then
  10154. DataSet.FOperationManager.DoDataSetAfterUndo(DataSet, FRec, FOperation, ADataRecord, slstFields, FData);
  10155. end;
  10156. end;
  10157. { TsdHistoryValue }
  10158. procedure TsdHistoryValue.CopyFrom(AValue: TsdValue);
  10159. begin
  10160. if Assigned(FOriginalCache) then
  10161. begin
  10162. FreeMemory(FOriginalCache);
  10163. FOriginalCache := nil;
  10164. end;
  10165. if Assigned(FData) then
  10166. begin
  10167. FreeMemory(FData);
  10168. FData := nil;
  10169. end;
  10170. FFieldName := AValue.FieldName;
  10171. if AValue.Field.IsVarField then
  10172. begin
  10173. FOriginalCacheLength := AValue.InnerCacheLength(AValue.FOriginalValue);
  10174. FLength := AValue.ActualLength;
  10175. if AValue.DataType = ftWideString then
  10176. begin
  10177. FOriginalCacheLength := FOriginalCacheLength * 2;
  10178. FLength := FLength * 2;
  10179. end;
  10180. end
  10181. else
  10182. begin
  10183. FOriginalCacheLength := AValue.DataSize;
  10184. FLength := AValue.DataSize;
  10185. end;
  10186. if Assigned(AValue.FOriginalValue) then
  10187. begin
  10188. FOriginalCache := AllocMem(FOriginalCacheLength);
  10189. CopyMemory(FOriginalCache, AValue.FOriginalValue, FOriginalCacheLength);
  10190. end;
  10191. if Assigned(AValue.FData) then
  10192. begin
  10193. FData := AllocMem(FLength);
  10194. CopyMemory(FData, AValue.FData, FLength);
  10195. end;
  10196. FIsNull := AValue.IsNull;
  10197. end;
  10198. procedure TsdHistoryValue.CopyTo(AValue: TsdValue);
  10199. var
  10200. iLength: Integer;
  10201. begin
  10202. if Assigned(FOriginalCache) then
  10203. begin
  10204. iLength := FOriginalCacheLength;
  10205. // 字符串以#0结尾
  10206. if AValue.Field.IsVarField then
  10207. begin
  10208. if AValue.DataType = ftWideString then
  10209. iLength := iLength + 2
  10210. else
  10211. iLength := iLength + 1;
  10212. end;
  10213. if Assigned(AValue.FOriginalValue) then
  10214. FreeMemory(AValue.FOriginalValue);
  10215. AValue.FOriginalValue := AllocMem(iLength);
  10216. // 按FOriginalCacheLength复制,这样字符串最后以#0结尾
  10217. CopyMemory(AValue.FOriginalValue, FOriginalCache, FOriginalCacheLength);
  10218. end
  10219. else
  10220. begin
  10221. FreeMemory(AValue.FOriginalValue);
  10222. AValue.FOriginalValue := nil;
  10223. end;
  10224. AValue.FOriginalCached := True;
  10225. if Assigned(FData) then
  10226. begin
  10227. iLength := FLength;
  10228. // 字符串以#0结尾
  10229. if AValue.Field.IsVarField then
  10230. begin
  10231. if AValue.DataType = ftWideString then
  10232. iLength := iLength + 2
  10233. else
  10234. iLength := iLength + 1;
  10235. end;
  10236. if Assigned(AValue.FData) then
  10237. FreeMemory(AValue.FData);
  10238. AValue.FData := AllocMem(iLength);
  10239. // 按FLength复制,这样字符串最后以#0结尾
  10240. CopyMemory(AValue.FData, FData, FLength);
  10241. AValue.FIsNull := FIsNull;
  10242. end
  10243. else
  10244. begin
  10245. FreeMemory(AValue.FData);
  10246. AValue.FData := nil;
  10247. AValue.FIsNull := True;
  10248. end;
  10249. end;
  10250. constructor TsdHistoryValue.Create;
  10251. begin
  10252. FOriginalCache := nil;
  10253. FData := nil;
  10254. FOriginalCacheLength := 0;
  10255. FLength := 0;
  10256. FIsNull := True;
  10257. end;
  10258. destructor TsdHistoryValue.Destroy;
  10259. begin
  10260. if Assigned(FOriginalCache) then
  10261. FreeMemory(FOriginalCache);
  10262. if Assigned(FData) then
  10263. FreeMemory(FData);
  10264. inherited;
  10265. end;
  10266. { TsdValueCache }
  10267. constructor TsdValueCache.Create(AOwner: TsdDataRecordCache);
  10268. begin
  10269. end;
  10270. destructor TsdValueCache.Destroy;
  10271. begin
  10272. FValue := Null;
  10273. inherited;
  10274. end;
  10275. procedure TsdValueCache.SetValue(const Value: Variant);
  10276. begin
  10277. FValue := Value;
  10278. end;
  10279. { TsdDataRecordCache }
  10280. procedure TsdDataRecordCache.AddValues;
  10281. var
  10282. I: Integer;
  10283. V: TsdValue;
  10284. Cache: TsdValueCache;
  10285. begin
  10286. for I := 0 to FRecord.Count - 1 do
  10287. begin
  10288. V := FRecord[I];
  10289. Cache := TsdValueCache.Create(Self);
  10290. Cache.Value := V.Value;
  10291. FList.Add(Cache);
  10292. end;
  10293. end;
  10294. constructor TsdDataRecordCache.Create(AOwner: TsdDataRecord);
  10295. begin
  10296. FRecord := AOwner;
  10297. FList := TList.Create;
  10298. AddValues;
  10299. end;
  10300. destructor TsdDataRecordCache.Destroy;
  10301. var
  10302. I: Integer;
  10303. begin
  10304. for I := 0 to FList.Count - 1 do
  10305. TsdValueCache(FList[I]).Free;
  10306. FList.Free;
  10307. inherited;
  10308. end;
  10309. function TsdDataRecordCache.GetCount: Integer;
  10310. begin
  10311. Result := FList.Count;
  10312. end;
  10313. function TsdDataRecordCache.GetValues(I: Integer): TsdValueCache;
  10314. begin
  10315. Result := nil;
  10316. if (I >= 0) and (I <= FList.Count - 1) then
  10317. Result := TsdValueCache(FList[I]);
  10318. end;
  10319. initialization
  10320. LogOn := False;
  10321. end.