| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834 |
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
- <html>
- <head>
- <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
- <title></title>
- <meta name="generator" content="LibreOffice 7.1.5.2 (Linux)"/>
- <meta name="author" content="alex "/>
- <meta name="created" content="2013-05-31T00:00:00.010003100"/>
- <meta name="changed" content="2022-06-24T17:47:03.455745039"/>
- <meta name="created" content="00:00:00">
- <meta name="created" content="00:00:00">
- <meta name="created" content="00:00:00">
- <meta name="created" content="00:00:00">
- <meta name="created" content="00:00:00">
- <meta name="created" content="00:00:00">
- <meta name="created" content="00:00:00">
- <meta name="created" content="00:00:00">
- <style type="text/css">
- @page { margin: 2.01cm }
- h1 { color: #000000 }
- p { margin-bottom: 0.2cm; color: #000000 }
- </style>
- </head>
- <body lang="en-US" text="#000000" dir="ltr"><p style="margin-top: 0.43cm; margin-bottom: 0.51cm; page-break-after: avoid">
- <font face="Albany, sans-serif"><font size="5" style="font-size: 18pt">Firebird
- interfaces.</font></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Firebird's
- OO API is based on use of interfaces. That interfaces, though looking
- in some aspects like OLE2 interfaces (some of them have addRef() and
- release() methods) are non standard and have features, missing in
- other widely used types of interfaces. First of all Firebird
- interfaces are </font><font size="4" style="font-size: 14pt"><b>language
- independent</b></font> – <font size="4" style="font-size: 14pt">that
- means that to define/use them one need not use language specific
- constructions like </font><font size="4" style="font-size: 14pt"><i>class</i></font>
- <font size="4" style="font-size: 14pt">in C++, interface may be
- defined using any language able to call functions using C calling
- conventions and having concepts of array and pointer to
- procedure/function. Next interfaces are </font><font size="4" style="font-size: 14pt"><b>versioned</b></font>
- – <font size="4" style="font-size: 14pt">i.e. we support different
- versions of same interface. Binary layout of interfaces is designed
- to support that features very efficient (there is no need in
- additional virtual calls like in OLE2/COM with it's </font><strong><font size="4" style="font-size: 14pt">QueryInterface)</font></strong><strong>
- </strong><strong><font size="4" style="font-size: 14pt">but it's not
- convenient for direct use from most languages. Therefore
- language-specific wrappers should better be designed for different
- languages making use of API easier. Currently we have wrappers for
- C++ and Pascal, Java is coming soon. From end-user POV calls from C++
- and Pascal have absolutely no difference, though some additional
- language-specific features present in C++ (like ability to turn off
- automatic status check after API calls) are missing in Pascal.</font></strong></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm; font-weight: normal"><font size="4" style="font-size: 14pt">Typically
- database API is used to access data stored in database. Firebird OO
- API certainly performs this task but in addition it supports writing
- your own </font><font size="4" style="font-size: 14pt"><b>plugins</b></font>
- – <font size="4" style="font-size: 14pt">modules, making it
- possible to enhance Firebird capabilities according to your needs.
- Therefore this document contains 2 big parts – accessing databases
- and writing plugins. Certainly some interfaces (like status vector)
- are used in both parts of API, they will be discussed in data access
- part and freely referenced later when discussing plugins. Therefore
- even if you plan to write some plugin you should better start with
- the first part of this document. Moreover a lot of plugins need to
- access databases themselves and data access API is typically needed
- for it.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="result_box"></a><font size="4" style="font-size: 14pt">Firebird
- installation package contains a number of live samples of use of OO
- API – they are in examples/interfaces (database access) and
- examples/dbcrypt (plugin performing fictitious database encryption)
- directories. It's supposed that the reader is familiar with ISC API
- used in Firebird since interbase times.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">This
- document does not pretend to be a full Firebird 3 documentation –
- it just describes new object oriented API, and a reader should be
- familiar with main Firebird concepts, knowledge about ISC API is also
- much welcome. For example – when describing how to work with
- services there is no explanation what is service and why is it
- needed, only description of how to obtain <a href="#Service">IService</a>
- interface and how to use it. Also pay attention that samples of code
- do not use a lot of powerful features of C++. Not used reference
- counted pointers, not used other RAII holders, not used templates
- (except one present in firebird public headers), etc. Primary goal is
- to make this text usable not only to C++ people because our API is
- oriented to support not only C++ but other, more simple languages
- too.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-top: 0.43cm; margin-bottom: 0.51cm; page-break-after: avoid">
- <font face="Albany, sans-serif"><font size="5" style="font-size: 18pt">Accessing
- databases.</font></font></p>
- <h1><font size="4" style="font-size: 14pt">Creating database and
- attaching to existing database.</font></h1>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">First
- of all we need to get access to <b>IMaster</b> interface. IMaster is
- primary Firebird interface, required to access all the rest of
- interfaces. Therefore there is a special way of accessing it – the
- only one needed to use OO API plain function called
- fb_get_master_interface(). This function has no parameters and always
- succeeds. There is one and only one instance of IMaster per Firebird
- client library, therefore one need not care about releasing memory,
- used by master interface. A simplest way to access it from your
- program is to have appropriate global or static variable:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>static
- <a href="#Master">IMaster</a>* master = fb_get_master_interface();</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">For
- a lot of methods, used in Firebird API, first parameter is <b>IStatus</b>
- interface. It's a logical replacement of ISC_STATUS_ARRAY, but works
- separately with errors and warnings (not mixing them in same array),
- can contain unlimited number of errors inside and (this will be
- important if you plan to implement IStatus yourself) always keeps
- strings, referenced by it, inside interface. Typically you need at
- least one instance of IStatus to call other methods. You obtain it
- from IMaster:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#Status">IStatus</a>*
- st = master->getStatus();</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">If
- method getStatus() fails for some reason (OOM for example) it returns
- NULL – obviously we can't use generic error reporting method which
- is based on use of IStatus here.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Now
- we are going to deal with first interface, directly related to
- database calls. This is <a href="#Provider">IProvider</a> –
- interface called this way cause it's exactly that interface that must
- be implemented by any provider in Firebird. Firebird client library
- also has it's own implementation of IProvider, which must be used to
- start any database activity. To obtain it we call IMaster's method:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IProvider*
- prov = master->getDispatcher();</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">When
- attaching to existing database or moreover creating new one it's
- often necessary to pass a lot of additional parameters
- (logon/password, page size for new database, etc.) to API call.
- Having separate language-level parameters is close to unreal – we
- will have to modify a call too often to add new parameters, and
- number of them will be very big no matter of the fact that typically
- one needs to pass not too much of them. Therefore to pass additional
- parameters special in-memory data structure, called </font><font size="4" style="font-size: 14pt"><i>database
- parameters block</i></font> <font size="4" style="font-size: 14pt">(DPB)
- is used. Format of it is well defined, and it's possible to build DPB
- byte after byte. But it's much easier to use special interface
- </font><a href="#XpbBuilder"><font size="4" style="font-size: 14pt"><b>IXpbBuilder</b></font></a><font size="4" style="font-size: 14pt">,
- which simplifies creation of various parameters blocks. To obtain an
- instance of IXpbBuilder you must know one more generic-use interface
- of firebird API – </font><a href="#Util"><font size="4" style="font-size: 14pt"><b>IUtil</b></font></a><font size="4" style="font-size: 14pt">.
- It's a kind of placeholder for the calls that do not fit well in
- other places. So we do</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IUtil*
- utl = master->getUtilInterface();</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IXpbBuilder*
- dpb = utl->getXpbBuilder(&status, IXpbBuilder::DPB, NULL, 0);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">This
- creates empty parameters' block builder of DPB type. Now adding
- required parameter to it is trivial:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>dpb->insertInt(&status,
- isc_dpb_page_size, 4 * 1024);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">will
- make firebird to create new database with pagesize equal to 4Kb and
- meaning of</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>dpb->insertString(&status,
- isc_dpb_user_name, “sysdba”);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>dpb->insertString(&status,
- isc_dpb_password, “masterkey”);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">is
- (I hope) obvious.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Status Wrapper"></a><font size="4" style="font-size: 14pt"><u>The
- following is C++ specific: </u>We are almost ready to call
- createDatabase() method of IProvider, but before it a few words about
- concept of <b>Status Wrapper</b> should be said. Status wrapper is
- not an interface, it's very thin envelope for IStatus interface. It
- helps to customize behavior of C++ API (change a way how errors,
- returned in IStatus interface, are processed). For the first time we
- recommend use of <b>ThrowStatusWrapper</b>, which raises C++
- exception each time an error is returned in IStatus.</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>ThrowStatusWrapper
- status(st);</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Now
- we may create new empty database:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#Attachment">IAttachment</a>*
- att = prov->createDatabase(&status, "fbtests.fdb",
- dpb->getBufferLength(&status), dpb->getBuffer(&status));</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>printf("Database
- fbtests.fdb created\n");</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Pay
- attention that we do not check status after the call to
- createDatabase(), because in case of error C++ or Pascal exception
- will be raised (therefore it's very good idea to have
- try/catch/except syntax in your program). We also use two new
- functions from IXpbBuilder – getBufferLength() and getBuffer(),
- which extract data from interface in native parameters block format.
- As you can see there is no need to check explicitly for status of
- functions, returning intermediate results.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Detaching
- from just created database is trivial:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>att->detach(&status);</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Now
- it remains to enclose all operators into <i>try</i> block and write a
- handler in catch block. When using ThrowStatusWrapper you should
- always catch defined in C++ API exception class FbException, in
- Pascal you must also work with class FbException. Exception handler
- block in simplest case may look this way:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>catch
- (const FbException& error)</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>char
- buf[256];</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>utl->formatStatus(buf,
- sizeof(buf), error.getStatus());</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>fprintf(stderr,
- "%s\n", buf);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Pay
- attention that here we use one more function from <a href="#Util">IUtil</a>
- – formatStatus(). It returns in buffer text, describing an error
- (warning), stored in IStatus parameter.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">To
- attach to existing database just use attachDatabase() method of
- IProvider instead createDatabase(). All parameters are the same for
- both methods.</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>att
- = prov->attachDatabase(&status, "fbtests.fdb", 0,
- NULL);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">This
- sample is using no additional DPB parameters. Take into account that
- without logon/password any remote connection will fail if no trusted
- authorization plugin is configured. Certainly login info may be also
- provided in environment (in ISC_USER and ISC_PASSWORD variables) like
- it was before.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Our
- examples contain complete samples, dedicated except others to
- creating databases – 01.create.cpp and 01.create.pas. When samples
- are present it will be very useful to build and try to run
- appropriate samples when reading this document.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <h1><font size="4" style="font-size: 14pt">Working with transactions.</font></h1>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Only
- creating empty databases is definitely not enough to work with RDBMS.
- We want to be able to create various objects (like tables and so on)
- in database and insert data in that tables. Any operation within
- database is performed by firebird under transaction control.
- Therefore first of all we must learn to start transaction. Here we do
- not discuss distributed transactions (supported by <a href="#Dtc">IDtc</a>
- interface) to avoid unneeded to most users overcomplication. Starting
- of non-distributed transaction is very simple and done via attachment
- interface:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#Transaction">ITransaction</a>*
- tra = att->startTransaction(&status, 0, NULL);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">In
- this sample default transaction parameters are used – no TPB is
- passed to startTransaction() method. If you need non-default
- parameters you may create appropriate <a href="#XpbBuilder">IXpbBuilder</a>,
- add required items to it:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#XpbBuilder">IXpbBuilder</a>*
- tpb = utl->getXpbBuilder(&status, IXpbBuilder::TPB, NULL, 0);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>tpb->insertTag(&status,
- isc_tpb_read_committed);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">and
- pass resulting TPB to startTransaction():</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>ITransaction*
- tra = att->startTransaction(&status,
- tpb->getBufferLength(&status), tpb->getBuffer(&status));</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Transaction
- interface is used as a parameter in a lot of other API calls but
- itself it does not perform any actions except commit/rollback
- transaction, may be retaining:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>tra->commit(&status);</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">You
- may take a look at how to start and commit transaction in examples
- 01.create.cpp and 01.create.pas.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <h1><font size="4" style="font-size: 14pt">Executing SQL operator
- without input parameters and returned rows.</font></h1>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">With
- started transaction we are ready to execute our first SQL operators.
- Used for it execute() method in <a href="#Attachment">IAttachment</a>
- is rather universal and may be also used to execute SQL operators
- with input and output parameters (which is typical for EXECUTE
- PROCEDURE statement), but right now we will use the simple most form
- of it. Both DDL and DML operators can be executed:</font></p>
- <p style="margin-bottom: 0cm; font-weight: normal"><font size="4" style="font-size: 14pt"><i>att->execute(&status,
- tra, 0, "create table dates_table (d1 date)",
- SQL_DIALECT_V6, NULL, NULL, NULL, NULL);</i></font></p>
- <p style="margin-bottom: 0cm; font-weight: normal"><font size="4" style="font-size: 14pt"><i>tra->commitRetaining(&status);</i></font></p>
- <p style="margin-bottom: 0cm; font-weight: normal"><font size="4" style="font-size: 14pt"><i>att->execute(&status,
- tra, 0, "insert into dates_table values (CURRENT_DATE)",
- SQL_DIALECT_V6, NULL, NULL, NULL, NULL);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">As
- you can see transaction interface is a required parameter for
- execute() method (must be NULL only if you execute START TRANSACTION
- statement). Next follows length of SQL operator (may be zero causing
- use of C rules to determine string length), text of operator and SQL
- dialect that should be used for it. The following for NULLs stand for
- metadata descriptions and buffers of input parameters and output
- data. Complete description of this method is provided in <a href="#Attachment">IAttachment</a>
- interface.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">You
- may take a look at how to start and commit transaction in examples
- 01.create.cpp and 01.create.pas.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <h1><font size="4" style="font-size: 14pt">Executing SQL operator
- with input parameters.</font></h1>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">There
- are 2 ways to execute statement with input parameters. Choice of
- correct method depends upon do you need to execute it more than once
- and do you know in advance format of parameters. When that format is
- known and statement is needed to be run only once single call to
- IAttachment::execute() may be used. In other cases SQL statement
- should be prepared first and after it executed, may be many times
- with different parameters.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">To
- prepare SQL statement for execution use prepare() method of
- <a href="#Attachment">IAttachment</a> interface:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#Statement">IStatement</a>*
- stmt = att->prepare(&status, tra, 0, “UPDATE department SET
- budget = ? * budget + budget WHERE dept_no = ?”,</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>SQL_DIALECT_V6,
- IStatement::PREPARE_PREFETCH_METADATA);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">If
- you are not going to use parameters description from firebird (i.e.
- you can provide that information yourself) please use
- IStatement::PREPARE_PREFETCH_NONE instead PREPARE_PREFETCH_METADATA –
- this will save client/server traffic and server resources a bit.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">In
- ISC API XSQLDA is used to describe format of statement parameters.
- New API does not use XSQLDA – instead interface IMessageMetadata is
- used. A set of input parameters (and also a row fetched from cursor)
- is described in firebird API in same way and later called message.
- <a href="#MessageMetadata">IMessageMetadata</a> is passed as a
- parameter to the methods performing message exchange between your
- program and database engine. There are many ways to have an instance
- of IMessageMetadata – one can:</font></p>
- <ul>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">get
- it from <a href="#Statement">IStatement</a>,</font></p>
- </ul>
- <ul>
- <li value="1"><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">build
- using <a href="#MetadataBuilder">IMetadataBuilder</a> interface,</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">have
- your own implementation of this interface.</font></p>
- </ul>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Getting
- metadata from prepared statement is very simple – method
- getInputMetadata() return interface describing input message (i.e.
- statement parameters), interface returned by getOutputMetadata()
- describes output message (i.e. row in selected data or values
- returned by procedure). In our case we can:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#MessageMetadata">IMessageMetadata</a>*
- meta = stmt->getInputMetadata(&status);</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Or
- we can build message metadata ourself. First of all we need builder
- interface for it:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#MetadataBuilder">IMetadataBuilder</a>*
- builder = master->getMetadataBuilder(&status, 2);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Second
- parameter is expected number of fields in the message, it can be
- changed later, i.e. that's just an optimization.</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Now
- it's necessary to set individual fields characteristics in the
- builder. An absolute minimum is field types and length for string
- fields:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>builder->setType(&status,
- 0, SQL_DOUBLE + 1);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>builder->setType(&status,
- 1, SQL_TEXT + 1);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>builder->setLength(&status,
- 1, 3);</i></font></p>
- <p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
- <font size="4" style="font-size: 14pt">New API is using old constants
- for SQL types, smallest bit as earlier stands for nullability. In
- some case it may also make sense to set sub-type (for blobs),
- character set (for text fields) or scale (for numeric fields). And
- finally it's time to get an instance of IMessageMetadata:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#MessageMetadata">IMessageMetadata</a>*
- meta = builder->getMetadata(&status);</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
- <font size="4" style="font-size: 14pt">Here we do not discuss in
- details own implementation of IMessageMetadata. If one cares there is
- a sample 05.user_metadata.cpp.</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">So
- finally we have obtained (one or another way) an instance of metadata
- description of input parameters. But to work with a message we also
- need buffer for it. Buffer size is one of main message metadata
- characteristics and it's returned by method in IMessageMetadata:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>char*
- buffer = new char[meta->getMessageLength(&status)];</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">To
- deal with individual values inside buffer offset to them should be
- taken into an account. IMessageMetadata is aware of offsets for all
- values in a message, using it we can create pointers to them:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>double*
- percent_inc = (double*) &buffer[meta->getOffset(&status,
- 0)];</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>char*
- dept_no = &buffer[meta->getOffset(&status, 1)];</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Also
- let's do not forget to set to NOT NULL null flags:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>short*
- flag = (short*)&buffer[meta->getNullOffset(&status, 0)];</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>*flag
- = 0;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>flag
- = (short*) &buffer[meta->getNullOffset(&status, 1)];</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>*flag
- = 0;</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">After
- finishing with offsets we are ready to execute statement with some
- parameters values:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>getInputValues(dept_no,
- percent_inc);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">and
- may execute prepared statement:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>stmt->execute(&status,
- tra, meta, buffer, NULL, NULL);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Two
- more NULLs in the end of parameters stand for output message and is
- used typically for EXECUTE PROCEDURE statement.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">If
- you do not need to get metadata from statement and plan to execute it
- only once you may choose a simpler way – use method execute() in
- <a href="#Attachment">IAttachment</a> interface:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>att->execute(&status,
- tra, 0, "UPDATE department SET budget = ? * budget + budget
- WHERE dept_no = ?", SQL_DIALECT_V6, meta, buffer, NULL, NULL);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">In
- that case you do not need to use <a href="#Statement">IStatement</a>
- at all.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">An
- example how to execute UPDATE with parameters is present in
- 02.update.cpp, you will also see how raised in trigger/procedure
- exception may be caught by C++ program.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <h1><font size="4" style="font-size: 14pt">Opening cursor and
- fetching data from it.</font></h1>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">The
- only way to get rows of data, returned by SELECT operator, in OO API
- is to use <a href="#ResultSet">IResultSet</a> interface. This
- interface is returned by openCursor() method in both IAttachment and
- IStatement. openCursor() is in most aspects alike execute() and a
- choice how to open cursor (using prepared statement or directly from
- attachment interface) is the same. In the samples 03.select.cpp and
- 04.print_table.cpp both methods are used. Let's pay attention at one
- specific openCursor() feature compared with execute() - one does not
- pass buffer for output message into openCursor(), it will be passed
- later when data is fetched from cursor. This makes it possible to
- open cursor with unknown format of output message (NULL is passed
- instead output metadata). Firebird is using in this case default
- message format which may be requested from IResultSet interface:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>const
- char* sql = "select * from ..."; // some select statement</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#ResultSet">IResultSet</a>*
- curs = att->openCursor(&status, tra, 0, sql, SQL_DIALECT_V6,
- NULL, NULL, NULL, NULL, 0);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#MessageMetadata">IMessageMetadata</a>*
- meta = curs->getMetadata(&status);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Later
- this metadata may be used to allocate buffer for data and parse
- fetched rows.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">As
- an alternative one can first prepare statement, get metadata from
- prepared statement and after it open cursor. This is preferred way if
- cursor is likely to be opened >1 times.</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><a href="#Statement">IStatement</a>*
- stmt = att->prepare(&status, tra, 0, sql, SQL_DIALECT_V6,
- Istatement::PREPARE_PREFETCH_METADATA);</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><a href="#MessageMetadata">IMessageMetadata</a>*
- meta = stmt->getOutputMetadata(&status);</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><a href="#ResultSet">IResultSet</a>*
- curs = stmt->openCursor(&status, tra, NULL, NULL, NULL, 0);</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">We
- have obtained (one or another way) an instance of metadata
- description of output fields (a row in a set). To work with a message
- we also need buffer for it:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>unsigned
- char* buffer = new unsigned char[meta->getMessageLength(&status)];</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IResultSet
- has a lot of various fetch methods but when cursor is not opened with
- SCROLL option only fetchNext() works, i.e. one can navigate only
- forward record by record. In addition to errors and warnings in
- status fetchNext() returns completion code, which may have values
- RESULT_OK (when buffer is filled with values for next row) or
- RESULT_NO_DATA (when no more rows left in cursor). RESULT_NO_DATA is
- not error state, it's normal state after completion of the method,
- but we know that data in cursor is over. If status wrapper, not
- throwing exception in case of error return is used, one more value –
- RESULT_ERROR – may be returned, that means no data in buffer and
- error vector in status. Method fetchNext() is usually called in a
- cycle:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>while
- (curs->fetchNext(&status, buffer) == IStatus::RESULT_OK)</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>//
- row processing</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">What
- is done during row processing depends upon your needs. To access
- particular field field's offset should be used:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>unsigned
- char* field_N_ptr = buffer + meta->getOffset(&status, n);</i></font></p>
- <p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
- <font size="4" style="font-size: 14pt">where n is the number of a
- field in a message. That pointer should be casted to appropriate
- type, depending upon field type. For example, for a VARCHAR field
- cast to struct vary should be used:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>vary*
- v_ptr = (vary*) (buffer + meta->getOffset(&status, n));</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Now
- we may print the value of a field:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>printf(“field
- %s value is %*.*s\n”, meta->getField(&status, n),
- v_ptr->vary_length, v_ptr->vary_length, v_ptr->vary_string);</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">If
- you need maximum performance it will be good idea to cache needed
- metadata values like it's done in our samples 03.select.cpp and
- 04.print_table.cpp.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <h1><font size="4" style="font-size: 14pt">Using FB_MESSAGE macro for
- static messages.</font></h1>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Working
- with data using offsets is rather efficient but requires a lot of
- code to be written. In C++ this problem can be solved using
- templates, but even compared with them the most convenient way to
- work with the message is to represent it in native (for given
- language) way – structure in C/C++, record in Pascal, etc.
- Certainly this works only if format of a message is known in advance.
- To help building such structures in C++ firebird contains special
- macro FB_MESSAGE.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_MESSAGE
- has 3 arguments – message (struct) name, type of status wrapper and
- list of fields. Usage of first and second is obvious, list of fields
- contains pairs (field_type, field_name), where field_type is one of
- the following:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BIGINT</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BLOB</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_CHAR(len)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_DATE</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_DECFIXED(scale)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_DECFLOAT16</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_DECFLOAT34</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_DOUBLE</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_FLOAT</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_INTEGER</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_INTL_CHAR(len,
- charSet)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_INTL_VARCHAR(len,
- charSet)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_SCALED_BIGINT(scale)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_SCALED_INTEGER(scale)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_SCALED_SMALLINT(scale)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_SMALLINT</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_TIME</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_TIMESTAMP</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_VARCHAR(len)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">In
- generated by preprocessor structure integer and float types are
- matched with appropriate C types, date and time – with classes
- <a href="#FbDate">FbDate</a> and <a href="#FbTime">FbTime</a> (all
- mentioned here classes are in namespace Firebird), timestamp – with
- class FbTimestamp, containing two public data members date and time
- of appropriate class, char - with struct <a href="#FbChar">FbChar</a>
- and varchar – with struct <a href="#FbVarChar">FbVarChar</a>. For
- each field preprocessor creates two data members in the message –
- </font><font size="4" style="font-size: 14pt"><i>name</i></font> <font size="4" style="font-size: 14pt">for
- field/parameter value and </font><font size="4" style="font-size: 14pt"><i>nameNull</i></font>
- <font size="4" style="font-size: 14pt">for NULL indicator. Message
- constructor has 2 parameters – pointer to status wrapper and master
- interface:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>FB_MESSAGE(Output,
- ThrowStatusWrapper,</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>(FB_SMALLINT,
- relationId)</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>(FB_CHAR(31),
- relationName)</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>(FB_VARCHAR(100),
- description)</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>)
- output(&status, master);</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">For
- static messages use of FB_MESSAGE is sooner of all the best choice –
- they can be at the same time easily passed to execute, openCursor and
- fetch methods:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>rs
- = att->openCursor(&status, tra, 0, sqlText,</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>SQL_DIALECT_V6,
- NULL, NULL, output.getMetadata(), NULL, 0);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">and
- used to work with values of individual fields:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>while
- (rs->fetchNext(&status, output.getData()) ==
- IStatus::RESULT_OK)</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>printf("%4d
- %31.31s %*.*s\n", output->relationId,
- output->relationName.str,</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>output->descriptionNull
- ? 0 : output->description.length,</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>output->descriptionNull
- ? 0 : output->description.length, output->description.str);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">An
- example of using macro FB_MESSAGE to work with messages is in the
- sample 06.fb_message.cpp.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <h1><font size="4" style="font-size: 14pt">Working with blobs.</font></h1>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">For
- blobs in message buffer firebird stores blob identifier – an 8-byte
- entity which should be aligned on 4-byte boundary. Identifier has
- ISC_QUAD type. Interface <a href="#Attachment">IAttachment</a> has 2
- methods to work with blobs – openBlob() and createBlob(), both
- returning interface <a href="#Blob">IBlob</a> and having same set of
- parameters, but performing somewhat contrary actions: openBlob()
- takes blob identifier from the message and prepares blob for reading
- but createBlob() creates new blob, puts it's identifier into message
- and prepares blob for writing. </font>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">To
- work with blobs one must first of all include blob identifier into
- the message. If you get metadata from firebird engine field of
- appropriate type will be already present. You just use it's offset
- (assuming variable blobFieldNumber contains number of blob field)
- (and appropriate null offset to check for nulls or set null flag) to
- obtain pointer into the message buffer:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>ISC_QUAD*
- blobPtr = (ISC_QUAD*) &buffer[metadata->getOffset(&status,
- blobFieldNumber)];</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>ISC_SHORT*
- blobNullPtr = (ISC_SHORT*) &buffer[metadata->getNullOffset(&status,
- blobFieldNumber)];</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">If
- you use static messages and FB_MESSAGE macro blob field is declared
- as having FB_BLOB type:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>FB_MESSAGE(Msg,
- ThrowStatusWrapper,</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>(FB_BLOB,
- b)</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>)
- message(&status, master);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>ISC_QUAD*
- blobPtr = &message->b;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>ISC_SHORT*
- blobNullPtr = &message->bNull;</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">To
- create new blob invoke createBlob() method:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#Blob">IBlob</a>*
- blob = att->createBlob(status, tra, blobPtr, 0, NULL);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Last
- two parameters are required only if you want to use blob filters or
- use stream blob, that's out of scope here.</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Blob
- interface is ready to accept data into blob. Use putSegment() method
- to send data to engine:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>void*
- segmentData;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>unsigned
- segmentLength;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>while
- (userFunctionProvidingBlobData(&segmentData, &segmentLength))</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>blob->putSegment(&status,
- segmentLength, segmentData);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">After
- sending some data to blob do not forget to close blob interface:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>blob->close(&status);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Make
- sure that null flag is not set (not required if you nullified all
- message buffer before creating blob):</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>*blobNullPtr
- = 0;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">and
- message, containing blob, may be used in insert or update statement.
- After execution of that statement new blob will be stored in
- database.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">To
- read a blob begin with getting containing it's identifier message
- from firebird engine. This may be done using fetch() or execute()
- methods. After it use openBlob() attachment's method:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#Blob">IBlob</a>*
- blob = att->openBlob(status, tra, blobPtr, 0, NULL);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Blob
- interface is ready to provide blob data. Use getSegment() method to
- receive data from engine:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>char
- buffer[BUFSIZE];</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>unsigned
- actualLength;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>for(;;)</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>switch
- (blob->getSegment(&status, sizeof(buffer), buffer,
- &actualLength))</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>case
- IStatus::RESULT_OK:</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>userFunctionAcceptingBlobData(buffer,
- actualLength, true);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>continue;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>case
- IStatus::RESULT_SEGMENT:</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>userFunctionAcceptingBlobData(buffer,
- actualLength, false);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>continue;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>default:</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>break;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Last
- parameter in userFunctionAcceptingBlobData() is a flag that end of
- segment is reached – when getSegment() returns RESULT_SEGMENT
- completion code that function is notified (by passing false as last
- parameter) that segment was not read completely and continuation is
- expected at next call.</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">After
- finishing with blob do not forget to close it:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>blob->close(&status);</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <h1><a name="Modifying data in a batch"></a><font size="4" style="font-size: 14pt">Modifying
- data in a batch.</font></h1>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Since
- version 4 firebird supports batch execution of statements with input
- parameters – that means sending more than single set of parameters
- when executing statement. <a href="#Batch">Batch</a> interface is
- designed (first of all) in order to satisfy JDBC requirements for
- prepared statement’s batch processing but has some serious
- differences:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">-
- like all operations with data in firebird it’s oriented on
- messages, not single field;</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">-
- as an important extension out batch interface supports inline use of
- blobs (specially efficient when working with small blobs);</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">-
- execute() method returns not plain array of integers but special
- <a href="#BatchCompletionState">BatchCompletionState</a> interface
- which can (depending upon batch creation parameters) contain both
- update records info and in addition to error flag detailed status
- vectors for messages that caused execution errors.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><a href="#Batch">Batch</a>
- (exactly like <a href="#ResultSet">ResultSet</a>) may be created in 2
- ways – using <a href="#Statement">Statement</a> or <a href="#Attachment">Attachment</a>
- interface, in both cases createBatch() method of appropriate
- interface is called. In second case text of SQL statement to be
- executed in a batch is passed directly to createBatch(). Tuning of
- batch operation is performed using <a href="#Batch_PB">Batch
- parameters block</a> which has format more or less similar to DPB v.2
- – tag in the beginning (IBatch::CURRENT_VERSION) followed by the
- set of wide clumplets: 1-byte tag, 4-byte length, length-byte value.
- Possible tags are <a href="#Batch_PB">described</a> in batch
- interface. The simplest (and recommended) way to create parameters
- block for batch creation is to use appropriate <a href="#XpbBuilder">XpbBuilder</a>
- interface:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IXpbBuilder*
- pb = utl->getXpbBuilder(&status, IXpbBuilder::BATCH, NULL, 0);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>pb->insertInt(&status,
- IBatch::RECORD_COUNTS, 1);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Use
- of such parameters block directs batch to account number of updated
- records on per-message basis.</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">To
- create batch interface with desired parameters pass parameters block
- to createBatch() call:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IBatch*
- batch = att->createBatch(&status, tra, 0, sqlStmtText,
- SQL_DIALECT_V6, NULL,</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>pb->getBufferLength(&status),
- pb->getBuffer(&status));</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">In
- this sample batch interface is created with default format of
- messages cause NULL is passed instead input metadata format.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">In
- order to proceed with created batch interface we need to know format
- of messages in it. It can be obtained using getMetadata() method:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IMessageMetadata*
- meta = batch->getMetadata(&status);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Certainly
- if you have passed your own format of messages to the batch you may
- simply use it.</font></p>
- <p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
- <font size="4" style="font-size: 14pt">In the former text I suppose
- that some function fillNextMessage(unsigned char* data,
- IMessageMetadata* metadata) is present and can fill buffer ‘data’
- according to passed format ‘metadata’. In order to work with
- messages we need a buffer for a data:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>unsigned
- char* data = new unsigned char[meta->getMessageLength(&status)];</i></font></p>
- <p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
- <font size="4" style="font-size: 14pt">Now we can add some messages
- full of data to the batch:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>fillNextMessage(data,
- meta);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>batch->add(&status,
- 1, data);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>fillNextMessage(data,
- meta);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>batch->add(&status,
- 1, data);</i></font></p>
- <p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
- <font size="4" style="font-size: 14pt">An alternative way of working
- with messages (using FB_MESSAGE macro) is present in the sample of
- using batch interface 11.batch.cpp.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
- <font size="4" style="font-size: 14pt">Finally batch should be
- executed:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#BatchCompletionState">IBatchCompletionState</a>*
- cs = batch->execute(&status, tra);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">We
- requested accounting of the number of modified (inserted, updated or
- deleted) records per message. To print it we must use
- <a href="#BatchCompletionState">BatchCompletionState</a> interface.
- Determine total number of messages processed by batch (it can be less
- than the number of messages passed to the batch if error happened and
- an option enabling multiple errors during batch processing was not
- turned on):</font></p>
- <p><font size="4" style="font-size: 14pt"><i>unsigned total =
- cs->getSize(&status);</i></font></p>
- <p><font size="4" style="font-size: 14pt">Now print the state of each
- message:</font></p>
- <p><font size="4" style="font-size: 14pt"><i>for (unsigned p = 0; p <
- total; ++p) printf(“Msg %u state %d\n”, p, cs->getState(&status,
- p));</i></font></p>
- <p style="font-variant: normal; font-style: normal"><font size="4" style="font-size: 14pt">When
- finished analyzing completion state don’t forget to dispose it:</font></p>
- <p><font size="4" style="font-size: 14pt"><i>cs->dispose();</i></font></p>
- <p><font color="#000000"><font size="4" style="font-size: 14pt">Full
- sample of printing contents</font></font><font color="#000000"> of
- </font><font color="#000000"><font size="4" style="font-size: 14pt"><a href="#BatchCompletionState">BatchCompletionState</a>
- is in print_cs() function in sample 11.batch.cpp.</font></font></p>
- <p style="font-variant: normal; font-style: normal"><font size="4" style="font-size: 14pt">If
- for some reason you want to make batch buffers empty not executing it
- (i.e. prepare for new portion of messages to process) use cancel()
- method:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>batch->cancel(&status);</i></font></p>
- <p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
- <font size="4" style="font-size: 14pt">Like the rest of our data
- access interfaces Batch has special method to close it:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>batch->close(&status);</i></font></p>
- <p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
- <font size="4" style="font-size: 14pt">Standard release() call may be
- used instead if one does not care about errors:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>batch->release();</i></font></p>
- <p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
- <font size="4" style="font-size: 14pt">Described methods help to
- implement all what one needs for JDBC-style prepared statement batch
- operations. </font>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Notice:
- JDBC does not recommend to use too large batches, for example “<a href="https://docs.oracle.com/cd/E11882_01/java.112/e16548/oraperf.htm#JJDBC28753">Oracle
- recommends you to keep the batch sizes in the general range of 50 to
- 100</a>”. Firebird supports bigger batches but it anyway has to
- limit maximum batch size – see <a href="#TAG_BUFFER_BYTES_SIZE">TAG_BUFFER_BYTES_SIZE</a>.
- If total size of messages exceeds that limit isc_batch_too_big error
- is returned. Pay attention that due to deep buffering of batch data
- when sending it over the wire you will not get this error at once but
- only when buffers are flashed from client to server. This may happen
- in both add() and execute() methods – execute() performs final
- flash. If you still wish to execute the batch with the messages that
- fit in a buffer you may do it (when error was returned by execute()
- just repeat it). An actual number of processed messages will be
- returned in </font><font color="#000000"><font size="4" style="font-size: 14pt"><a href="#BatchCompletionState">BatchCompletionState</a>.
- An optimal batch size should be found for each particular case but
- sooner of all having it >1000 hardly gives you serious performance
- increase.</font></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p><font size="4" style="font-size: 14pt">One can add more than
- single message in one call to the batch. When doing it please
- remember – messages should be appropriately aligned for this
- feature to work correctly. Required alignment and aligned size of the
- message should be obtained from <a href="#MessageMetadata">MessageMetadata</a>
- interface, for example:</font></p>
- <p><font size="4" style="font-size: 14pt"><i>unsigned aligned =
- meta->getAlignedLength(&status);</i></font></p>
- <p><font size="4" style="font-size: 14pt">Later that size will be
- useful when allocating an array of messages and working with it:</font></p>
- <p><font size="4" style="font-size: 14pt"><i>unsigned char* data =
- new unsigned char[aligned * N]; // N is desired number of messages</i></font></p>
- <p><font size="4" style="font-size: 14pt"><i>for (int n = 0; n <
- N; ++n) fillNextMessage(&data[aligned * n], meta);</i></font></p>
- <p><font size="4" style="font-size: 14pt"><i>batch->add(&status,
- N, data);</i></font></p>
- <p style="font-variant: normal; font-style: normal"><font size="4" style="font-size: 14pt">After
- it batch may be executed or next portion of messages added to it.</font></p>
- <p><br/>
- <br/>
- </p>
- <p><font size="4" style="font-size: 14pt">Blobs in general are not
- compatible with batches – batch is efficient when one needs to pass
- a lot of small data to the server in single step, blobs are treated
- as large objects and therefore in general it makes no sense to use
- them in batches. But on practice it often happens that blobs are not
- too big – and in this case use of traditional blob API (create
- blob, pass segments to the server, close blob, pass blobs ID in the
- message) kills performance, specially when used over WAN. Therefore
- in firebird batch supports passing blobs to server inline, together
- with other messages. To use that feature first of all <a href="#Batch_Blob_Policy">blob
- usage policy</a> for a batch to be created should be set (as an
- option in <a href="#Batch_PB">parameters block</a>):</font></p>
- <p><font size="4" style="font-size: 14pt"><i>pb->insertInt(&status,
- IBatch::BLOB_IDS, IBatch::BLOB_IDS_ENGINE);</i></font></p>
- <p style="font-variant: normal; font-style: normal"><font size="4" style="font-size: 14pt">In
- this example temporal blob IDs needed to keep a link between blob and
- a message where it’s used will be generated by firebird engine –
- that’s the simplest and rather common usage. Imagine that the
- message is described as follows:</font></p>
- <p style="font-variant: normal"><font size="4" style="font-size: 14pt"><i>FB_MESSAGE(Msg,
- ThrowStatusWrapper,</i></font></p>
- <p><font size="4" style="font-size: 14pt"><i>(FB_VARCHAR(5), id)</i></font></p>
- <p><font size="4" style="font-size: 14pt"><i>(FB_VARCHAR(10), name)</i></font></p>
- <p><font size="4" style="font-size: 14pt"><i>(FB_BLOB, desc)</i></font></p>
- <p><font size="4" style="font-size: 14pt"><i>) project(&status,
- master);</i></font></p>
- <p style="font-variant: normal; font-style: normal"><font size="4" style="font-size: 14pt">In
- that case to send a message containing blob to the server one can do
- something like this:</font></p>
- <p><font size="4" style="font-size: 14pt"><i>project->id =
- ++idCounter;</i></font></p>
- <p><font size="4" style="font-size: 14pt"><i>project->name.set(currentName);</i></font></p>
- <p><font size="4" style="font-size: 14pt"><i>batch->addBlob(&status,
- descriptionSize, descriptionText, &project->desc);</i></font></p>
- <p><font size="4" style="font-size: 14pt"><i>batch->add(&status,
- 1, project.getData());</i></font></p>
- <p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
- <font size="4" style="font-size: 14pt">If some blob happened to be
- big enough not to fit into your existing buffer you may instead
- reallocating buffer use appendBlobData() method. It appends more data
- to last added blob. </font>
- </p>
- <p style="font-variant: normal"><font size="4" style="font-size: 14pt"><i>batch->addBlob(&status,
- descriptionSize, descriptionText, &project→desc, bpbLength,
- bpb);</i></font></p>
- <p style="font-variant: normal; font-style: normal"><font size="4" style="font-size: 14pt">After
- adding first part of blob get next portion of data into
- descriptionText, update descriptionSize and:</font></p>
- <p style="font-variant: normal"><font size="4" style="font-size: 14pt"><i>batch->appendBlobData(&status,
- descriptionSize, descriptionText);</i></font></p>
- <p><font size="4" style="font-size: 14pt">This may be done in a loop
- but take care not to overflow internal batch buffers – it’s size
- is controlled by <a href="#Batch_PB">BUFFER_BYTES_SIZE</a> option
- when creating batch interface but can’t exceed 256Mb (default is
- 16Mb). If you need to process such big blob (for example on the
- background of a lot of small one – this can explain use of batch)
- just use standard blob API and <a href="#Batch::registerBlob">registerBlob</a>
- method of <a href="#Batch">Batch</a> interface.</font></p>
- <p style="font-variant: normal; font-style: normal"><font size="4" style="font-size: 14pt">One
- more possible choice of blob policy is BLOB_IDS_USER. Usage at the
- first look does not change much – before calling addBlob() correct
- and unique per batch execution ID should be placed to the memory
- referenced by last parameter. Certainly same ID should be passed in
- the data message to the blob. Taking into an account that generation
- of blob IDs by engine is very fast such policy may seem useless but
- imagine a case when you get blobs and other data in relatively
- independent streams (blocks in a file for example) and some good IDs
- are already present in them. In such case use of user-supplied blob
- IDs can greatly simplify your code.</font></p>
- <p><font size="4" style="font-size: 14pt">Please take into an account
- – unlike blobs created using regular <a href="#Attachment">createBlob</a>()
- blobs created by <a href="#Batch">Batch</a> interface are by default
- stream, not segmented. Segmented blobs provide nothing interesting
- compared with stream one and therefore not recommended to be used in
- new development, we support that format only for backward
- compatibility reasons. If you really need segmented blobs this
- default may be overridden by calling:</font></p>
- <p><font size="4" style="font-size: 14pt"><i>batch->setDefaultBpb(&status,</i></font>
- <font size="4" style="font-size: 14pt"><i>bpbLength, bpb);</i></font></p>
- <p style="font-variant: normal; font-style: normal"><font size="4" style="font-size: 14pt">Certainly
- passed BPB may contain any other blob creation parameters too. As you
- may have already noticed you may also pass BPB directly to addBlob()
- but if most of blobs you are going to add have same non-default
- format use of setDefaultBpb() is slightly more efficient. Returning
- to segmented blobs – call to addBlob() will add first segment to
- the blob, following calls to appendBlobData() will add more segments.
- Do not forget that segment size is limited to 64Kb – 1, an attempt
- to pass more data in a single call with cause an error.</font></p>
- <p><font size="4" style="font-size: 14pt">Next step when working with
- existing blob streams is use of addBlobStream() method. Using it one
- can add more than one blob to the batch per single call. Blob stream
- is a sequence of blobs, each starts with blob header. Header should
- be appropriately aligned - <a href="#Batch">Batch</a> interface
- provides special call for this purpose:</font></p>
- <p style="font-variant: normal"><font size="4" style="font-size: 14pt"><i>unsigned
- alignment = batch->getBlobAlignment(&status);</i></font></p>
- <p style="font-variant: normal; font-style: normal"><font size="4" style="font-size: 14pt">It’s
- supposed that all components of blob stream in a batch should be
- aligned at least at alignment boundary, including size of stream
- portions passed to addBlobStream() which should be a multiple of this
- alignment. Header contains 3 fields – 8-byte blob ID (must be
- non-zero), 4-byte total blob size and 4 byte BPB size. Total blob
- size includes BPB inside, i.e. one will always find next blob in the
- stream in blob-size bytes after the header (taking into account the
- alignment). BPB (if present, i.e. if BPB size is not zero) is placed
- right after the header. After BPB blob data goes, it’s format
- depends upon blob type – stream or segmented. In case of stream
- blob it’s a plain sequence of bytes having size blob-size –
- BPB-size. With segmented blob things are a bit more compicated: blob
- data is a set of segments where each segment has the following format
- – 2-bytes size of segment (this should be aligned at
- IBatch::BLOB_SEGHDR_ALIGN boundary) followed by stored in this 2
- bytes number of bytes.</font></p>
- <p style="font-variant: normal; font-style: normal"><font size="4" style="font-size: 14pt">When
- big blob is added to the stream it’s size is not always known in
- advance. In order not to have too big buffer for that blob (remember,
- size should be provided in blob header, before blob data) blob
- continuation record may be used. In blob header you leave blob size
- at a value known when creating that header and add continuation
- record that has format absolutely same as blob header, but here blob
- ID must be zero and BPB size must always be zero too. Typically you
- will want to have one continuation record per addBlobStream() call.</font></p>
- <p><a name="Batch::registerBlob"></a><font size="4" style="font-size: 14pt">Last
- method used to work with blobs stands alone from the first three that
- pass blob data inline with the rest of batch data </font>– <font size="4" style="font-size: 14pt">it’s
- needed to register in a batch ID of a blob created using standard
- blob API. This may be unavoidable if one needs to pass to a batch
- really big blob. Do not use ID of such blob in batch directly –
- that will cause invalid blob ID error during batch execution. Instead
- do:</font></p>
- <p><font size="4" style="font-size: 14pt"><i>batch->registerBlob(&status,
- &realId, &msg->desc);</i></font></p>
- <p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
- <font size="4" style="font-size: 14pt">If blob policy makes firebird
- engine generate blob IDs this code is enough to correctly register
- existing blob in a batch. In other cases you will have to assign
- correct (from batch POV) ID to msg->desc.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
- <font size="4" style="font-size: 14pt">Almost all mentioned methods
- are used in 11.batch.cpp – please use it to see an alive sample of
- batching in firebird.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
- <font size="4" style="font-size: 14pt">Two words about access to
- batches from ISC API - one can execute prepared ISC statement in
- batch mode. Main support for it is presence of two new API functions,
- namely fb_get_transaction_interface & fb_get_statement_interface,
- which make it possible to access appropriate interfaces identical to
- existing ISC handles. An example of it is present in
- 12.batch_isc.cpp.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <h1><font size="4" style="font-size: 14pt">Working with events.</font></h1>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Events
- interface was not completed in FB3, we expect to have something more
- interesting in next version. The minimum existing support is as
- follows: <a href="#Attachment">IAttachment</a> contains call
- queEvents() which performs almost same functions as isc_que_events()
- call. Instead the pair of parameters </font><font size="4" style="font-size: 14pt"><i>FPTR_EVENT_CALLBACK
- ast</i></font> <font size="4" style="font-size: 14pt">and </font><font size="4" style="font-size: 14pt"><i>void*
- arg</i></font><font size="4" style="font-size: 14pt">, required to
- invoke user code when event happens in firebird engine, callback
- interface IEventCallback is used. This is traditional approach which
- helps to avoid non-safe casts from void* in user function. Another
- important difference is that instead event identifier (a kind of
- handler) this function returns reference counted interface <a href="#Events">IEvents</a>
- having method cancel() used when waiting for event should be stopped.
- Unlike identifier which is automatically destroyed when event arrives
- interface can not be automatically destroyed – in case when event
- is received right before canceling interface call to cancel() would
- cause segfault when interface is already destroyed. Therefore
- interface <a href="#Events">IEvents</a> must be explicitly released
- after receiving an event. This may be done for example right before
- queuing for an event next time:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>events->release();</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>events
- = NULL;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>events
- = attachment->queEvents(&status, this, eveLen, eveBuffer);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Setting
- interface pointer to NULL is useful in case of exception during
- queEvents. In other aspects events handling did not change compared
- with ISC API. Please use for additional details our sample
- 08.events.cpp. </font>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <h1><font size="4" style="font-size: 14pt">Using services.</font></h1>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">To
- begin to use services one should first of all connect to service
- manager. This is done using attachServiceManager() method of
- <a href="#Provider">IProvider</a>. This method returns <a href="#Service">IService</a>
- interface which is used later to talk to service. To prepare SPB to
- attach to service manager one can use IXpbBuilder:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IXpbBuilder*
- spb1 = utl->getXpbBuilder(&status, IXpbBuilder::SPB_ATTACH,
- NULL, 0);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>spb1->insertString(&status,
- isc_spb_user_name, “sysdba”);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>spb1->insertString(&status,
- isc_spb_password, “masterkey”);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">and
- proceed with attach:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><a href="#Service">IService</a>*
- svc = prov->attachServiceManager(&status, “service_mgr”,
- spb1->getBufferLength(&status), spb1->getBuffer(&status));</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Using
- IService one can perform both available for services actions –
- start services and query various information about started utilities
- and server in general. When querying information one limitation takes
- place – formats of parameter blocks, used by query() method, in
- Firebird 3 are not supported by IXpbBuilder. Support will be probably
- added in later versions, in Firebird 3 you will have to build and
- analyze that blocks manually. Format of that blocks matches old
- format (used in ISC API) one to one. </font>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">To
- start service one should first of all create appropriate SPB:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IXpbBuilder*
- spb2 = utl->getXpbBuilder(&status, IXpbBuilder::SPB_START,
- NULL, 0);</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">and
- add required items to it. For example, to print encryption statistics
- for database employee the following should be placed into SPB:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">spb2->insertTag(&status,
- isc_action_svc_db_stats);</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">spb2->insertString(&status,
- isc_spb_dbname, "employee");</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">spb2->insertInt(&status,
- isc_spb_options, isc_spb_sts_encryption);</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">After
- it service can be started using start() method of <a href="#Service">IService</a>
- interface:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">svc->start(&status,
- spb2->getBufferLength(&status), spb2->getBuffer(&status));</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Many
- started services (including mentioned here gstat) return text
- information during execution. To display it one should query started
- service anout that information line by line. This is done by calling
- query() method of <a href="#Service">IService</a> interface with
- appropriate send and receive blocks of parameters. Send block may
- contain various helper information (like timeout when querying
- service) or information to be passed to stdin of service utility or
- may be empty in the simplest case. Receive block must contain list of
- tags you want to receive from service. For most of utilities this is
- single isc_info_svc_line:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>const
- unsigned char receiveItems1[] = {isc_info_svc_line};</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">To
- query information one also needs a buffer for that information:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>unsigned
- char results[1024];</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">After
- that preliminary steps we are ready to query service in a loop (each
- line returned in a single call to query()):</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>do</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>svc->query(&status,
- 0, NULL, sizeof(receiveItems1), receiveItems1, sizeof(results),
- results);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}
- while (printInfo(results, sizeof(results)));</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">In
- this example we suppose that printInfo() function returns TRUE as
- long as service returns results block containing next output line
- (i.e. till end of data stream from service). Format of results block
- varies from service to service, and some services like gsec produce
- historical formats that are not trivial for parse – but this is out
- of our scope here. A minimum working sample of printInfo() is present
- in example 09.service.cpp.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Same
- query method is used to retrieve information about server but in this
- case query function is not invoked in a loop, i.e. buffer must be big
- enough to fit all information at once. This is not too hard –
- typically such calls do not return much data. As in previous case
- begin with receive block placing required items in it – in our
- example it's isc_info_svc_server_version:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- unsigned char receiveItems2[] = {isc_info_svc_server_version};</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Existing
- from previous call results buffer may be reused. No loop is needed
- here:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>svc->query(&status,
- 0, NULL, sizeof(receiveItems2), receiveItems2, sizeof(results),
- results);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>printInfo(results,
- sizeof(results));</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">After
- finishing with services tasks do not forget to close an interface:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>svc->detach(&status);</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
- <font size="4" style="font-size: 14pt">IService interface also
- contains method cancel(). It’s needed to cancel wait in a query()
- and is used internally by network server. Current implementation is
- restricted – IService::cancel() is not supported by remote
- redirector, only engine provider supports it. That means one can use
- it only in embedded connections.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-top: 0.43cm; margin-bottom: 0.51cm; page-break-after: avoid">
- <font face="Albany, sans-serif"><font size="5" style="font-size: 18pt">Writing
- plugins.</font></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">To
- write a plugin means to implement some interfaces and place your
- implementation into dynamic library (.dll in windows or .so in linux)
- later referenced as </font><font size="4" style="font-size: 14pt"><i>plugin
- module</i></font> <font size="4" style="font-size: 14pt">or just
- </font><font size="4" style="font-size: 14pt"><i>module</i></font><font size="4" style="font-size: 14pt">.
- In most cases single plugin is placed</font> <font size="4" style="font-size: 14pt">into</font>
- <font size="4" style="font-size: 14pt">dynamic library but in common
- case multiple plugins may coexist in single dynamic library. One of
- that interfaces – <a href="#PluginModule">IPluginModule</a> – is
- module-wide (as more or less clear from it's name), others are per
- plugin. Also each plugin module should contain special exported
- entrypoint firebird_plugin() which name is defined in include file
- firebird/Interfaces.h as FB_PLUGIN_ENTRY_POINT.</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">In
- previous part of this text we were mostly describing how to use
- existing interfaces, here main attention will be paid to implementing
- interfaces yourself. Certainly to do it one can and should use
- already existing interfaces both generic needed for accessing
- firebird databases (already described) and some more interfaces
- specifically designed for plugins.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Following
- text is actively using example of database encryption plugin
- examples/dbcrypt/DbCrypt.cpp. It will be good idea to compile this
- sample yourself and learn it when reading later.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <h1><font size="4" style="font-size: 14pt">Implementation of plugin
- module.</font></h1>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Plugins
- actively interact with special firebird component called </font><font size="4" style="font-size: 14pt"><i>plugin
- manager</i></font><font size="4" style="font-size: 14pt">. In
- particular plugin manager should be aware what plugin modules were
- loaded and must be notified if operating system tries to unload one
- of that modules without explicit plugin manager command (this may
- happen first of all when using embedded access – when exit() is
- called in a program or main firebird library </font><font size="4" style="font-size: 14pt"><i>fbclient</i></font>
- <font size="4" style="font-size: 14pt">is unloaded). Primary task of
- IPluginModule interface is that notification. First of all one must
- decide - how to detect that module is going to be unloaded? When
- dynamic library is unloaded for some reason a lot of OS-dependent
- actions is performed and some of that actions may be used to detect
- this fact in the program. When writing plugins distributed with
- firebird we always use invocation of destructor of global variable.
- The big “plus” for this method is that it is OS independent
- (though something like atexit() function maybe also used
- successfully). But use of destructor makes it possible to easily
- concentrate almost everything related with unload detection in single
- class implementing at the same time <a href="#PluginModule">IPluginModule</a>
- interface.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Minimum
- implementation looks as follows:</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>class
- PluginModule : public IPluginModuleImpl<PluginModule,
- CheckStatusWrapper></i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>private:</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IPluginManager*
- pluginManager;</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>public:</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>PluginModule()</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>:
- pluginManager(NULL)</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{
- }</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>~PluginModule()</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>if
- (pluginManager)</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>pluginManager->unregisterModule(this);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>doClean();</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>void
- registerMe(IPluginManager* m)</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>pluginManager
- = m;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>pluginManager->registerModule(this);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>void
- doClean()</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>pluginManager
- = NULL;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>};</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">The
- only data member is plugin manager interface <a href="#PluginManager">IPluginManager</a>.
- It's passed to registerModule() function and saved in private
- variable, at the same time module is registered in plugin manager by
- the call to registerModule() method with own address as a single
- parameter. Variable </font><font size="4" style="font-size: 14pt"><i>pluginManager
- </i></font><font size="4" style="font-size: 14pt">not only stores
- pointer to interface, at the same time it serves as a flag that
- module is registered. When destructor of registered module is invoked
- it notifies plugin manager (yes, this is what for this class exists!)
- about unexpected unload by the call to unregisterModule() passing
- pointer to itself. When plugin manager is going to unload module in
- regular way in first of all calls doClean() method changing module
- state to unregistered and this avoiding call to unregisterModule()
- when OS performs actual unload.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Implementing
- plugin's interface IPluginModule we met with first interface required
- to implement plugins – <a href="#PluginManager">IPluginManager</a>.
- It will be actively used later, the rest of internals of this class
- will hardly be required to you after copying it to your program. Just
- don't forget to declare global variable of this type and call
- registerMe() function from FB_PLUGIN_ENTRY_POINT.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <h1><font size="4" style="font-size: 14pt">Core interface of any
- plugin.</font></h1>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Let's
- start implementing plugin itself. The type of main interface depends
- upon plugin type (which is obvious), but all of them are based on
- common reference counted interface IPluginBase which performs common
- for all plugins (and very simple) tasks. Each plugin has some (also
- reference counted) object which <i>owns</i> this plugin. In order to
- perform smart plugin lifetime management any plugin must be able to
- store that owner information and report it to plugin manager on
- request. That means that each plugin must implement two trivial
- methods setOwner() and getOwner() contained in IPluginBase interface.
- Type-dependent methods are certainly more interesting - they are
- discussed in interfaces description part.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Let's
- take a look at typical part of any plugin implementation (here I
- specially use non-existent type SomePlugin):</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>class
- MyPlugin : public ISomePluginImpl<MyPlugin, CheckStatusWrapper></i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>public:</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>explicit
- MyPlugin(<a href="#PluginConfig">IPluginConfig</a>* cnf) noexcept</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>:
- config(cnf), refCounter(0), owner(NULL)</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>config->addRef();</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
- <p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
- <font size="4" style="font-size: 14pt">Constructor gets as parameter
- plugin configuration interface. If you are going to have you plugin
- configured in some way it's good idea to save this interface in your
- plugin and use it later. This will let you use common for all
- firebird configuration style letting users have familiar
- configuration and minimize code written. Certainly when saving any
- reference counted interface it's better not forget to add reference
- to it. Also set reference counter to 0 and plugin owner to NULL.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>~MyPlugin()</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>config->release();</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
- <p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
- <font size="4" style="font-size: 14pt">Destructor releases config
- interface. Pay attention – we do not change reference counter of
- our owner cause it owns us, not we own it.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>//
- IRefCounted implementation</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>int
- release()</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>if
- (--refCounter == 0)</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>delete
- this;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>return
- 0;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>return
- 1;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>void
- addRef()</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>++refCounter;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
- <p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
- <font size="4" style="font-size: 14pt">Absolutely typical
- implementation of reference counted object.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>//
- IPluginBase implementation</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>void
- setOwner(IReferenceCounted* o)</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>owner
- = o;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IReferenceCounted*
- getOwner()</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>return
- owner;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
- <p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
- <font size="4" style="font-size: 14pt">As it was promised
- implementation of IPluginBase is trivial.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>//
- ISomePlugin implementation</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>//
- … here go various methods required for particular plugin type</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>private:</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IPluginConfig*
- config;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>std::atomic_int
- refCounter;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IReferenceCounted*
- owner;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>};</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">With
- this sample formal part of main plugin interface implementation is
- over. After adding type-specific methods (and writing probably a
- lo-o-o-ot of code to make them useful) interface is ready.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <h1><font size="4" style="font-size: 14pt">Plugin's factory.</font></h1>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">One
- more interface required for plugin to work is <a href="#PluginFactory">IPluginFactory</a>.
- Factory creates instances of plugin and returns them to plugin
- manager. Factory typically looks this way:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>class
- Factory : public IPluginFactoryImpl<Factory, CheckStatusWrapper></i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>public:</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IPluginBase*
- createPlugin(CheckStatusWrapper* status, IPluginConfig*
- factoryParameter)</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>MyPlugin*
- p = new MyPlugin(factoryParameter);</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>p->addRef();</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>return
- p;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>};</i></font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
- <font size="4" style="font-size: 14pt">Here attention should be payed
- to the fact that even in a case when code in a function may throw
- exceptions (operator new may throw in a case when memory exhausted)
- one need not always manually define try/catch block –
- implementation of firebird interfaces does this job for you, in
- implementation of IPluginFactory it's placed into template
- IPluginFactoryImpl. Take into an account that default status wrappers
- perform meaning-full processing only for FbException. But if you
- (that definitely makes sense if you work on some big project) define
- your own wrapper you can handle any type of C++ exception and pass
- useful information about it from your plugin.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <h1><font size="4" style="font-size: 14pt">Plugin module
- initialization entrypoint.</font></h1>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">When
- plugin manager loads plugin module it invokes module initializing
- routine – the only exported from plugin function
- FB_PLUGIN_ENTRY_POINT. To wrote it's code one will need two global
- variables – plugin module and plugin factory. In our case that is:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>PluginModule
- module;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>Factory
- factory;</i></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">If
- you module contains more than one plugin you will need a factory per
- each plugin.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">For
- FB_PLUGIN_ENTRY_POINT we should not forget that it should be exported
- from plugin module, and it requires taking into an account some OS
- specifics. We do it using macro FB_DLL_EXPORT defined in
- examples/interfaces/ifaceExamples.h. If you are sure you write plugin
- only for some specific OS you can make this place a bit simpler. In
- minimum case the function should register module and all factories in
- plugin manager:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">extern
- "C" FB_DLL_EXPORT void FB_PLUGIN_ENTRY_POINT(IMaster*
- master)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">{</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IPluginManager*
- pluginManager = master->getPluginManager();</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">module.registerMe(pluginManager);</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">pluginManager->registerPluginFactory(IPluginManager::TYPE_DB_CRYPT,
- "fbSampleDbCrypt", &factory);</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">}</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">First
- of all we call written by us not long ago PluginModule::registerMe()
- function which will saves IPluginManager for future use and registers
- our plugin module. Next time to register factory (or factories in
- case of multiple plugins per module) takes place. We must pass
- correct plugin type (valid types are enumerated in interface
- IPluginManager) and a name under which plugin will be registered. In
- simple case it should match with the name of dynamic library with
- plugin module. Following last rule will help you avoid configuring
- your plugin manually in plugins.conf.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Pay
- attention - unlike applications plugins should not use
- fb_get_master_interface() to obtain IMaster. Instance, passed to
- FB_PLUGIN_ENTRY_POINT, should be used instead. If you ever need
- master interface in your plugin take care about saving it in this
- function.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-top: 0.43cm; margin-bottom: 0.51cm; page-break-after: avoid">
- <font face="Albany, sans-serif"><font size="5" style="font-size: 18pt">Interfaces:
- from A to Z</font></font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">In
- this glossary we do not list interfaces that are not actively used
- (like IRequest, needed first of all to support legacy ISC API
- requests). Same reference may be made for a number of methods (like
- compileRequest() in IAttachment). For interfaces / methods, having
- direct analogue in old API, that analogue is provided.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <h1><font size="4" style="font-size: 14pt">Generic interfaces.</font></h1>
- <p style="margin-bottom: 0cm"><a name="Attachment"></a><font size="4" style="font-size: 14pt">Attachment
- interface – replaces isc_db_handle:</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- getInfo(StatusType* status, unsigned itemsLength, const unsigned
- char* items, unsigned bufferLength, unsigned char* buffer) –
- replaces isc_database_info().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ITransaction*
- startTransaction(StatusType* status, unsigned tpbLength, const
- unsigned char* tpb) – partially replaces isc_start_multiple(), to
- start >1 transaction <a href="#Dtc">distributed transactions
- coordinator</a> should be used, also possible to <a href="#Transaction">join</a>
- 2 transactions into single distributed transaction.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ITransaction*
- reconnectTransaction(StatusType* status, unsigned length, const
- unsigned char* id) – makes it possible to connect to a transaction
- in limbo. Id parameter contains transaction number in network format
- of given length.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IRequest*
- compileRequest(StatusType* status, unsigned blrLength, const
- unsigned char* blr) – support of ISC API.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- transactRequest(StatusType* status, ITransaction* transaction,
- unsigned blrLength, const unsigned char* blr, unsigned inMsgLength,
- const unsigned char* inMsg, unsigned outMsgLength, unsigned char*
- outMsg) – support of ISC API.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IBlob*
- createBlob(StatusType* status, ITransaction* transaction, ISC_QUAD*
- id, unsigned bpbLength, const unsigned char* bpb) – creates new
- blob, stores it's identifier in id, replaces isc_create_blob2().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IBlob*
- openBlob(StatusType* status, ITransaction* transaction, ISC_QUAD*
- id, unsigned bpbLength, const unsigned char* bpb) – opens existing
- blob, replaces isc_open_blob2().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
- getSlice(StatusType* status, ITransaction* transaction, ISC_QUAD*
- id, unsigned sdlLength, const unsigned char* sdl, unsigned
- paramLength, const unsigned char* param, int sliceLength, unsigned
- char* slice) - support of ISC API.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- putSlice(StatusType* status, ITransaction* transaction, ISC_QUAD*
- id, unsigned sdlLength, const unsigned char* sdl, unsigned
- paramLength, const unsigned char* param, int sliceLength, unsigned
- char* slice) - support of ISC API.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- executeDyn(StatusType* status, ITransaction* transaction, unsigned
- length, const unsigned char* dyn) - support of ISC API.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IStatement*
- prepare(StatusType* status, ITransaction* tra, unsigned stmtLength,
- const char* sqlStmt, unsigned dialect, unsigned flags) – replaces
- isc_dsql_prepare(). Additional parameter flags makes it possible to
- control what information will be preloaded from engine at once (i.e.
- in single network packet for remote operation).</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ITransaction*
- execute(StatusType* status, ITransaction* transaction, unsigned
- stmtLength, const char* sqlStmt, unsigned dialect, IMessageMetadata*
- inMetadata, void* inBuffer, IMessageMetadata* outMetadata, void*
- outBuffer) – executes any SQL statement except returning multiple
- rows of data. Partial analogue of isc_dsql_execute2() - in and out
- XSLQDAs replaced with input and output messages with appropriate
- buffers.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IResultSet*
- openCursor(StatusType* status, ITransaction* transaction, unsigned
- stmtLength, const char* sqlStmt, unsigned dialect, IMessageMetadata*
- inMetadata, void* inBuffer, IMessageMetadata* outMetadata, const
- char* cursorName, unsigned cursorFlags) – executes SQL statement
- potentially returning multiple rows of data. Returns <a href="#ResultSet">ResultSet</a>
- interface which should be used to fetch that data. Format of output
- data is defined by outMetadata parameter, leaving it NULL default
- format may be used. Parameter cursorName specifies name of opened
- cursor (analogue of isc_dsql_set_cursor_name()). Parameter
- cursorFlags is needed to open bidirectional cursor setting it's
- value to Istatement::CURSOR_TYPE_SCROLLABLE.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IBatch*
- createBatch(StatusType* status, ITransaction* transaction, unsigned
- stmtLength, const char* sqlStmt, unsigned dialect, IMessageMetadata*
- inMetadata, unsigned parLength, const unsigned char* par) –
- prepares sqlStmt and creates <a href="#Batch">Batch</a> interface
- ready to accept multiple sets of input parameters in inMetadata
- format. Leaving inMetadata NULL makes batch use default format for
- sqlStmt. Parameters block may be passed to createBatch() making it
- possible to adjust batch behavior.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IEvents*
- queEvents(StatusType* status, IEventCallback* callback, unsigned
- length, const unsigned char* events) – replaces isc_que_events()
- call. Instead callback function with void* parameter callback
- interface is used.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- cancelOperation(StatusType* status, int option) – replaces
- fb_cancel_operation().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- ping(StatusType* status) – check connection status. If test fails
- the only operation possible with attachment is to close it.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- detach(StatusType* status) – replaces isc_detach_database(). On
- success releases interface.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- dropDatabase(StatusType* status) - replaces isc_drop_database(). On
- success releases interface.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Batch"></a><font size="4" style="font-size: 14pt">Batch
- interface – makes it possible to process multiple sets of
- parameters in single statement execution.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- add(StatusType* status, unsigned</font> <font size="4" style="font-size: 14pt">count,
- const void* inBuffer) – adds count messages from inBuffer to the
- batch. Total size of messages that can be added to the batch is
- limited by TAG_BUFFER_BYTES_SIZE <a href="#Batch_PB">parameter</a>
- of batch creation.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- addBlob(StatusType* status, unsigned</font> <font size="4" style="font-size: 14pt">length,
- const void* inBuffer, ISC_QUAD* blobId, unsigned bpbLength, const
- unsigned char* bpb) – adds single blob having length bytes from
- inBuffer to the batch, blob identifier is located at blobId address.
- If blob should be created with non-default parameters BPB may be
- passed (format matches one used in <a href="#Attachment">Attachment</a>::createBlob).Total
- size of inline blobs that can be added to the batch (including
- optional BPBs, blob headers, segment sizes and taking into an
- accoount alignment) is limited by TAG_BUFFER_BYTES_SIZE <a href="#Batch_PB">parameter</a>
- of batch creation (affects all blob-oriented methods except
- registerBlob()). </font>
- </p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- appendBlobData(StatusType* status, unsigned length, const void*
- inBuffer) – extend last added blob: append length bytes taken from
- inBuffer address to it.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- addBlobStream(StatusType* status, unsigned length, const void*
- inBuffer) – adds blob data (this can be multiple objects or part
- of single blob) to the batch. Header of each blob in the stream is
- aligned at getBlobAlignment() boundary and contains 3 fields: first
- - 8-bytes blob identifier (in ISC_QUAD format), second - 4-bytes
- length of blob, third – 4-bytes length of BPB. Blob header should
- not cross boundaries of buffer in this function call. BPB data is
- placed right after header, blob data goes next. Length of blob
- includes BPB (if it present). All data may be distributed between
- multiple addBlobStream() calls. Blob data in turn may be structured
- in case of segmented blob, see chapter “<a href="#Modifying data in a batch">Modifying
- data in a batch</a>”.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- registerBlob(StatusType* status, const ISC_QUAD* existingBlob,
- ISC_QUAD* blobId) – makes it possible to use in batch blobs added
- using standard <a href="#Blob">Blob</a> interface. This function
- contains 2 ISC_QUAD* parameters, it’s important not to mix them –
- second parameter (existingBlob) is a pointer to blob identifier,
- already added out of batch scope, third (blobId) points to blob
- identifier that will be placed in a message in this batch.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><a href="#BatchCompletionState">IBatchCompletionState</a>*
- execute(StatusType* status, ITransaction* transaction) – execute
- batch with parameters passed to it in the messages. If parameter
- MULTIERROR is not set in <a href="#Batch_PB">parameters block</a>
- when creating the batch execution will be stopped after first error,
- in MULTIERROR mode an unlimited number of errors can happen, after
- an error execution is continued from the next message. This function
- returns BatchCompletionState interface that contains all requested
- nformation about the results of batch execution.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- cancel(StatusType* status) – clear messages and blobs buffers,
- return batch to a state it had right after creation. Notice –
- being reference counted interface batch does not contain any special
- function to close it, please use release() for this purposes. </font>
- </p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getBlobAlignment(StatusType* status) – returns required alignment
- for the data placed into the buffer of addBlobStream().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IMessageMetadata*
- getMetadata(StatusType* status) – return format of metadata used
- in batch’s messages.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setDefaultBpb(StatusType* status, unsigned parLength, const unsigned
- char* par) – sets BPB which will be used for all blobs missing
- non-default BPB. Must be called before adding any message or blob to
- batch.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- getInfo(StatusType* status, unsigned itemsLength, const unsigned
- char* items, unsigned bufferLength, unsigned char* buffer) –
- requests information about batch.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><a name="Batch_PB"></a><font size="4" style="font-size: 14pt">Tag
- for parameters block:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">VERSION1</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Tags
- for clumplets in parameters block:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TAG_MULTIERROR
- (0/1) – can have >1 message with errors</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TAG_RECORD_COUNTS
- (0/1) - per-message modified records accounting</font></p>
- <p style="margin-bottom: 0cm"><a name="TAG_BUFFER_BYTES_SIZE"></a><font size="4" style="font-size: 14pt">TAG_BUFFER_BYTES_SIZE
- (integer) - maximum possible buffer size on server (default 16Mb,
- maximum 256Mb)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TAG_BLOB_POLICY
- - <a href="#Batch_Blob_Policy">policy</a> used to store blobs</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TAG_DETAILED_ERRORS
- (integer) - how many vectors with detailed error info are stored in
- completion state (default 64, maximum 256)</font></p>
- <p style="margin-bottom: 0cm"><a name="Batch_Blob_Policy"></a><font size="4" style="font-size: 14pt">Policies
- used to store blobs:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">BLOB_NONE
- – inline blobs can't be used (registerBlob() works anyway)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">BLOB_ID_ENGINE
- - blobs are added one by one, IDs are generated by firebird engine</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">BLOB_ID_USER
- - blobs are added one by one, IDs are generated by user</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">BLOB_STREAM
- - blobs are added in a stream</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Items
- accepted in getInfo() call:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">INF_BUFFER_BYTES_SIZE
- – actual </font><font color="#000000"><font size="4" style="font-size: 14pt">m</font></font><font size="4" style="font-size: 14pt">aximum
- possible buffer size (one set by TAG_BUFFER_BYTES_SIZE)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">INF_DATA_BYTES_SIZE
- - already added messages size</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">INF_BLOBS_BYTES_SIZE
- - already added blobs size</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">INF_BLOB_ALIGNMENT
- - required alignment for the BLOB data (duplicates getBlobAlignment)</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="BatchCompletionState"></a><font size="4" style="font-size: 14pt">BatchCompletionState
- – disposable interface, always returned by execute() method of
- <a href="#Batch">Batch</a> interface. It contains more or less
- (depending upon parameters passed when <a href="#Batch">Batch</a> was
- created) detailed information about the results of batch execution.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">uint
- getSize(StatusType* status) – returns the total number of
- processed messages.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
- getState(StatusType* status, uint pos) – returns the result of
- execution of message number ‘pos’. On any error with the message
- this is EXECUTE_FAILED constant, value returned on success depends
- upon presence of RECORD_COUNTS <a href="#Batch_PB">parameter</a> of
- batch creation. When it present and has non-zero value number of
- records inserted, updated or deleted during particular message
- processing is returned, else SUCCESS_NO_INFO constant is returned.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">uint
- findError(StatusType* status, uint pos) – finds next (starting
- with pos) message which processing caused an error. When such
- message is missing NO_MORE_ERRORS constant is returned. Number of
- status vectors, returned in this interface, is limited by the value
- of DETAILED_ERRORS <a href="#Batch_PB">parameter</a> of batch
- creation.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- getStatus(StatusType* status, IStatus* to, uint pos) – returns
- detailed information (full status vector) about an error that took
- place when processing ‘pos’ message. In order to distinguish
- between errors (in <a href="#Batch">Batch</a>::execute() or in
- <a href="#BatchCompletionState">BatchCompletionState</a>::getStatus())
- that status is returned in separate ‘to’ parameter unlike errors
- in this call that are placed into ‘status’ parameter.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Special
- values returned by getState():</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">EXECUTE_FAILED
- - error happened when processing this message</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">SUCCESS_NO_INFO
- - record update info was not collected</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Special
- value returned by findError():</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">NO_MORE_ERRORS
- – no more messages with errors in this batch</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Blob"></a><font size="4" style="font-size: 14pt">Blob
- interface – replaces isc_blob_handle:</font></p>
- <ol>
- <li value="1"><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- getInfo(StatusType* status, unsigned itemsLength, const unsigned
- char* items, unsigned bufferLength, unsigned char* buffer) –
- replaces isc_blob_info().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
- getSegment(StatusType* status, unsigned bufferLength, void* buffer,
- unsigned* segmentLength) – replaces isc_get_segment(). Unlike it
- never returns isc_segstr_eof and isc_segment errors (that are
- actually not errors), instead returns <a href="#Completion codes">completion
- codes</a> IStatus::RESULT_NO_DATA and IStatus::RESULT_SEGMENT,
- normal return is IStatus::RESULT_OK.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- putSegment(StatusType* status, unsigned length, const void* buffer)
- – replaces isc_put_segment().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- cancel(StatusType* status) – replaces isc_cancel_blob(). On
- success releases interface.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- close(StatusType* status) – replaces isc_close_blob(). On success
- releases interface.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
- seek(StatusType* status, int mode, int offset) – replaces
- isc_seek_blob().</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Config"></a><font size="4" style="font-size: 14pt">Config
- interface – generic configuration file interface:</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IConfigEntry*
- find(StatusType* status, const char* name) – find entry by name.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IConfigEntry*
- findValue(StatusType* status, const char* name, const char* value) –
- find entry by name and value.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IConfigEntry*
- findPos(StatusType* status, const char* name, unsigned pos) – find
- entry by name and position. If configuration file contains lines:</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Db=DBA</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Db=DBB</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Db=DBC</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">call
- to findPos(status, “Db”, 2) will return entry with value DBB.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="ConfigManager"></a><font size="4" style="font-size: 14pt">ConfigManager
- interface – generic interface to access various configuration
- objects:</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* getDirectory(unsigned code) – returns location of
- appropriate directory in current firebird instance. See codes for
- this call a <a href="#Directory codes">few lines later</a>.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IFirebirdConf*
- getFirebirdConf() - returns interface to access default
- configuration values (from firebird.conf).</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IFirebirdConf*
- getDatabaseConf(const char* dbName) - returns interface to access
- db-specific configuration (takes into an account firebird.conf and
- appropriate part of databases.conf).</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IConfig*
- getPluginConfig(const char* configuredPlugin) – returns interface
- to access named plugin configuration.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* getInstallDirectory() - returns directory where firebird is
- installed.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* getRootDirectory() - returns root directory of current
- instance, in single-instance case usually matches install directory.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* getDefaultSecurityDb() - returns default (i.e. not taking into
- an account configuration files) pathname of security database, used
- first of all internally to enable correct access to security
- database on multi-provider server with zero configuration.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><a name="Directory codes"></a><font size="4" style="font-size: 14pt">Directory
- codes:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_BIN
- – bin (utilities like isql, gbak, gstat)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_SBIN
- – sbin (fbguard and firebird server)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_CONF
- – configuration files (firebird.conf, databases.conf, plugins.conf)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_LIB
- – lib (fbclient, ib_util)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_INC
- – include (ibase.h, firebird/Interfaces.h)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_DOC
- - documentation</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_UDF
- – UDF (ib_udf, fbudf)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_SAMPLE
- - samples</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_SAMPLEDB
- – samples database (employee.fdb)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_INTL
- – international libraries (fbintl)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_MISC
- – miscellaneous files (like uninstall manifest and something else)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_SECDB
- – where security database is stored (securityN.fdb)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_MSG
- – where messages file is stored (firebird.msg)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_LOG
- – where log file is stored (firebird.log)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_GUARD
- – where guardian lock is stored (fb_guard)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_PLUGINS
- – plugins directory ([lib]Engine13.{dll|so})</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="ConfigEntry"></a><font size="4" style="font-size: 14pt">ConfigEntry
- interface – represents an entry (Key = Values with probably
- sub-entries) in firebird configuration file:</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* getName() - returns key name.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* getValue() - returns value as character string.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ISC_INT64
- getIntValue() - treats value as integer and returns it.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN
- getBoolValue() - treats value as boolean and returns it.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IConfig*
- getSubConfig(StatusType* status) – treats sub-entries as separate
- configuration file and returns Config interface for it.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="DecFloat16"></a><a name="DecFloat34"></a>
- <font size="4" style="font-size: 14pt">DecFloat16 / DecFloat34 –
- interfaces that help to work with DECFLOAT (16 & 34 respectively)
- datatypes. They have almost same set of methods with FB_DEC16
- parameter replaced by FB_DEC34 for DecFloat34:</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- toBcd(const FB_DEC16* from, int* sign, unsigned char* bcd, int* exp)
- – convert decimal float value to BCD.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- toString(StatusType* status, const FB_DEC16* from, unsigned
- bufferLength, char* buffer) – convert decimal float value to
- string.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- fromBcd(int sign, const unsigned char* bcd, int exp, FB_DEC16* to) –
- make decimal float value from BCD.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- fromString(StatusType* status, const char* from, FB_DEC16* to) –
- make decimal float value from string.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Dtc"></a><font size="4" style="font-size: 14pt"><font color="#000000">Dtc
- </font>interface – distributed transactions coordinator. Used to
- start distributed (working with 2 or more attachments) transaction.
- Unlike pre-FB3 approach where distributed transaction must be started
- in this way from the most beginning FB3's distributed transactions
- coordinator makes it also possible to join already started
- transactions into single distributed transaction.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ITransaction*
- join(StatusType* status, ITransaction* one, ITransaction* two) –
- joins 2 independent transactions into distributed transaction. On
- success both transactions passed to join() are released and pointers
- to them should not be used any more.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IDtcStart*
- startBuilder(StatusType* status) – returns <a href="#DtcStart">DtcStart</a>
- interface.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="DtcStart"></a><font size="4" style="font-size: 14pt">DtcStart
- interface – replaces array of struct TEB (passed to
- isc_start_multiple() in ISC API). This interface accumulates
- attachments (and probably appropriate TPBs) for which dustributed
- transaction should be started.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- addAttachment(StatusType* status, IAttachment* att) – adds
- attachment, transaction for it will be started with default TPB.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- addWithTpb(StatusType* status, IAttachment* att, unsigned length,
- const unsigned char* tpb) - adds attachment and TPB which will be
- used to start transaction for this attachment.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ITransaction*
- start(StatusType* status) – start distributed transaction for
- accumulated attachments. On successful return DtcStart interface is
- disposed automatically.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="EventCallback"></a><font size="4" style="font-size: 14pt">EventCallback
- interface – replaces callback function used in isc_que_events()
- call. Should be implemented by user to monitor events with
- IAttachment::queEvents() method.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- eventCallbackFunction(unsigned length, const unsigned char* events)
- – is called each time event happens.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Events"></a><font size="4" style="font-size: 14pt">Events
- interface – replaces event identifier when working with events
- monitoring.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- cancel(StatusType* status) - cancels events monitoring started by
- IAttachment::queEvents().</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FirebirdConf
- interface – access to main firebird configuration. Used for both
- default configuration, set by firebird.conf, and per-database
- configuration, adjusted by databases.conf. In order to speed up
- access to configuration values calls accessing actual values use
- integer key instead symbolic parameter name. Key is stable during
- server run (i.e. plugin can get it once and than use to get
- configuration value for different databases). </font>
- </p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getKey(const char* name) – get key for parameter name. ~0 (all
- bits are 1) is returned in a case when there is no such parameter.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ISC_INT64
- asInteger(unsigned key) – return value of integer parameter.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* asString(unsigned key) - return value of string parameter.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN
- asBoolean(unsigned key) - return value of boolean parameter.
- Standard abbreviations (1/true/t/yes/y) are treated as “true”,
- all other cases – false.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getVersion(StatusType* status) – get version of configuration
- manager associated with this interface. Different versions of
- configuration manager may coexist on same server for example when
- old DB engine is in use on modern server. Pay attention – keys
- (see getKey()) from different versions do not match and when used
- inappropriately will always return 0/nullptr/false.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Int128"></a><font size="4" style="font-size: 14pt">Int128
- interfaces that help to work with 128-bit integers (used as base type
- for numeric and decimal with precision > 18).</font></p>
- <ol>
- <li value="1"><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- toString(StatusType* status, const FB_I128* from, int scale,
- unsigned bufferLength, char* buffer) – convert 128-bit integer
- value to string taking scale into an account.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- fromString(StatusType* status, int scale, const char* from, FB_I128*
- to) – make 128-bit integer value from string taking scale into an
- account.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Master"></a><font size="4" style="font-size: 14pt">Master
- interface – main interface from which start all operations with
- firebird API.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IStatus*
- getStatus() - get instance of <a href="#Status">Status</a>
- interface.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IProvider*
- getDispatcher() - get instance of <a href="#Provider">Provider</a>
- interface, implemented by yValve (main provider instance).</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IPluginManager*
- getPluginManager() - get instance of <a href="#PluginManager">PluginManager</a>
- interface.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ITimerControl*
- getTimerControl() - get instance of <a href="#TimerControl">TimerControl</a>
- interface.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IDtc*
- getDtc() - get instance of <a href="#Dtc">Dtc</a> interface.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IUtil*
- getUtilInterface() - get instance of <a href="#Util">Util</a>
- interface.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IConfigManager*
- getConfigManager() - get instance of <a href="#ConfigManager">ConfigManager</a>
- interface.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="MessageMetadata"></a><font size="4" style="font-size: 14pt">MessageMetadata
- interface – partial analogue of XSQLDA (does not contain message
- data, only message format info is present). Used in a calls related
- with execution of SQL statements.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getCount(StatusType* status) – returns number of fields/parameters
- in a message. In all calls, containing index parameter, it's value
- should be: 0 <= index < getCount().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* getField(StatusType* status, unsigned index) – returns field
- name.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* getRelation(StatusType* status, unsigned index) – returns
- relation name (from which given field is selected).</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* getOwner(StatusType* status, unsigned index) - returns
- relation's owner name.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* getAlias(StatusType* status, unsigned index) - returns field
- alias.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getType(StatusType* status, unsigned index) - returns field SQL
- type.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN
- isNullable(StatusType* status, unsigned index) - returns true if
- field is nullable.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
- getSubType(StatusType* status, unsigned index) - returns blof field
- subtype (0 – binary, 1 – text, etc.).</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getLength(StatusType* status, unsigned index) - returns maximum
- field length.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
- getScale(StatusType* status, unsigned index) - returns scale factor
- for numeric field.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getCharSet(StatusType* status, unsigned index) - returns character
- set for character field and text blob.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getOffset(StatusType* status, unsigned index) - returns offset of
- field data in message buffer (use it to access data in message
- buffer).</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getNullOffset(StatusType* status, unsigned index) - returns offset
- of null indicator for a field in message buffer.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IMetadataBuilder*
- getBuilder(StatusType* status) - returns <a href="#MessageMetadata">MetadataBuilder</a>
- interface initialized with this message metadata.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getMessageLength(StatusType* status) - returns length of message
- buffer (use it to allocate memory for the buffer).</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getAlignment(StatusType* status) – returns alignment required for
- message buffer.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getAlignedLength(StatusType* status) – returns length of message
- buffer taking into an account alignment requirements (use it to
- allocate memory for an array of buffers and navigate through that
- array).</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="MetadataBuilder"></a><font size="4" style="font-size: 14pt">MetadataBuilder
- interface – makes it possible to coerce datatypes in existing
- message or construct metadata from the beginning.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setType(StatusType* status, unsigned index, unsigned type) – set
- SQL type of a field.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setSubType(StatusType* status, unsigned index, int subType) – set
- blof field subtype.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setLength(StatusType* status, unsigned index, unsigned length) –
- set maximum length of character field.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setCharSet(StatusType* status, unsigned index, unsigned charSet) –
- set character set for character field and text blob.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setScale(StatusType* status, unsigned index, unsigned scale) – set
- scale factor for numeric field </font>
- </p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- truncate(StatusType* status, unsigned count) – truncate message to
- contain not more than count fields.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- moveNameToIndex(StatusType* status, const char* name, unsigned
- index) – reorganize fields in a message – move field “name”
- to given position.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- remove(StatusType* status, unsigned index) – remove field.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- addField(StatusType* status) – add field.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IMessageMetadata*
- getMetadata(StatusType* status) – get <a href="#10. MessageMetadata">MessageMetadata</a>
- interface built by this builder.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setField(StatusType* status, uint index, const string field) – set
- name of a field / column.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setRelation(StatusType* status, uint index, const string relation) –
- set name of the relation from which the field was selected.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setOwner(StatusType* status, uint index, const string owner) – set
- name of that relation owner.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setAlias(StatusType* status, uint index, const string alias) – set
- alias name of the field in related statement.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="OffsetsCallback"></a><font size="4" style="font-size: 14pt">OffsetsCallback
- interface:</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">setOffset(StatusType*
- status, unsigned index, unsigned offset, unsigned nullOffset) –
- notifies that offsets for field/parameter number “index” should
- be set to passed values. Should be implemented by user when
- implementing <a href="#MessageMetadata">MessageMetadata</a>
- interface and using <a href="#Util">Util</a>::setOffsets().</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="PluginConfig"></a><font size="4" style="font-size: 14pt">PluginConfig
- interface – passed to plugin's factory when plugin instance (with
- particular configuration) to be created.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* getConfigFileName() - recommended file name where
- configuration for plugin is expected to be stored.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IConfig*
- getDefaultConfig(StatusType* status) – plugin configuration loaded
- with default rules.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IFirebirdConf*
- getFirebirdConf(StatusType* status) – master firebird
- configuration taking into an account per-database settings for a
- database with which will work new instance of plugin.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setReleaseDelay(StatusType* status, ISC_UINT64 microSeconds) –
- used by plugin to configure recommended delay during which plugin
- module will not be unloaded by plugin manager after release of last
- plugin instance from that module.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="PluginFactory"></a><font size="4" style="font-size: 14pt">PluginFactory
- interface – should be implemented by plugin author when writing
- plugin.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IPluginBase*
- createPlugin(StatusType* status, IPluginConfig* factoryParameter) –
- creates new instance of plugin with passed recommended
- configuration.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="PluginManager"></a><font size="4" style="font-size: 14pt">PluginManager
- interface – API of plugin manager.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- registerPluginFactory(unsigned pluginType, const char* defaultName,
- IPluginFactory* factory) – registers named factory of plugins of
- given type.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- registerModule(IPluginModule* cleanup) – registers plugin module.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- unregisterModule(IPluginModule* cleanup) – unregisters plugin
- module (in case of unexpected unload by OS).</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IPluginSet*
- getPlugins(StatusType* status, unsigned pluginType, const char*
- namesList, IFirebirdConf* firebirdConf) – returns PluginSet
- interface providing access to list of plugins of given type. Names
- of plugins to be included are taken from namesList, when missing
- (NULL) – from configuration setting for given pluginType. If
- firebirdConf parameter is specified it is used for all configuration
- purporses (including getting list of plugins and passing to
- <a href="#PluginFactory">PluginFactory</a>::createPlugin() method),
- if missing (NULL) – default configuration (from firebird.conf) is
- used.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IConfig*
- getConfig(StatusType* status, const char* filename) – returns
- Config interface for given configuration file name. Can be used by
- plugins to access configuration files with standard format but
- non-default name.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- releasePlugin(IPluginBase* plugin) – release given plugin. Should
- be used for plugins instead simple release() due to need to perform
- additional actions with plugin owner before actual release.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Constants
- defined by PluginManager interface (plugin types):</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TYPE_PROVIDER</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TYPE_AUTH_SERVER</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TYPE_AUTH_CLIENT</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TYPE_AUTH_USER_MANAGEMENT</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TYPE_EXTERNAL_ENGINE</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TYPE_TRACE</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TYPE_WIRE_CRYPT</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TYPE_DB_CRYPT</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TYPE_KEY_HOLDER</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="PluginModule"></a><font size="4" style="font-size: 14pt">PluginModule
- interface – represents plugin module (dynamic library). Should be
- implemented by plugin author in each plugin module (one instance per
- module).</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- doClean() - called by plugin manager before normal unload of plugin
- module.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">PluginSet
- interface – represents set of plugins of given type. Typically used
- by internal firebird code but recommended for use in plugins loading
- other plugins.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* getName() - get name of current plugin in a set.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* getModuleName() - get name of a module of current plugin in a
- set (in simple case matches plugin name).</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IPluginBase*
- getPlugin(StatusType* status) – get an instance of current plugin,
- returned interface should be casted to main interface of plugin of
- requested in <a href="#PluginManager">PluginManager</a>::getPlugins()
- type. Returns NULL if set does not contain any more plugins.
- Reference counter of plugin, returned by this function, is
- incremented on return – do not forget to use releasePlugin()
- method of <a href="#PluginManager">PluginManager</a> for plugins
- returned by this method.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- next(StatusType* status) – make set to switch to next plugin from
- the list.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- set(StatusType* status, const char* list) – reset interface: make
- it work with list of plugins provided by list parameter. Type of
- plugins remains unchanged.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Provider"></a><font size="4" style="font-size: 14pt">Provider
- interface – main interface to start database / service access.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IAttachment*
- attachDatabase(StatusType* status, const char* fileName, unsigned
- dpbLength, const unsigned char* dpb) – replaces
- isc_attach_database().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IAttachment*
- createDatabase(StatusType* status, const char* fileName, unsigned
- dpbLength, const unsigned char* dpb) – replaces
- isc_create_database().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IService*
- attachServiceManager(StatusType* status, const char* service,
- unsigned spbLength, const unsigned char* spb) – replaces
- isc_service_attach().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- shutdown(StatusType* status, unsigned timeout, const int reason) –
- replaces fb_shutdown().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setDbCryptCallback(StatusType* status, ICryptKeyCallback*
- cryptCallback) – sets database encryption callback interface that
- will be used for following database and service attachments. See …
- for details.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="ResultSet"></a><font size="4" style="font-size: 14pt">ResultSet
- interface – replaces (with extended functionality) some functions
- of isc_stmt_handle. This interface is returned by openCursor() call
- in <a href="#Attachment">IAttachment</a> or <a href="#Statement">IStatement</a>.
- All fetch calls except fetchNext() work only for bidirectional
- (opened with CURSOR_TYPE_SCROLLABLE flag) result set.</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Items
- accepted in getInfo() call:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">INF_RECORD_COUNT
- – number of records stored inside a scrollable cursor, or -1 for a
- uni-directional cursor.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
- fetchNext(StatusType* status, void* message) – fetch next record,
- replaces isc_dsql_fetch(). This method (and other fetch methods)
- returns <a href="#Completion codes">completion code</a>
- Status::RESULT_NO_DATA when EOF is reached, Status::RESULT_OK on
- success.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
- fetchPrior(StatusType* status, void* message) – fetch previous
- record.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
- fetchFirst(StatusType* status, void* message) – fetch first
- record.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
- fetchLast(StatusType* status, void* message) – fetch last record.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
- fetchAbsolute(StatusType* status, int position, void* message) –
- fetch record by it's absolute position in result set.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
- fetchRelative(StatusType* status, int offset, void* message) –
- fetch record by position relative to current.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN
- isEof(StatusType* status) – check for EOF.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN
- isBof(StatusType* status) – check for BOF.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IMessageMetadata*
- getMetadata(StatusType* status) – get metadata for messages in
- result set, specially useful when result set is opened by
- <a href="#Attachment">IAttachment</a>::openCursor() call with NULL
- output metadata format parameter (this is the only way to obtain
- message format in this case).</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- close(StatusType* status) – close result set, releases interface
- on success.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- getInfo(StatusType* status, unsigned itemsLength, const unsigned
- char* items, unsigned bufferLength, unsigned char* buffer) –
- retrieve information about result set.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Service"></a><font size="4" style="font-size: 14pt">Service
- interface – replaces isc_svc_handle.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- detach(StatusType* status) – close attachment to services manager,
- on success releases interface. Replaces isc_service_detach().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- query(StatusType* status, unsigned sendLength, const unsigned char*
- sendItems, unsigned receiveLength, const unsigned char*
- receiveItems, unsigned bufferLength, unsigned char* buffer) – send
- and request information to/from service, with different receiveItems
- may be used for both running services and to obtain various
- server-wide information. Replaces isc_service_query().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- start(StatusType* status, unsigned spbLength, const unsigned char*
- spb) – start utility in services manager. Replaces
- isc_service_start().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- cancel(StatusType* status) – cancel wait of current query() call.
- Supported only for embedded connections.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Statement"></a><font size="4" style="font-size: 14pt">Statement
- interface – replaces (partially) isc_stmt_handle.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- getInfo(StatusType* status, unsigned itemsLength, const unsigned
- char* items, unsigned bufferLength, unsigned char* buffer) –
- replaces isc_dsql_sql_info().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getType(StatusType* status) – statement type, currently can be
- found only in firebird sources in dsql/dsql.h.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* getPlan(StatusType* status, FB_BOOLEAN detailed) – returns
- statement execution plan.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ISC_UINT64
- getAffectedRecords(StatusType* status) – returns number of records
- affected by statement.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IMessageMetadata*
- getInputMetadata(StatusType* status) – returns parameters
- metadata.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IMessageMetadata*
- getOutputMetadata(StatusType* status) – returns output values
- metadata.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ITransaction*
- execute(StatusType* status, ITransaction* transaction,
- IMessageMetadata* inMetadata, void* inBuffer, IMessageMetadata*
- outMetadata, void* outBuffer) – executes any SQL statement except
- returning multiple rows of data. Partial analogue of
- isc_dsql_execute2() - in and out XSLQDAs replaced with input and
- output messages with appropriate buffers.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IResultSet*
- openCursor(StatusType* status, ITransaction* transaction,
- IMessageMetadata* inMetadata, void* inBuffer, IMessageMetadata*
- outMetadata, unsigned flags) – executes SQL statement potentially
- returning multiple rows of data. Returns <a href="#ResultSet">ResultSet</a>
- interface which should be used to fetch that data. Format of output
- data is defined by outMetadata parameter, leaving it NULL default
- format may be used. Parameter flags is needed to open bidirectional
- cursor setting it's value to Istatement::CURSOR_TYPE_SCROLLABLE.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IBatch*
- createBatch(StatusType* status, IMessageMetadata* inMetadata, uint
- parLength, const uchar* par) – creates <a href="#Batch">Batch</a>
- interface to SQL statement with input parameters making it possible
- to execute that statement with multiple sets of parameters. Format
- of input data is defined by inMetadata parameter, leaving it NULL
- makes batch use default format from this interface. Parameters block
- may be passed to createBatch() making it possible to adjust batch
- behavior.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setCursorName(StatusType* status, const char* name) – replaces
- isc_dsql_set_cursor_name().</font>
- </p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- free(StatusType* status) – free statement, releases interface on
- success.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getFlags(StatusType* status) – returns <a href="#Values returned by getFlags">flags</a>
- describing how this statement should be executed, simplified
- replacement of getType() method.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Constants
- defined by Statement interface:</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IAttachment::prepare()
- flags:</font></p>
- <p style="margin-left: 0.96cm; text-indent: -0.02cm; margin-bottom: 0cm; page-break-before: auto; page-break-after: auto">
- <font size="4" style="font-size: 14pt">PREPARE_PREFETCH_NONE –
- constant to pass no flags, 0 value.</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">The
- following flags may be OR-ed to get desired set of flags:</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">PREPARE_PREFETCH_TYPE</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">PREPARE_PREFETCH_INPUT_PARAMETERS</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">PREPARE_PREFETCH_OUTPUT_PARAMETERS</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">PREPARE_PREFETCH_LEGACY_PLAN</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">PREPARE_PREFETCH_DETAILED_PLAN</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">PREPARE_PREFETCH_AFFECTED_RECORDS</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">PREPARE_PREFETCH_FLAGS
- (flags returned by getFlags() method)</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Frequently
- used combinations of flags:</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">PREPARE_PREFETCH_METADATA</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">PREPARE_PREFETCH_ALL
- </font>
- </p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Values returned by getFlags"></a>
- <font size="4" style="font-size: 14pt">Values returned by getFlags()
- method: </font>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FLAG_HAS_CURSOR
- – use openCursor() to execute this statement, not execute()</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FLAG_REPEAT_EXECUTE
- – when prepared statement may be executed many times with different
- parameters</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Flags passed to openCursor"></a>
- <font size="4" style="font-size: 14pt">Flags passed to openCursor():</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">CURSOR_TYPE_SCROLLABLE
- – open bidirectional cursor.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Status"></a><font size="4" style="font-size: 14pt">Status
- interface – replaces ISC_STATUS_ARRAY. Functionality is extended –
- Status has separate access to errors and warnings vectors, can hold
- vectors of unlimited length, itself stores strings used in vectors
- avoiding need in circular strings buffer. In C++ Status is always
- used under status wrapper, C++ API provides two different <a href="#Status Wrapper">wrappers</a>
- having different behavior when error is returned from API call.
- Interface is on purpose minimized (methods like convert it to text
- are moved to <a href="#Util">Util</a> interface) in order to simplify
- it's implementation by users when needed.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- init() - cleanup interface, set it to initial state.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getState() - get current state of interface, returns <a href="#returned by getState">state
- flags</a>, may be OR-ed.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setErrors2(unsigned length, const intptr_t* value) – set contents
- of errors vector with length explicitly specified in a call.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setWarnings2(unsigned length, const intptr_t* value) – set
- contents of warnings vector with length explicitly specified in a
- call.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setErrors(const intptr_t* value) – set contents of errors vector,
- length is defined by value context.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setWarnings(const intptr_t* value) – set contents of warnings
- vector, length is defined by value context.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- intptr_t* getErrors() - get errors vector.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- intptr_t* getWarnings() - get warnings vector.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IStatus*
- clone() - create clone of current interface.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Constants
- defined by Status interface:</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="returned by getState"></a><font size="4" style="font-size: 14pt">Flags
- set in the value, returned by getState() method:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">STATE_WARNINGS</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">STATE_ERRORS</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Completion codes"></a><font size="4" style="font-size: 14pt">Completion
- codes:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">RESULT_ERROR</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">RESULT_OK</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">RESULT_NO_DATA</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">RESULT_SEGMENT</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Timer"></a><font size="4" style="font-size: 14pt">Timer
- interface – user timer. Callback interface which should be
- implemented by user to use firebird timer.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- handler() - method is called when timer rings (or when server is
- shutting down).</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="TimerControl"></a><font size="4" style="font-size: 14pt">TimerControl
- interface – very simple and not too precise implementation of
- timer. Arrived here because existing timers are very much OS
- dependent and may be used in programs that require to be portable and
- do not need really high precision timer. Particularly execution of
- given timer may be delayed if another one has not completed at the
- moment when given timer should alarm.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- start(StatusType* status, ITimer* timer, ISC_UINT64 microSeconds) –
- start <a href="#Timer">ITimer</a> to alarm after given delay (in
- microseconds, 10</font><sup><font size="4" style="font-size: 14pt">-6</font></sup>
- <font size="4" style="font-size: 14pt">seconds). Timer will be waked
- up only once after this call.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- stop(StatusType* status, ITimer* timer) – stop <a href="#Timer">ITimer</a>.
- It's not an error to stop not started timer thus avoiding problems
- with races between stop() and timer alarm.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Transaction"></a><font size="4" style="font-size: 14pt">Transaction
- interface – replaces isc_tr_handle.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- getInfo(StatusType* status, unsigned itemsLength, const unsigned
- char* items, unsigned bufferLength, unsigned char* buffer) –
- replaces isc_transaction_info().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- prepare(StatusType* status, unsigned msgLength, const unsigned char*
- message) – replaces isc_prepare_transaction2(), with zero
- msgLength behaves like isc_prepare_transaction() automatically
- generating appropriate message.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- commit(StatusType* status) – replaces isc_commit_transaction().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- commitRetaining(StatusType* status) – replaces
- isc_commit_retaining().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- rollback(StatusType* status) – replaces
- isc_rollback_transaction().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- rollbackRetaining(StatusType* status) – replaces
- isc_rollback_retaining().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- disconnect(StatusType* status) – replaces
- fb_disconnect_transaction().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ITransaction*
- join(StatusType* status, ITransaction* transaction) – joins
- current transaction and passed as parameter transaction into single
- distributed transaction (using <a href="#Dtc">Dtc</a>). On success
- both current transaction and passed as parameter transaction are
- released and should not be used any more.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ITransaction*
- validate(StatusType* status, IAttachment* attachment) – this
- method is used to support distributed transactions coordinator.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ITransaction*
- enterDtc(StatusType* status) – this method is used to support
- distributed transactions coordinator.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="VersionCallback"></a><font size="4" style="font-size: 14pt">VersionCallback
- interface – callback for <a href="#Util">Util</a>::getFbVersion().</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- callback(StatusType* status, const char* text) – called by
- firebird engine for each line in multiline version report. Makes it
- possible to print that lines one by one, place them into message box
- in any GUI, etc.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Util"></a><font size="4" style="font-size: 14pt">Util
- interface – various helper methods required here or there.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- getFbVersion(StatusType* status, IAttachment* att, IVersionCallback*
- callback) – produce long and beautiful report about firebird
- version used. It may be seen in ISQL when invoked with -Z switch.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- loadBlob(StatusType* status, ISC_QUAD* blobId, IAttachment* att,
- ITransaction* tra, const char* file, FB_BOOLEAN txt) – load blob
- from file.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- dumpBlob(StatusType* status, ISC_QUAD* blobId, IAttachment* att,
- ITransaction* tra, const char* file, FB_BOOLEAN txt) – save blob
- to file.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- getPerfCounters(StatusType* status, IAttachment* att, const char*
- countersSet, ISC_INT64* counters) – get statistics for given
- attachment.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IAttachment*
- executeCreateDatabase(StatusType* status, unsigned stmtLength, const
- char* creatDBstatement, unsigned dialect, FB_BOOLEAN*
- stmtIsCreateDb) – execute “CREATE DATABASE ...” statement –
- ISC trick with NULL statement handle does not work with interfaces.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- decodeDate(ISC_DATE date, unsigned* year, unsigned* month, unsigned*
- day) – replaces isc_decode_sql_date().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- decodeTime(ISC_TIME time, unsigned* hours, unsigned* minutes,
- unsigned* seconds, unsigned* fractions) – replaces
- isc_decode_sql_time().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ISC_DATE
- encodeDate(unsigned year, unsigned month, unsigned day) – replaces
- isc_encode_sql_date().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ISC_TIME
- encodeTime(unsigned hours, unsigned minutes, unsigned seconds,
- unsigned fractions) – replaces isc_encode_sql_time().</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- formatStatus(char* buffer, unsigned bufferSize, IStatus* status) –
- replaces fb_interpret(). Size of buffer, passed into this method,
- should not be less than 50 bytes.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getClientVersion() – returns integer, containing major version in
- byte 0 and minor version in byte 1.</font></p>
- <li><p style="margin-bottom: 0cm"><font color="#000000"><font size="4" style="font-size: 14pt">IXpbBuilder*
- getXpbBuilder(StatusType* status, unsigned kind, const unsigned
- char* buf, unsigned len) – returns <a href="#XpbBuilder">XpbBuilder</a>
- interface. Valid <a href="#Valid builder types">kinds</a> are
- enumerated in <a href="#XpbBuilder">XpbBuilder</a>.</font></font></p>
- <li><p style="margin-bottom: 0cm"><font color="#000000"><font size="4" style="font-size: 14pt">unsigned
- setOffsets(StatusType* status, IMessageMetadata* metadata,
- IOffsetsCallback* callback) – sets valid offsets in
- <a href="#MessageMetadata">MessageMetadata</a>. Performs calls to
- callback in <a href="#OffsetsCallback">OffsetsCallback</a> for each
- field/parameter.</font></font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IDecFloat16*
- getDecFloat16(StatusType* status) – access <a href="#DecFloat16">DecFloat16</a>
- interface.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IDecFloat34*
- getDecFloat34(StatusType* status) – access <a href="#DecFloat34">DecFloat34</a>
- interface.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- decodeTimeTz(StatusType* status, const ISC_TIME_TZ* timeTz,
- unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned*</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">fractions,
- unsigned timeZoneBufferLength, char* timeZoneBuffer) – decode time
- taking time zone into an account.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- decodeTimeStampTz(StatusType* status, const ISC_TIMESTAMP_TZ*
- timeStampTz, unsigned* year, unsigned* month, unsigned* day,
- unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned*
- fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer) -
- decode timestamp taking time zone into an account.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- encodeTimeTz(StatusType* status, ISC_TIME_TZ* timeTz, unsigned
- hours, unsigned minutes, unsigned seconds, unsigned fractions, const
- char* timeZone) – encode time taking time zone into an account.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- encodeTimeStampTz(StatusType* status, ISC_TIMESTAMP_TZ* timeStampTz,
- unsigned year, unsigned month, unsigned day, unsigned hours,
- unsigned minutes, unsigned seconds, unsigned fractions, const char*
- timeZone) – encode timestamp taking time zone into an account.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IInt128*
- getInt128(Status status) – access <a href="#Int128">Int128</a>
- interface.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- decodeTimeTzEx(Status status, const ISC_TIME_TZ_EX* timeTz, uint*
- hours, uint* minutes, uint* seconds, uint* fractions, uint
- timeZoneBufferLength, string timeZoneBuffer) – decode time taking
- extended time zone into an account.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- decodeTimeStampTzEx(Status status, const ISC_TIMESTAMP_TZ_EX*
- timeStampTz, uint* year, uint* month, uint* day, uint* hours, uint*
- minutes, uint* seconds, uint* fractions, uint timeZoneBufferLength,
- string timeZoneBuffer) – decode timestamp taking extended time
- zone into an account.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="XpbBuilder"></a><font size="4" style="font-size: 14pt">XpbBuilder
- methods:</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- clear(StatusType* status) – reset builder to empty state.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- removeCurrent(StatusType* status) – removes current clumplet.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- insertInt(StatusType* status, unsigned char tag, int value) –
- inserts a clumplet with value representing integer in network
- format.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- insertBigInt(StatusType* status, unsigned char tag, ISC_INT64 value)
- – inserts a clumplet with value representing integer in network
- format.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- insertBytes(StatusType* status, unsigned char tag, const void*
- bytes, unsigned length) - inserts a clumplet with value containing
- passed bytes.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- insertTag(StatusType* status, unsigned char tag) – inserts a
- clumplet without a value.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN
- isEof(StatusType* status) – checks that there is no current
- clumplet.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- moveNext(StatusType* status) – moves to next clumplet.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- rewind(StatusType* status) – moves to first clumplet.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN
- findFirst(StatusType* status, unsigned char tag) – finds first
- clumplet with given tag.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN
- findNext(StatusType* status) – finds next clumplet with given tag.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- char getTag(StatusType* status) – returns tag for current
- clumplet.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getLength(StatusType* status) – returns length of current clumplet
- value.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
- getInt(StatusType* status) – returns value of current clumplet as
- integer.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ISC_INT64
- getBigInt(StatusType* status) – returns value of current clumplet
- as 64-bit integer.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* getString(StatusType* status) – returns value of current
- clumplet as pointer to zero-terminated string (pointer is valid till
- next call to this method).</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- unsigned char* getBytes(StatusType* status) – returns value of
- current clumplet as pointer to unsigned char.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getBufferLength(StatusType* status) – returns length of parameters
- block.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- unsigned char* getBuffer(StatusType* status) – returns pointer to
- parameters block.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Constants
- defined by XpbBuilder interface:</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Valid builder types"></a><font size="4" style="font-size: 14pt">Valid
- builder types:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">BATCH
- (IBatch parameters block)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">BPB
- (BLOB parameters block)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DPB
- (database attachment parameters block)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">SPB_ATTACH
- (service attachment parameters block)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">SPB_START
- (start service parameters)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">SPB_SEND
- (send items in <a href="#Service">IService</a>::query())</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">SPB_RECEIVE
- (receive items in <a href="#Service">IService</a>::query())</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">SPB_RESPONSE
- (response from <a href="#Service">IService</a>::query())</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TPB
- (transaction parameters block)</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <h1><font size="4" style="font-size: 14pt">Plugin, encrypting data
- transferred over the wire.</font></h1>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Algorithms
- performing encryption of data for different purposes are well known
- for many years. The only “little” typical problem remaining is
- where to get the top secret key to be used by that algorithm. Luckily
- for network traffic encryption there is one good solution – unique
- encryption key should be generated by authentication plugin. At least
- default SRP plugin can produce such a key. And that key is resistant
- to attacks, including man-in-the-middle. Therefore was chosen a
- method of providing keys for wire crypt plugin: get it from
- authentication plugin. (In case when used authentication plugin can
- not provide a key a pseudo-plugin may be added in AuthClient and
- AuthServer lists to produce keys, something like two asymmetric
- private/public pairs.) </font>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">CryptKey
- interface is used to store a key provided by authentication plugin
- and pass it to wire crypt plugin. This interface should be used as
- follows – when server or client authentication plugin is ready to
- provide a key it asks <a href="#ServerBlock">ServerBlock</a> or
- <a href="#ClientBlock">ClientBlock</a> to produce new CryptKey
- interface and stores a key in it. Appropriate for <a href="#WireCryptPlugin">WireCryptPlugin</a>
- type of key will be selected by firebird and passed to that
- interface.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setSymmetric(StatusType* status, const char* type, unsigned
- keyLength, const void* key) – make it store symmetric key of given
- type.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setAsymmetric(StatusType* status, const char* type, unsigned
- encryptKeyLength, const void* encryptKey, unsigned decryptKeyLength,
- const void* decryptKey) – make it store pair of asymmetric keys of
- given type.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- void* getEncryptKey(unsigned* length) – get a key for encryption.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- void* getDecryptKey(unsigned* length) – get a key for decryption
- (in case of symmetric key produces same result as getEncryptKey()).</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="WireCryptPlugin"></a><font size="4" style="font-size: 14pt">WireCryptPlugin
- interface is main interface of network crypt plugin. Like any other
- such interface it should be implemented by author of the plugin.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* getKnownTypes(StatusType* status) – returns
- whitespace/tab/comma separated list of acceptable keys.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setKey(StatusType* status, ICryptKey* key) – plugin should use a
- key passed to it by this call.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- encrypt(StatusType* status, unsigned length, const void* from, void*
- to) – encrypts a packet to be sent over the wire.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- decrypt(StatusType* status, unsigned length, const void* from, void*
- to) – decrypts a packet received from network.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <h1><font size="4" style="font-size: 14pt">Server side of
- authentication plugin.</font></h1>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Authentication
- plugin contains two required parts – client and server and may also
- contain related third part - user manager. During authentication
- process firebird client invokes client plugin and sends generated by
- it data to server, next server invokes server plugin and sends
- generated by it data to client. This process repeats as long as both
- plugins return AUTH_MORE_DATA code. AUTH_SUCCESS returned at server
- side means successful authentication, AUTH_FAILED at any side –
- immediate abort of iterative process and failure reported to client,
- AUTH_CONTINUE means that next plugin from the list of configured
- authentication plugins should be tried.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">There
- is no dedicated sample of authentication plugins but in firebird
- sources in directory src/auth one can find AuthDbg plugin using which
- one can learn on trivial example (no complex calculations like in Srp
- and no calls to crazy WinAPI functions like in AuthSspi) how client
- and server sides perform authentication handshake. </font>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Auth
- interface does not contain methods, only some constants defining
- codes return from authenticate() method of <a href="#Client">Client</a>
- and <a href="#Server">Server</a>.</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">AUTH_FAILED</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">AUTH_SUCCESS</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">AUTH_MORE_DATA</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">AUTH_CONTINUE</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Writer"></a><font size="4" style="font-size: 14pt">Writer
- interface – writes authentication parameters block.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- reset() - clear target block.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- add(StatusType* status, const char* name) – add login name.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setType(StatusType* status, const char* value) – set type of added
- login (user, group, etc).</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setDb(StatusType* status, const char* value) – set security
- database in which authentication was done.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="ServerBlock"></a><font size="4" style="font-size: 14pt">ServerBlock
- interface is used by server side of authentication plugin to exchange
- data with client.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* getLogin() - get login name passed from client.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- unsigned char* getData(unsigned* length) – get authentication data
- passed from client.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- putData(StatusType* status, unsigned length, const void* data) –
- pass authentication data to client.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICryptKey*
- newKey(StatusType* status) – create new wire crypt key and add it
- to the list of available for wire crypt plugins.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Server"></a><font size="4" style="font-size: 14pt">Server
- interface is main interface of server side of authentication plugin. </font>
- </p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
- authenticate(StatusType* status, IServerBlock* sBlock, IWriter*
- writerInterface) – perform single authentication step. Data
- exchange with client is performed using sBlock interface. When some
- authentication item is produced it should be added to authentication
- block using writerInterface. Possible return values are defined in
- <a href="#Auth">Auth</a> interface.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <h1><font size="4" style="font-size: 14pt">Client side of
- authentication plugin.</font></h1>
- <p style="margin-bottom: 0cm"><a name="ClientBlock"></a><font size="4" style="font-size: 14pt">ClientBlock
- interface is used by client side of authentication plugin to exchange
- data with server.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* getLogin() - get login name if it is present in DPB.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* getPassword() - get password if it is present in DPB.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- unsigned char* getData(unsigned* length) – get authentication data
- passed from server.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- putData(StatusType* status, unsigned length, const void* data) –
- pass authentication data to server.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICryptKey*
- newKey(StatusType* status) - create new wire crypt key and add it to
- the list of available for wire crypt plugins.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Client"></a><font size="4" style="font-size: 14pt">Client
- interface is main interface of client side of authentication plugin.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
- authenticate(StatusType* status, IClientBlock* cBlock)1. – perform
- single authentication step. Data exchange with server is performed
- using cBlock interface. Possible return values are defined in Auth
- interface. AUTH_SUCCESS is treated by client side as AUTH_MORE_DATA
- (i.e. client sends generated data to server and waits for an answer
- from it).</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <h1><font size="4" style="font-size: 14pt">User management plugin.</font></h1>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">This
- plugin is actively related with server side of authentication – it
- prepares users' list for authentication plugin. Not each
- authentication plugin requires user manager – some may access list
- of users created using non-firebird software (AuthSspi for example).
- Record describing user consists of a number of fields and operation
- which should be performed like add user, modify user, list user(s),
- etc. Plugin must interpret commands received in <a href="#User">User</a>
- interface.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="UserField"></a><font size="4" style="font-size: 14pt">UserField
- interface is not used as standalone interface, it's base for
- CharUserField and IntUserField. </font>
- </p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
- entered() - returns non-zero if a value for a field was entered
- (assigned).</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
- specified() - return non-zero if NULL value was assigned to the
- field.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setEntered(StatusType* status, int newValue) – sets entered flag
- to 0/non-zero value for a field. There is no method to assign NULL
- for a field cause it's never needed. NULLs if used are assigned by
- the code implementing interfaces and therefore having full access to
- internals of them.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="CharUserField"></a><font size="4" style="font-size: 14pt">CharUserField
- interface:</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* get() - get field's value as C-string (\0 terminated).</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- set(StatusType* status, const char* newValue) – assigns value to
- the field. Sets entered flag to true.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="IntUserField"></a><font size="4" style="font-size: 14pt">IntUserField
- interface:</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
- get() - get field's value.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- set(StatusType* status, int newValue) – assigns value to the
- field. Sets entered flag to true.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="User"></a><font size="4" style="font-size: 14pt">User
- interface is a list of methods accessing fields included into record
- about the user. </font>
- </p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- operation() - code of operation (see <a href="#Constants defined by User interface">list</a>
- below).</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICharUserField*
- userName() - login name.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICharUserField*
- password() - password. Always empty when listing users.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICharUserField*
- firstName() - this and 2 next are components of full user name.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICharUserField*
- lastName()</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICharUserField*
- middleName()</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICharUserField*
- comment() - comment (from SQL operator COMMENT ON USER IS …).</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICharUserField*
- attributes() - tags in a form tag1=val1, tag2=val2, …, tagN=valN.
- Val may be empty – than means that tag will be deleted.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IIntUserField*
- active() - changes ACTIVE/INACTIVE setting for user.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IIntUserField*
- admin() - sets/drops admin rights for the user.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- clear(StatusType* status) – sets all fields to not entered and not
- specified.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Constants defined by User interface"></a>
- <font size="4" style="font-size: 14pt">Constants defined by User
- interface – valid codes of operation.</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">OP_USER_ADD
- – create user</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">OP_USER_MODIFY
- – alter user</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">OP_USER_DELETE
- – drop user</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">OP_USER_DISPLAY
- – show user</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">OP_USER_SET_MAP
- – turn on mapping of windows admins to role rdb$admin</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">OP_USER_DROP_MAP
- – turn off mapping of windows admins to role rdb$admin</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="ListUsers"></a><font size="4" style="font-size: 14pt">ListUsers
- interface is callback used by authentication plugin when list users
- operation is requested. Plugin fills <a href="#User">User</a>
- interface for all items in list of users one by one and for each user
- calls list() method of this interface.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- list(StatusType* status, IUser* user) – callback function.
- Implementation can do what it wants with received data. For example,
- it may put data from user parameter into output stream of listing
- service or place into special tables from SEC$ group.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="LogonInfo"></a><font size="4" style="font-size: 14pt">LogonInfo
- interface contains data passed to user mamngement plugin to attach to
- security database with valid credentials. Pres</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* name() - returns current attachment's login name.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* role() - returns current attachment's active role.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* networkProtocol() - returns current attachment's network
- protocol. Currently not used by plugins.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* remoteAddress() - returns current attachment's remote address.
- Currently not used by plugins.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- unsigned char* authBlock(unsigned* length) – returns current
- attachment's authentication block. When not NULL overrides login
- name.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="Management"></a><font size="4" style="font-size: 14pt">Management
- interface is main interface of user management plugin.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- start(StatusType* status, ILogonInfo* logonInfo) – starts plugin,
- if needed it attaches to security database to manage may be (it's
- plugin-dependent solution use it or not) using credentials from
- logonInfo. </font>
- </p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
- execute(StatusType* status, IUser* user, IListUsers* callback) –
- executes a command provided by operation() method of user parameter.
- If needed callback interface will be used. Parameter callback may
- have NULL value for commands not requiring users' listing.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- commit(StatusType* status) – commits changes done by calls to
- execute() method.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- rollback(StatusType* status) – rollbacks changes done by calls to
- execute() method.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <h1><font size="4" style="font-size: 14pt">Database encryption
- plugin.</font></h1>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">An
- ability to encrypt database was present in firebird since interbase
- times but appropriate places in the code were commented.
- Implementation was suspicious – crypt key was always sent from the
- client in DPB, no attempt was made to hide it from the world and no
- way was suggested to encrypt existing database. FB3 solves most of
- the problems except probably the worst one – how to manage crypt
- keys. We suggest a kind of solution but it requires efforts in
- plugins, i.e. there is no beautiful way to work with keys like it is
- for wire crypt plugins.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Before
- starting with own db crypt plugin one should take into an account the
- following. We see two main usages of database encryption – first,
- it may be needed to avoid data loss if database server is physically
- stolen, and second, it may be used to protect data in database which
- is sailed together with special application accessing that data.
- Requirements for this usages are quite different. In first case we
- may trust database server that it is not modified to steal keys
- passed to security plugin – i.e. we expect that key will not be
- sent to inappropriate server. In second case server may be modified
- in some way to steal keys (if they are passed from application to
- plugin via server code) or even data (as the last resort to dump
- blocks from the cache where they are in non-encrypted form).
- Therefore your plugin should make sure that it's running with not
- modified firebird binaries and your application before sending a key
- to plugin should make sure it's really required plugin, may be asking
- a kind of digital signature from it. Making sure that network line is
- encrypted (parsing output of <a href="#Util">Util</a>::getFbVersion())
- or using some own encryption of a key is also very good idea in case
- when network access to the server is used. All this job should be
- done in plugin (and application working with it) i.e. database block
- encryption algorithm by itself may happen to be easiest part of db
- crypt plugin, specially when some standard library is used for it.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="CryptKeyCallback"></a><font size="4" style="font-size: 14pt">CryptKeyCallback
- interface should be provided by a side sending crypt key to db crypt
- plugin or key holder plugin.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- callback(unsigned dataLength, const void* data, unsigned
- bufferLength, void* buffer) – when performing callback information
- is passed in both directions. The source of a key receives
- dataLength bytes of data and may send up to bufferLength bytes into
- buffer returning actual number of bytes placed into buffer.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">
- void dispose() - invoked when interface is not needed any more. Helps
- to avoid memory leaks in statefull inrefaces.
- </font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">
- unsigned afterAttach(StatusType* status, const char* dbName, const IStatus* attStatus) -
- invoked after attach on client system. NULL in attStatus means attach was successful
- but afterAttach() is anyway invoked in order to let plugin perform required cleanup.
- The following values may be returned by this function:
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">NO_RETRY -
- do not repeat attempts to attach to database.</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DO_RETRY -
- retry attach (ignored when function was called without attStatus).</font></p>
- </font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="DbCryptInfo"></a><font size="4" style="font-size: 14pt">DbCryptInfo
- interface is passed to DbCryptPlugin by engine. Plugin may save this
- interface and use when needed to obtain additional informatio about
- database.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
- char* getDatabaseFullPath(StatusType* status) – returns full
- (including path) name of primary database file.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="DbCryptPlugin"></a><font size="4" style="font-size: 14pt">DbCryptPlugin
- interface is main interface of database crypt plugin.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setKey(StatusType* status, unsigned length, IKeyHolderPlugin**
- sources, const char* keyName) – is used to provide to db crypt
- plugin information about encryption key. Firebird never passes keys
- for this type of plugin directly. Instead array of <a href="#KeyHolderPlugin">KeyHolderPlugins</a>
- of given length is passed to crypt plugin which must get from one of
- it <a href="#CryptKeyCallback">CryptKeyCallback</a> interface and
- get a key using it. Parameter keyName is a name of a key like it was
- entered in “ALTER DATABASE ENCRYPT …” operator.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- encrypt(StatusType* status, unsigned length, const void* from, void*
- to) – encrypts data before writing block to database file.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- decrypt(StatusType* status, unsigned length, const void* from, void*
- to) – decrypts data after reading block from database file.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- setInfo(StatusType* status, IDbCryptInfo* info) – in this method
- crypt plugin typically saves informational interface for future use.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <h1><font size="4" style="font-size: 14pt">Key holder for database
- encryption plugin.</font></h1>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">This
- type of plugin is needed to delineate functionality – db crypt
- plugin is dealing with actual encryption, key holder solves questions
- related with providing it a key in secure way. Plugin may be received
- from application or loaded in some other way (up to using flash
- device inserted into server at firebird startup time).</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="KeyHolderPlugin"></a><font size="4" style="font-size: 14pt">KeyHolderPlugin
- interface is main interface of database crypt key holder plugin.</font></p>
- <ol>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
- keyCallback(StatusType* status, ICryptKeyCallback* callback) – is
- used to pass attachment's <a href="#CryptKeyCallback">CryptKeyCallback</a>
- interface (if provided by user with <a href="#Provider">Provider</a>::setDbCryptCallback()
- call). This call is always performed at database attach moment, and
- some holders may reject attachment if satisfactory key was not
- provided. Return value of 0 means that key holder can not provide a
- key to crypt plugin, non-zero – can.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICryptKeyCallback*
- keyHandle(StatusType* status, const char* keyName) – is intended
- to be called by <a href="#DbCryptPlugin">DbCryptPlugin</a> directly
- to obtain callback interface for named key from key holder. This
- makes it possible for open source firebird code to never touch
- actual keys avoiding ability to steal a key changing firebird code.
- After getting <a href="#CryptKeyCallback">CryptKeyCallback</a>
- interface crypt plugin starts data exchange using it. Key holder can
- (for example) check digital signature of crypt plugin before sending
- a key to it in order to avoid use of modified crypt plugin able to
- steal secret key.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN
- useOnlyOwnKeys(StatusType* status) – informs firebird engine
- whether a key, provided by key holder, can be used in other
- attachments. Makes sense only for SuperServer – only it can share
- database crypt keys between attachments. Returning FB_TRUE from this
- method enforces firebird to make sure that this particular key
- holder (and therefore in turn attachment related to it) provides
- correct crypt key for any other attachment to this database.</font></p>
- <li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICryptKeyCallback*
- chainHandle(StatusType* status) – support of a chain of key
- holders. In some cases key has to pass through more than single key
- holder before it reaches db crypt plugin. This is needed (for
- example) to support execute statement in encrypted database. This is
- just a sample – chains are also used in some other cases. Callback
- interface, returned by this method, may differ from one returned by
- keyHandle() function (see above). Typically is should be able to
- duplicate one-to-one keys, received by KeyHolderPlugin when
- keyCallback() function is invoked.</font></p>
- </ol>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <h1><font size="4" style="font-size: 14pt">Non-interface objects used
- by API (C++ specific header Message.h).</font></h1>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Following
- 3 classes are used to represent date, time and timestamp (datetime)
- when using FB_MESSAGE macro. Members of data structure, representing
- static message, correspondint to fields of types FB_DATE / FB_TIME /
- FB_TIMESTAMP will have a type of one of this classes. Knowing methods
- / members (which are enough self-descriptive to avoid describing them
- here) of this classes is needed to access date and time fields in
- static messages.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="FbDate"></a><font size="4" style="font-size: 14pt">class
- FbDate methods:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- decode(IUtil* util, unsigned* year, unsigned* month, unsigned* day)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getYear(IUtil* util) </font>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getMonth(IUtil* util)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getDay(IUtil* util)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- encode(IUtil* util, unsigned year, unsigned month, unsigned day)</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><a name="FbTime"></a><font size="4" style="font-size: 14pt">class
- FbTime methods:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- decode(IUtil* util, unsigned* hours, unsigned* minutes, unsigned*
- seconds, unsigned* fractions)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getHours(IUtil* util)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getMinutes(IUtil* util)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getSeconds(IUtil* util)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
- getFractions(IUtil* util)</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- encode(IUtil* util, unsigned hours, unsigned minutes, unsigned
- seconds, unsigned fractions)</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">class
- FbTimestamp members:</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FbDate
- date;</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FbTime
- time;</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Following
- two templates are used in static messages to represent CHAR(N) and
- VARCHAR(N) fields. </font>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">template
- <unsigned N></font></p>
- <p style="margin-bottom: 0cm"><a name="FbChar"></a><font size="4" style="font-size: 14pt">struct
- FbChar</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">{</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">char
- str[N];</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">};</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">template
- <unsigned N></font></p>
- <p style="margin-bottom: 0cm"><a name="FbVarChar"></a><font size="4" style="font-size: 14pt">struct
- FbVarChar</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">{</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ISC_USHORT
- length;</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">char
- str[N];</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
- set(const char* s);</font></p>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">};</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- <hr/>
- <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">This
- document is currently missing 2 types of plugins – ExternalEngine
- and Trace. Information about them will be made available in next
- release of it.</font></p>
- <p style="margin-bottom: 0cm"><br/>
- </p>
- </body>
- </html>
|