| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820 |
- <!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) throw()</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>FbSampleAtomic
- 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 if <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>
- </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>
|