home *** CD-ROM | disk | FTP | other *** search
/ Delphi Anthology / aDELPHI.iso / Runimage / Delphi50 / Source / Vcl / dsintf.pas < prev    next >
Pascal/Delphi Source File  |  1999-08-11  |  46KB  |  1,180 lines

  1.  
  2. {*******************************************************}
  3. {                                                       }
  4. {       Borland Delphi Visual Component Library         }
  5. {       DBClient Interface                              }
  6. {                                                       }
  7. {       Copyright (c) 1997,99 Inprise Corporation       }
  8. {                                                       }
  9. {*******************************************************}
  10.  
  11. unit DSIntf;
  12.  
  13. {$MINENUMSIZE 4}
  14. {$T-,H+,X+}
  15.  
  16. interface
  17.  
  18. uses Windows, ActiveX, DB, DBCommon;
  19.  
  20. const
  21.  
  22. { Record attributes }
  23.  
  24.   dsRecUnmodified    = $0000;       { Unmodified record }
  25.   dsRecOrg           = $0001;       { Original record (was changed) }
  26.   dsRecDeleted       = $0002;       { Record was deleted }
  27.   dsRecNew           = $0004;       { Record was inserted }
  28.   dsRecModified      = $0008;       { Record was changed }
  29.   dsUnused           = $0020;       { Record not used anymore (hole) }
  30.   dsDetUpd           = $0040;       { Detail modification  Ins/Del/Mod. }
  31.                                     { Can be combined with other status. }
  32.   dsIsNotVisible     = dsRecDeleted or dsRecOrg or dsUnused;
  33.   dsIsVisible        = not (dsRecDeleted or dsRecOrg or dsUnused);
  34.  
  35. { Field attributes }
  36.  
  37.   fldAttrHIDDEN      = $0001;       { Field is hidden }
  38.   fldAttrREADONLY    = $0002;       { Field is readonly }
  39.   fldAttrREQUIRED    = $0004;       { Field value required }
  40.   fldAttrLINK        = $0008;       { Linking field }
  41.  
  42.   BLANK_NULL         = 1;           { 'real' NULL }
  43.   BLANK_NOTCHANGED   = 2;           { Not changed , compared to original value }
  44.  
  45.   MAXKEYFIELDS       = 16;
  46.  
  47. { Master Detail Semantics DSBase.SetProp(dspropMD_SEMANTICS, Value) }
  48.  
  49.   mdCASCADEDEL       = $0004;
  50.   mdCASCADEMOD       = $0008;  { Allow master link field to be changed (cascade change to details) }
  51.   mdALLOWLINKCHANGE  = $0010;  { Allow detail linkfields to be changed (fly-away) }
  52.  
  53. type
  54.   DBResult          = Word;         { Function result }
  55.  
  56.   DBSearchCond = (                     { Search condition for keys }
  57.     keySEARCHEQ,                          { = }
  58.     keySEARCHGT,                          { > }
  59.     keySEARCHGEQ                          { >= }
  60.   );
  61.  
  62.   MIDASNAME            = packed array [0..31] of Char; { holds a name }
  63.   MIDASPATH            = packed array [0..260] of Char; { holds a DOS path }
  64.  
  65. { Native Types }
  66.  
  67.   TDataPacket = PSafeArray;
  68.  
  69.   pDSAttr = ^DSAttr;
  70.   DSAttr = type Byte;
  71.  
  72.   phDSFilter = ^hDSFilter;
  73.   hDSFilter = type Pointer;
  74.  
  75.   GROUPSTATE = (
  76.     grSTATEMIDDLE,                  { Record is neither the first or the last in the group }
  77.     grSTATEFIRST,                   { Record is the first in the group }
  78.     grSTATELAST,                    { Record is the last in the group }
  79.     grSTATEFIRSTLAST
  80.   );
  81.  
  82.   phDSAggregate = ^hDSAggregate;
  83.   hDSAggregate = type Integer;
  84.  
  85.   AGGSTATE = (
  86.     aggSTATEUNDEF,                  { State is undefined. Needs recalc. }
  87.     aggSTATEOK,
  88.     aggSTATEBLANK,                  { This is a blank value }
  89.     aggSTATEERROR                   { An error occurred previously }
  90.   );
  91.  
  92.   AGGVALUE = packed record
  93.     iCnt      : Integer;            { Count of records in each }
  94.     eAggState : AGGSTATE;           { State of value }
  95.     Value     : record end;         { First byte of value }
  96.   end;
  97.  
  98.   pDSBOOKMRK = ^DSBOOKMRK;
  99.   DSBOOKMRK = packed record
  100.     iPos   : Integer;               { Position in given order }
  101.     iState : Integer;               { State of cursor }
  102.     iRecNo : Integer;               { Record number }
  103.     iSeqNo : Integer;               { Version number of order }
  104.     iOrderID : Integer;             { Defines Order }
  105.   end;
  106.  
  107.   pSAVEPOINT = ^SAVEPOINT;
  108.   SAVEPOINT = type Integer;
  109.  
  110.   DSKEY = packed array[0..MAXKEYFIELDS-1] of Integer;
  111.   DSKEYBOOL = packed array[0..MAXKEYFIELDS-1] of Bool;
  112.  
  113. { Dataset and Cursor Properties }
  114.  
  115.   DSProp = (
  116.     dspropLOGCHANGES,               { rw BOOL,   Log changes for undo/delta }
  117.     dspropREADONLY,                 { rw BOOL,   Disable dataset updates }
  118.     dspropNOOFCHANGES,              { r  UINT32, Number of changes }
  119.     dspropCONSTRAINTS_DISABLED,     { rw BOOL,   Disable constraints }
  120.     dspropDSISPARTIAL,              { rw BOOL,   Dataset is parital }
  121.     dspropRECORDSINDS,              { r  UINT32, Records in dataset }
  122.     dspropAUTOINC_DISABLED,         { rw BOOL,   Autoinc disabled }
  123.     dspropISDELTA,                  { r  BOOL,   Dataset is a delta }
  124.     dspropDONTINCLMETADATA,         { rw BOOL,   Exclude metadata in StreamDS }
  125.     dspropINCLBLOBSINDELTA,         { rw UINT32, include blobs with lengths <= than }
  126.                                     { this value in delta for 'original' record }
  127.     dspropGETSAVEPOINT,             { r  SAVEPOINT, return savepoint for current update state. }
  128.     dspropCOMPRESSARRAYS,           { rw BOOL(TRUE), if true expands fielddescriptors for arrays }
  129.     dspropMD_SEMANTICS,             { rw UINT32(0), Master/detail semantics }
  130.     dspropFIELD_FULLNAME,           { r  in: UINT32 (FieldID), out: zstring (full name) }
  131.     dspropFIELDID_FORNAME,          { r  in: zstring(full name), out:UINT32 (fieldid) }
  132.     dspropFIELDID_FORPARENT,        { r  in: UINT32 (FieldID), out: UINT32 (FieldID) }
  133.     dspropCHANGEINDEX_VIEW,         { rw DSAttr (UINT32) (update attributes), any combination, 0->show all }
  134.     dspropGETUNIQUEINDEX,           { r  DSIDX, internal use, returns first unique index, if any }
  135.     dspropREMOTE_UPDATEMODE,        { rw UINT32, 0: where key, 1: where all, 3: where ch }
  136.     dspropXML_STREAMMODE
  137.   );
  138.  
  139.   CURProp = (
  140.     curpropCONSTRAINT_ERROR_MESSAGE,{ r pCHAR,   Constraint Error Message }
  141.     curpropDSBASE,                  { r pDSBASE, Underlying DSBASE) }
  142.     curpropSETCRACK,                { w Sets crack-value to supplied value (DBERR_NOCURRREC) }
  143.     curpropGETORG_RECBUF            { r returns recordbuffer for original record, error if none }
  144.   );
  145.  
  146.   pDSProps = ^DSProps;
  147.   DSProps = packed record
  148.     szName           : MIDASPATH;      { Name, if any }
  149.     iFields          : Integer;      { Number of columns }
  150.     iRecBufSize      : Integer;      { Size of record buffer }
  151.     iBookMarkSize    : Integer;      { Size of bookmark }
  152.     bReadOnly        : Bool;         { Dataset is not updateable }
  153.     iIndexes         : Integer;      { Number of indexes on dataset }
  154.     iOptParams       : Integer;      { Number of optional parameters }
  155.     bDelta           : Bool;         { This is a delta dataset }
  156.     iLCID            : Integer;      { Language used }
  157.     iUnused          : packed array[0..7] of Integer; { Reserved }
  158.   end;
  159.  
  160. { Field Descriptor }
  161.  
  162.   pDSFLDDesc = ^DSFLDDesc;
  163.   DSFLDDesc = packed record
  164.     szName          : MIDASNAME;      { Field name }
  165.     iFldType        : Integer;      { Field type }
  166.     iFldSubType     : Integer;      { Field subtype (if applicable) }
  167.     iUnits1         : Integer;      { Number of Chars, precision etc }
  168.     iUnits2         : Integer;      { Decimal places etc. }
  169.     iFldLen         : Integer;      { Length in bytes (computed) }
  170.     iFldOffsInRec   : Integer;      { Offset to field  in record buffer }
  171.     iNullOffsInRec  : Integer;      { Offset to null flag (1byte) in record buffer }
  172.     iFieldID        : Word;         { FieldID of this field }
  173.     iFieldIDParent  : Word;         { FieldID of parent, if any (part of ADT or ARRAY) }
  174.     bCalculated     : Bool;         { Field is Calculated }
  175.     iFldAttr        : Integer;      { Field attributes }
  176.     iOptParameters  : Integer;      { Number of optional parameters for field }
  177.   end;
  178.  
  179. {  Index descriptor }
  180.  
  181.   pDSIDXDesc = ^DSIDXDesc;
  182.   DSIDXDesc = packed record
  183.     szName    : MIDASNAME;            { IndexName }
  184.     iFields   : Integer;            { Number of fields in order (0 -> base order) }
  185.     iKeyFields: DSKEY;              { FieldNumbers }
  186.     iKeyLen   : Integer;            { Total length of key (computed) }
  187.     bUnique   : Bool;
  188.     bDescending  : DSKEYBOOL;       { TRUE ->Descending }
  189.     bCaseInsensitive : DSKEYBOOL;
  190.   end;
  191.  
  192. { Callbacks }
  193.  
  194.   pfCHANGECallBack = procedure(     { Change Notification callback }
  195.     iClientData  : Integer          { Client data }
  196.   ); stdcall;
  197.  
  198.   pfDSFilter = function(            { Filter callback }
  199.     iClientData  : Integer;         { Client data }
  200.     pRecBuf      : Pointer            { Record buffer }
  201.   ): Bool; stdcall;
  202.  
  203.   pfDSCalcField = function(         { Calculated field callback }
  204.     iClientData  : Integer;         { Client data }
  205.     pRecBuf      : Pointer          { Current record-buffer }
  206.   ): DBResult; stdcall;
  207.  
  208.   dsCBRType = Integer;              { Return value for reconcile callback }
  209.   pdsCBRType = ^dsCBRType;
  210.  
  211.   pfDSReconcile = function(         { Reconcile callback }
  212.     iClientData   : Integer;        { Client data }
  213.     iRslt         : Integer;        { Result of previous callback }
  214.     iAction       : DSAttr;         { Update request Insert/Modify/Delete }
  215.     iResponse     : dsCBRType;      { Resolver response }
  216.     iErrCode      : Integer;        { Native error-code }
  217.     pErrMessage   : PChar;          { Native errormessage if any }
  218.     pErrContext   : PChar;          { 1-level error context, if any }
  219.     pRecUpd       : Pointer;        { Record that failed update }
  220.     pRecOrg       : Pointer;        { Original record, if any }
  221.     pRecConflict  : Pointer         { Conflicting record, if any }
  222.   ): dsCBRType; stdcall;
  223.  
  224.   pfDSReconcile_MD = function(
  225.     iClientData   : Integer;
  226.     iRslt         : Integer;  { Result of previous callback. If set, the previuos parameters are repeated. }
  227.     iAction       : DSAttr;   { Update request Insert/Modify/Delete }
  228.     iErrResponse  : dsCBRType; { Resolver response }
  229.     iErrCode      : Integer;  { Native error-code, (BDE or ..) }
  230.     pErrMessage   : PChar;    { Native errormessage, if any (otherwise NULL) }
  231.     pErrContext   : PChar;    { 1-level error context, if any (otherwise NULL) }
  232.     pRecUpd       : PByte;    { Record that failed update }
  233.     pRecOrg       : PByte;    { Original record, if any }
  234.     pRecConflict  : PByte;    { Conflicting error, if any }
  235.     iLevels       : Integer;  { Number of levels to error0level }
  236.     piFieldIDs    : PInteger  { Array of fieldIDS to navigate to error-dataset }
  237. ): dsCBRType;
  238.  
  239.   pfFLDComp = function(             { Field compare callback }
  240.     iClientData  : Integer;         { Client callback data }
  241.     pVal1        : Pointer;         { Fieldvalue 1 (NULL if blank) }
  242.     pVal2        : Pointer          { Fieldvalue 2 (NULL if blank) }
  243.   ): Integer;                       { returns -1 if pVal1 < pVal2, }
  244.                                     { 0 if equal, +1 if pVal1 > pVal2 }
  245.  
  246. { Resolver & Reconcile callback return values }
  247.  
  248. const
  249.   dscbrSKIP          = 1;   { Skip this operation (resolver : report error) }
  250.   dscbrABORT         = 2;   { Abort the callback session (reconcile or resolve) }
  251.                             { (resolver : undo all changes). }
  252.   dscbrMERGE         = 3;   { Merge the changes  (resolver : 'simple' merge) }
  253.                             { (reconcile : update original. Keep change). }
  254.   { Resolving only }
  255.   dscbrAPPLY         = 4;   { Overwrite the current record with new values. }
  256.   dscbrIGNORE        = 5;   { Ignore the update request. Don't report error. }
  257.  
  258.   { Reconcile only }
  259.   dscbrCORRECT       = 4;   { Overwrite change with new values. }
  260.   dscbrCANCEL        = 5;   { Cancel change (remove from delta). }
  261.   dscbrREFRESH       = 6;   { Update original record. Cancel change. }
  262.  
  263. { Defines for SetXmlMode/GetXmlMode }
  264.  
  265.   xmlUNTYPED         =  1;  { Forces XML Data }
  266.   xmlXMLDATATYPED    =  2;  { Not used }
  267.   xmlXMLSCHEMA       =  4;  { Get XML Meta Data }
  268.  
  269.   xmlON              = xmlXMLSCHEMA or xmlUNTYPED;
  270.   xmlOFF             =  0;      
  271.  
  272.  
  273. { Packet Creation }
  274.  
  275. type
  276.   TPcktAttrArea = (fldAttrArea, pcktAttrArea);
  277.   TPcktFldStatus = (fldIsChanged, fldIsNull, fldIsUnChanged);
  278.  
  279.   PDSDataPacketFldDesc = ^TDSDataPacketFldDesc;
  280.   TDSDataPacketFldDesc = packed record
  281.     szFieldName: MIDASNAME;           { Column Name }
  282.     iFieldType: Integer;            { Column Type }
  283.     iAttributes: Word;              { Column attributes }
  284.   end;
  285.  
  286. const
  287. {Do not localize }
  288.   szUNIQUE_KEY       = 'UNIQUE_KEY';  { Series of unique keys to enforce on the client }
  289.   szPRIMARY_KEY      = 'PRIMARY_KEY'; { Primary key used in RowRequest and for key information }
  290.   szDEFAULT_ORDER    = 'DEFAULT_ORDER'; { Index used for the default ordering of the dataset }
  291.   szCHANGEINDEX      = 'CHANGEINDEX';
  292.   szCHANGE_LOG       = 'CHANGE_LOG';
  293.   szSERVER_COL       = 'SERVER_COL';
  294.   szCONSTRAINTS      = 'CONSTRAINTS';
  295.   szDATASET_CONTEXT  = 'DATASET_CONTEXT';
  296.   szDATASET_DELTA    = 'DATASET_DELTA';
  297.   szREADONLY         = 'READONLY'; { Specifies the packet is read only }
  298.   szSUBTYPE          = 'SUBTYPE'; { Field Subtype }
  299.   szDECIMALS         = 'DECIMALS'; { Field decimal precision }
  300.   szWIDTH            = 'WIDTH'; { Field width }
  301.   szLCID             = 'LCID'; { Locale ID that the packet comes from }
  302.   szBDEDOMX          = 'BDEDOMAIN_X'; { Server side field constraints }
  303.   szBDERECX          = 'BDERECORD_X'; { Server side record constraints }
  304.   szBDEDEFX          = 'BDEDEFAULT_X'; { Server side default values }
  305.   szAUTOINCVALUE     = 'AUTOINCVALUE';
  306.   szELEMENTS         = 'ELEMENTS';
  307.   szTABLE_NAME       = 'TABLE_NAME'; { Table name used for resolving the packet - deprecated}
  308.   szMD_FIELDLINKS    = 'MD_FIELDLINKS'; { Master detail field relationships }
  309.   szTYPENAME         = 'TYPENAME'; { Field type name.  Used for object fields }
  310.   szUPDATEMODE       = 'UPDATEMODE'; { Update mode }
  311.   szFIELDPROPS       = 'FIELDPROPS'; { Delphi transferable field properties }
  312.   szPROVFLAGS        = 'PROVFLAGS'; { Provider flags }
  313.   szORIGIN           = 'ORIGIN'; { Field origin }
  314.   szMD_SEMANTICS     = 'MD_SEMANTICS'; { Master detail semantic properties }
  315.   szSERVERCALC       = 'SERVER_CALC'; { A server side calculated field }
  316.   szBDEDOMCL         = 'BDEDOMAIN_CL'; { Client side field constraints }
  317.   szBDERECCL         = 'BDERECORD_CL'; { Client side record constraints }
  318.   szBDEDEFCL         = 'BDEDEFAULT_CL'; { Client side default values }
  319.   szDISABLE_INSERTS  = 'DISABLE_INSERTS'; { Disable inserting records }
  320.   szDISABLE_DELETES  = 'DISABLE_DELETES'; { Disable deleting records }
  321.   szDISABLE_EDITS    = 'DISABLE_EDITS'; { Disable editing records }
  322.   szNO_RESET_CALL    = 'NO_RESET_CALL'; { Specifies not to call reset when the client closes the data }
  323.   szMINVALUE         = 'MINVALUE'; { Minimum value for the field }
  324.   szMAXVALUE         = 'MAXVALUE'; { Maximum value for the field }
  325.  
  326.   szstMEMO           = 'Text';
  327.   szstBINARY         = 'Binary';
  328.   szstFMTMEMO        = 'Formatted';
  329.   szstOLEOBJ         = 'Ole';
  330.   szstGRAPHIC        = 'Graphics';
  331.   szstDBSOLEOBJ      = 'dBASEOle';
  332.   szstTYPEDBINARY    = 'TypedBinary';
  333.   szstMONEY          = 'Money';
  334.   szstAUTOINC        = 'Autoinc';
  335.   szstADTNESTEDTABLE = 'ADTNestedTable';
  336.   szstFIXEDCHAR      = 'FixedChar';
  337.   szstREFNESTEDTABLE = 'Reference';
  338.   szstGUID           = 'Guid';
  339.   szstACCOLEOBJ      = 'AccessOle';
  340.   szstHMEMO          = 'HMemo';
  341.   szstHBINARY        = 'HBinary';
  342.  
  343.   fldstReference     = 70;
  344.  
  345.   dsfldUNKNOWN       = 0;           { Unknown }
  346.   dsfldINT           = 1;           { signed integer }
  347.   dsfldUINT          = 2;           { Unsigned integer }
  348.   dsfldBOOL          = 3;           { Boolean }
  349.   dsfldFLOATIEEE     = 4;           { IEEE float }
  350.   dsfldBCD           = 5;           { BCD }
  351.   dsfldDATE          = 6;           { Date     (32 bit) }
  352.   dsfldTIME          = 7;           { Time     (32 bit) }
  353.   dsfldTIMESTAMP     = 8;           { Time-stamp  (64 bit) }
  354.   dsfldZSTRING       = 9;           { Multi-byte string }
  355.   dsfldUNICODE       = 10;          { unicode string }
  356.   dsfldBYTES         = 11;          { bytes }
  357.   dsfldADT           = 12;          { ADT (Abstract Data Type) }
  358.   dsfldARRAY         = 13;          { Array type (not attribute) }
  359.   dsfldEMBEDDEDTBL   = 14;          { Embedded (nested table type) }
  360.   dsfldREF           = 15;          { Reference }
  361.  
  362.   dsSizeBitsLen      = 16;          { no. bits indicating fld size }
  363.   dsSizeBitsMask     = $0000FFFF;   { mask to retrieve fld size }
  364.   dsTypeBitsMask     = $003F0000;   { mask to retrieve Type info }
  365.   dsVaryingFldType   = $00400000;   { Varying attribute type. }
  366.   dsArrayFldType     = $00800000;   { Array attribute type. }
  367.  
  368.   dsPseudoFldType    = $01000000;   {Composite. Bits 1..15 gives number of elements }
  369.   dsCompArrayFldType = $02000000;   { Compressed array }
  370.   dsEmbeddedFldType  = $04000000;   { Embedded table }
  371.   dsIncInDelta       = $80000000;   { For optional parameters only:include parameter in delta }
  372.  
  373.   dskeyCASEINSENSITIVE  = $4000;
  374.   dskeyDESCENDING       = $8000;
  375.  
  376.   dsDELAYEDBIT       = $80000000;   { Length/number is not present }
  377.  
  378.   PACKETVERSION_1     = 1;
  379.   PACKETVERSION_2     = 2;
  380.  
  381.   dsCASCADEDELETES   = 1;
  382.   dsCASCADEUPDATES   = 2;
  383.  
  384. { Field Types (Logical) - Originally from BDE.PAS }
  385.  
  386.   fldUNKNOWN         = 0;
  387.   fldZSTRING         = 1;               { Null terminated string }
  388.   fldDATE            = 2;               { Date     (32 bit) }
  389.   fldBLOB            = 3;               { Blob }
  390.   fldBOOL            = 4;               { Boolean  (16 bit) }
  391.   fldINT16           = 5;               { 16 bit signed number }
  392.   fldINT32           = 6;               { 32 bit signed number }
  393.   fldFLOAT           = 7;               { 64 bit floating point }
  394.   fldBCD             = 8;               { BCD }
  395.   fldBYTES           = 9;               { Fixed number of bytes }
  396.   fldTIME            = 10;              { Time        (32 bit) }
  397.   fldTIMESTAMP       = 11;              { Time-stamp  (64 bit) }
  398.   fldUINT16          = 12;              { Unsigned 16 bit integer }
  399.   fldUINT32          = 13;              { Unsigned 32 bit integer }
  400.   fldFLOATIEEE       = 14;              { 80-bit IEEE float }
  401.   fldVARBYTES        = 15;              { Length prefixed var bytes }
  402.   fldLOCKINFO        = 16;              { Look for LOCKINFO typedef }
  403.   fldCURSOR          = 17;              { For Oracle Cursor type }
  404.   fldINT64           = 18;              { 64 bit signed number }
  405.   fldUINT64          = 19;              { Unsigned 64 bit integer }
  406.   fldADT             = 20;              { Abstract datatype (structure) }
  407.   fldARRAY           = 21;              { Array field type }
  408.   fldREF             = 22;              { Reference to ADT }
  409.   fldTABLE           = 23;              { Nested table (reference) }
  410.  
  411.   MAXLOGFLDTYPES     = 24;              { Number of logical fieldtypes }
  412.  
  413. { Additional (non-BDE fieldtypes }
  414.   fldUNICODE          = $1007;          { Unicode }
  415.  
  416. { Sub Types (Logical) }
  417.  
  418. { fldFLOAT subtype }
  419.  
  420.   fldstMONEY         = 21;              { Money }
  421.  
  422. { fldBLOB subtypes }
  423.  
  424.   fldstMEMO          = 22;              { Text Memo }
  425.   fldstBINARY        = 23;              { Binary data }
  426.   fldstFMTMEMO       = 24;              { Formatted Text }
  427.   fldstOLEOBJ        = 25;              { OLE object (Paradox) }
  428.   fldstGRAPHIC       = 26;              { Graphics object }
  429.   fldstDBSOLEOBJ     = 27;              { dBASE OLE object }
  430.   fldstTYPEDBINARY   = 28;              { Typed Binary data }
  431.   fldstACCOLEOBJ     = 30;              { Access OLE object }
  432.   fldstHMEMO         = 33;              { CLOB }
  433.   fldstHBINARY       = 34;              { BLOB }
  434.   fldstBFILE         = 36;              { BFILE }
  435.  
  436. { fldZSTRING subtype }
  437.  
  438.   fldstPASSWORD      = 1;               { Password }
  439.   fldstFIXED         = 31;              { CHAR type }
  440.   fldstUNICODE       = 32;              { Unicode }
  441.   fldstGUID          = 38;              { GUID }
  442.  
  443. { fldINT32 subtype }
  444.  
  445.   fldstAUTOINC       = 29;
  446.  
  447. const
  448.   FieldTypeMap: TFieldMap = (
  449.     fldUNKNOWN, fldZSTRING, fldINT16, fldINT32, fldUINT16, fldBOOL,
  450.     fldFLOAT, fldFLOAT, fldBCD, fldDATE, fldTIME, fldTIMESTAMP, fldBYTES,
  451.     fldVARBYTES, fldINT32, fldBLOB, fldBLOB, fldBLOB, fldBLOB, fldBLOB,
  452.     fldBLOB, fldBLOB, fldCURSOR, fldZSTRING, fldZSTRING, fldINT64, fldADT,
  453.     fldArray, fldREF, fldTABLE, fldBLOB, fldBLOB, fldUNKNOWN, fldUNKNOWN,
  454.     fldUNKNOWN, fldZSTRING);
  455.  
  456.   FldSubTypeMap: array[TFieldType] of Word = (
  457.     0, 0, 0, 0, 0, 0, 0, fldstMONEY, 0, 0, 0, 0, 0, 0, fldstAUTOINC,
  458.     fldstBINARY, fldstMEMO, fldstGRAPHIC, fldstFMTMEMO, fldstOLEOBJ,
  459.     fldstDBSOLEOBJ, fldstTYPEDBINARY, 0, fldstFIXED, fldstUNICODE,
  460.     0, 0, 0, 0, 0, fldstHBINARY, fldstHMEMO, 0, 0, 0, 0);
  461.  
  462.   DataTypeMap: array[0..MAXLOGFLDTYPES - 1] of TFieldType = (
  463.     ftUnknown, ftString, ftDate, ftBlob, ftBoolean, ftSmallint,
  464.     ftInteger, ftFloat, ftBCD, ftBytes, ftTime, ftDateTime,
  465.     ftWord, ftInteger, ftUnknown, ftVarBytes, ftUnknown, ftUnknown,
  466.     ftLargeInt, ftLargeInt, ftADT, ftArray, ftReference, ftDataSet);
  467.  
  468.   BlobTypeMap: array[fldstMEMO..fldstBFILE] of TFieldType = (
  469.     ftMemo, ftBlob, ftFmtMemo, ftParadoxOle, ftGraphic, ftDBaseOle,
  470.     ftTypedBinary, ftBlob, ftBlob, ftBlob, ftBlob, ftOraClob,
  471.     ftOraBlob, ftBlob, ftBlob);
  472.  
  473. { Error Codes }
  474.  
  475. const
  476.  
  477.   DBERR_NONE                   = 0;
  478.   DBERR_BOF                    = $2201;
  479.   DBERR_EOF                    = $2202;
  480.   DBERR_NOSUCHINDEX            = $270D;
  481.  
  482.   ERRCAT_ALC  = $40;
  483.   ERRBASE_ALC = $4000;
  484.  
  485.   ERRCODE_DELTAISEMPTY       = 1;   { Delta is empty }
  486.   ERRCODE_NOTHINGTOUNDO      = 2;   { Nothing to undo }
  487.   ERRCODE_NOMETADATA         = 3;   { Datapacket contains no meta data }
  488.   ERRCODE_CANNOTAPPEND       = 4;   { Trying to append data to a non-partial }
  489.   ERRCODE_DATAPACKETMISMATCH = 5;   { Mismatch in datapacket }
  490.   ERRCODE_ABORTED            = 6;   { Operation was aborted }
  491.   ERRCODE_CANCELLED          = 7;   { Operation was cancelled }
  492.   ERRCODE_NEWERVERSIONREQ    = 8;   { Newer version required }
  493.   ERRCODE_BLOBNOTFETCHED     = 9;   { Blob has not been fetched }
  494.   ERRCODE_DETAILSNOTFETCHED  = 10;  { Details has not been fetched }
  495.   ERRCODE_NOMASTERRECORD     = 11;  { no corresponding master record found }
  496.   ERRCODE_LINKFIELDSNOTUNIQUE= 12;  { Linkfields must be unique }
  497.   ERRCODE_FLYAWAY_WRONGORDER = 13;  { Special case: wrong order of updates for fly-away }
  498.   ERRCODE_NOCASCADEDUPDATES  = 14;  { Cascaded updates is not enabled }
  499.  
  500.   DBERR_DELTAISEMPTY        = ERRBASE_ALC + ERRCODE_DELTAISEMPTY;
  501.   DBERR_NOTHINGTOUNDO       = ERRBASE_ALC + ERRCODE_NOTHINGTOUNDO;
  502.   DBERR_NOMETADATA          = ERRBASE_ALC + ERRCODE_NOMETADATA;
  503.   DBERR_CANNOTAPPEND        = ERRBASE_ALC + ERRCODE_CANNOTAPPEND;
  504.   DBERR_DATAPACKETMISMATCH  = ERRBASE_ALC + ERRCODE_DATAPACKETMISMATCH;
  505.   DBERR_ABORTED             = ERRBASE_ALC + ERRCODE_ABORTED;
  506.   DBERR_CANCELLED           = ERRBASE_ALC + ERRCODE_CANCELLED;
  507.   DBERR_NEWERVERSIONREQ     = ERRBASE_ALC + ERRCODE_NEWERVERSIONREQ;
  508.   DBERR_BLOBNOTFETCHED      = ERRBASE_ALC + ERRCODE_BLOBNOTFETCHED;
  509.   DBERR_DETAILSNOTFETCHED   = ERRBASE_ALC + ERRCODE_DETAILSNOTFETCHED;
  510.   DBERR_NOMASTERRECORD      = ERRBASE_ALC + ERRCODE_NOMASTERRECORD;
  511.   DBERR_LINKFIELDSNOTUNIQUE = ERRBASE_ALC + ERRCODE_LINKFIELDSNOTUNIQUE;
  512.   DBERR_FLYAWAY_WRONGORDER  = ERRBASE_ALC + ERRCODE_FLYAWAY_WRONGORDER;
  513.   DBERR_NOCASCADEDUPDATES   = ERRBASE_ALC + ERRCODE_NOCASCADEDUPDATES;
  514.  
  515. { IDSBase }
  516.  
  517. type
  518.  
  519.   IDSBase = interface(IUnknown)
  520.     ['{9E8D2FA2-591C-11D0-BF52-0020AF32BD64}']
  521.  
  522.     function Create(                { Create empty dataset }
  523.         iFields  : DWord;           { Number of fields }
  524.         pFldDes  : pDSFLDDesc;      { Array of field descriptors }
  525.         pszName  : PChar            { Name (optional) }
  526.     ): DBResult; stdcall;
  527.  
  528.     function AddField(              { Add a field to the dataset }
  529.         pFldDes  : pDSFLDDesc       { Field descriptor }
  530.     ): DBResult; stdcall;
  531.  
  532.     function AppendData(            { Appends data packet to dataset. }
  533.         Packet   : PSafeArray;      { Data packet }
  534.         bEof     : Bool             { If True, this is last packet }
  535.     ): DBResult; stdcall;
  536.  
  537.     function GetOptParameter(       { Returns optional parameter (unknown to dataset) }
  538.         iNo      : DWord;           { Number 1..iOptAttr }
  539.         iFldNo   : DWord;           { 0 if not field attribute }
  540.     var ppName   : Pointer;         { returns ptr to name }
  541.     var piType   : DWord;           { returns type }
  542.     var piLen    : DWord;           { returns length }
  543.     var ppValue  : Pointer          { returns ptr to value }
  544.     ): DBResult; stdcall;
  545.  
  546.     function AddOptParameter(       { Adds optional parameter to dataset }
  547.         iFldNo   : DWord;           { 0 if not field attribute }
  548.         pszAttr  : PChar;           { ptr to name }
  549.         iType    : DWord;           { type }
  550.         iLen     : DWord;           { length }
  551.         pValue   : Pointer          { ptr to value }
  552.     ): DBResult; stdcall;
  553.  
  554.     function GetProps(              { Get dataset properties }
  555.     var Prop : DSProps
  556.     ): DBResult; stdcall;
  557.  
  558.     function GetFieldDescs(         { Get field descriptors }
  559.         Fields  : pDSFLDDesc        { Array of fields descriptors (output) }
  560.     ): DBResult; stdcall;
  561.  
  562.     function GetIndexDescs(         { Get index descriptors }
  563.         p1: PDSIDXDesc              { Array of index descriptors (output) }
  564.     ): DBResult; stdcall;
  565.  
  566.     function GetDelta(              { Extract delta from dataset }
  567.     out DsDelta: IDSBase            { Delta in a dataset }
  568.     ): DBResult; stdcall;
  569.  
  570.     function StreamDS(              { Create data packet from the dataset }
  571.     out Packet  : PSafeArray        { Return data packet }
  572.     ): DBResult; stdcall;
  573.  
  574.     function AcceptChanges: DBResult; stdcall; { Accept all current changes }
  575.  
  576.     function PutBlank(              { Put blank value }
  577.         pRecBuf      : Pointer;     { RecBuf OR }
  578.         iRecNo       : DWord;       { iRecNo }
  579.         iFldNo       : DWord;
  580.         iBlankValue  : DWord
  581.     ): DBResult; stdcall;
  582.  
  583.     function CreateIndex(           { Create, and add an index }
  584.     const IdxDesc  : DSIDXDesc
  585.     ): DBResult; stdcall;
  586.  
  587.     function RemoveIndex(           { Remove index of given name }
  588.         pszName  : PChar
  589.     ): DBResult; stdcall;
  590.  
  591.     function GetErrorString(        { Retrieve error string }
  592.         iErrCode  : DBResult;
  593.         pString   : PChar
  594.     ): DBResult; stdcall;
  595.  
  596.     function FldCmp(                { Compare field values returns 0 if equal }
  597.         iFldType  : DWord;          { Fieldtype }
  598.         pFld1     : Pointer;        { NULL if blank }
  599.         pFld2     : Pointer;        { NULL if blank }
  600.         iUnits1   : DWord;
  601.         iUnits2   : DWord
  602.     ): Integer; stdcall;
  603.  
  604.     function GetProp(               { Get property }
  605.         eProp       : DSProp;
  606.         piPropValue : Pointer
  607.     ): DBResult; stdcall;
  608.  
  609.     function SetProp(               { Set property }
  610.         eProp      : DSProp;
  611.         iPropValue : DWord
  612.     ): DBResult; stdcall;
  613.  
  614.     function SetFieldCalculation(   { Register fieldcalculation on this field }
  615.         iClientData  : DWord;       { Client data }
  616.         pfCalc       : pfDSCalcField { Callback function, NULL to remove }
  617.     ): DBResult; stdcall;
  618.  
  619.     function Reconcile(             { Reconcile update errors }
  620.         DeltaPacket   : PSafeArray; { Delta data packet }
  621.         ErrorPacket   : PSafeArray; { NULL if all changes accepted }
  622.         iClientData   : DWord;
  623.         pfReconcile   : pfDSReconcile { Callback-fn (called for each error) }
  624.     ): DBResult; stdcall;
  625.  
  626.     { Place Holders for aggregate functions that were moved into DSCursor }
  627.     function Reserved1(Input: Pointer): DBResult; stdcall;
  628.     function Reserved2(Input: Pointer): DBResult; stdcall;
  629.     function Reserved3(Input: Pointer): DBResult; stdcall;
  630.  
  631.     function Refresh(               { Refresh dataset }
  632.         NewPacket    : PSafeArray;  { New updated packet }
  633.         iClientData  : DWord;       { Client data }
  634.         pfReconcile  : pfDSReconcile { Callback for resolving conflicts }
  635.     ): DBResult; stdcall;
  636.  
  637.     function Reset: DBResult; stdcall; { Remove all data from dataset }
  638.  
  639.     function RollBack(              { Rollback changes to this savepoint }
  640.         iSavePoint  : SAVEPOINT
  641.     ): DBResult; stdcall;
  642.  
  643.     function GetEmbeddedDS(
  644.         iFieldID  : DWord;          { FieldID of embedded table (0 : get the first one) }
  645.     out DsDet     : IDSBase         { Returns the ds of the embedded table }
  646.     ): DBResult; stdcall;
  647.  
  648.     function MakeEmbedded(
  649.         DsDet             : IDSBase;  { Embed this dataset }
  650.         iFieldsLink       : DWord;
  651.         piFieldsM         : PDWord;   { Fields in Master }
  652.         piFieldsD         : PDWord;   { Fields in Detail }
  653.         pMasterFieldName  : PChar;    { Name of new link field in master, NULL if using default name }
  654.         pDetailFieldName  : PChar     { Name of new link field in detail, NULL if using defaultname }
  655.     ): DBResult; stdcall;
  656.  
  657.     function RefreshRecords(            { Refresh specific records }
  658.         NewDataPacket   : PSafeArray;   { Datapacket containing refreshed records }
  659.         iRecNo          : DWord;        { Refresh this specific record (0 if more than one.Unique key req.) }
  660.         iClientData     : DWord;
  661.         pfReconcile     : pfDSReconcile { (NULL) Callback for resolving conflicts }
  662.     ): DBResult; stdcall;
  663.  
  664.     function ReleaseBlobs(          { Release all uncommitted blobs }
  665.         iBlobId  : DWord            { 0: all uncommitted blobs, otherwise : specific blob }
  666.     ): DBResult; stdcall;
  667.  
  668.     function Clone(                 { Clones the structure of the dsbase, including details if any }
  669.          iPType : DWord;            { 0:normal-ds, 1:delta-ds, 2:error-ds }
  670.          bRecurse : Bool;           { TRUE:create complete tree-structure }
  671.          bCloneOptParams: Bool;     { TRUE:clone all optional parameters (normal only) }
  672.          var DataSet: IDSBase       { Returned dsbase }
  673.     ): DBResult; stdcall;
  674.  
  675.     function Reconcile_MD(
  676.         pDsRec          : IDSBase;           { Ds for info }
  677.         pDeltaPacket    : PSafeArray;        { Delta pickle }
  678.         pErrorPacket    : PSafeArray;        { NULL if all changes accepted }
  679.         iClientData     : DWord;
  680.         pfReconcile_MD  : pfDSReconcile_MD   { Callback-fn (called for each error) }
  681.     ): DBResult; stdcall;
  682.  
  683.    function DropOptParameter(
  684.            iFldNo: DWord;    { 0 if not field attribute }
  685.            pName: PChar      { Name of attribute to delete }
  686.         ): DBResult; stdcall;
  687.   end;
  688.  
  689. { IDSCursor }
  690.  
  691.   IDSCursor = interface(IUnknown)
  692.     ['{9E8D2FA4-591C-11D0-BF52-0020AF32BD64}']
  693.  
  694.     function InitCursor(            { Associate Cursor with a DataSet }
  695.        DataSet: IDSBase
  696.     ): DBResult; stdcall;
  697.  
  698.     function CloneCursor(           { Clone cursor from cursor }
  699.        Cursor: IDSCursor
  700.     ): DBResult; stdcall;
  701.  
  702.     function GetCursorProps(        { Get cursor properties }
  703.     var p1: DSProps
  704.     ): DBResult; stdcall;
  705.  
  706.     function GetIndexDescs(         { Get index descriptors }
  707.         bCurrentOnly  : Bool;       { Only return 'current' indexdesc, otherwise all }
  708.     var IdxDesc       : DSIDXDesc
  709.     ): DBResult; stdcall;
  710.  
  711.     function GetFieldDescs(         { Get field descriptors }
  712.         p1  : pDSFLDDesc
  713.     ): DBResult; stdcall;
  714.  
  715.     function GetCurrentRecord(      { Return record at current cursorposition }
  716.         pRecBuf  : Pointer
  717.     ): DBResult; stdcall;
  718.  
  719.     function GetRecordBlock(        { Return block of records }
  720.         piRecs   : PDWord;
  721.         pRecBuf  : Pointer
  722.     ): DBResult; stdcall;
  723.  
  724.     function GetCurrentBookMark(    { Get bookmark for current position }
  725.         pBookMark  : Pointer
  726.     ): DBResult; stdcall;
  727.  
  728.     function GetSequenceNumber(     { Get Sequence number of current position }
  729.     var iSeq  : DWord
  730.     ): DBResult; stdcall;
  731.  
  732.     function GetRecordAttribute(    { Get record attribute of current position }
  733.     var Attr  : DSAttr
  734.     ): DBResult; stdcall;
  735.  
  736.     function GetRecordCount(        { Number of records in active view }
  737.     var iRecs  : Integer
  738.     ): DBResult; stdcall;
  739.  
  740.     function MoveToBOF: DBResult; stdcall; { Set to beginning of table (BOF) }
  741.  
  742.     function MoveToEOF: DBResult; stdcall; { Set to end of table (EOF) }
  743.  
  744.     function MoveRelative(i: Integer): DBResult; stdcall;
  745.  
  746.     function MoveToSeqNo(i: DWord): DBResult; stdcall;
  747.  
  748.     function MoveToBookMark(        { Goto bookmark }
  749.       pBookMark: Pointer
  750.     ): DBResult; stdcall;
  751.  
  752.     function MoveToKey(             { Goto key }
  753.         SearchCond  : DBSearchCond;
  754.         iFields     : DWord;
  755.         iPartLen    : DWord;
  756.         pRecBuf     : Pointer
  757.     ): DBResult; stdcall;
  758.  
  759.  
  760.     function CompareBookMarks(      { Compare two bookmark (positions) -1, 0, 1 }
  761.         pBookMark1  : Pointer;
  762.         pBookMark2  : Pointer;
  763.     var iCmp        : Integer
  764.     ): DBResult; stdcall;
  765.  
  766.     function ExtractKey(            { Extract key from record }
  767.         pRecBuf  : Pointer;
  768.         pKeyBuf  : Pointer
  769.     ): DBResult; stdcall;
  770.  
  771.     function GetRecordForKey(       { Return (first) record with given key }
  772.         iFields   : DWord;
  773.         iPartLen  : DWord;
  774.         pKey      : Pointer;
  775.         pRecBuf   : Pointer
  776.     ): DBResult; stdcall;
  777.  
  778.     function GetField(              { Extract field value from record buffer }
  779.         pRecBuf   : Pointer;
  780.         iFieldNo  : DWord;
  781.         pFldBuf   : Pointer;
  782.     var bBlank    : Bool            { Returns TRUE/FALSE if blank }
  783.     ): DBResult; stdcall;
  784.  
  785.     function PutField(              { Put field value into record buffer }
  786.         pRecBuf   : Pointer;
  787.         iFieldNo  : DWord;
  788.         pFldBuf   : Pointer         { If NULL, adds a blank value }
  789.     ): DBResult; stdcall;
  790.  
  791.     { Blob functions }
  792.  
  793.     function GetBlobLen(            { Return length of blob }
  794.         pRecBuf   : Pointer;
  795.         iFieldNo  : DWord;
  796.     var iLength   : DWord
  797.     ): DBResult; stdcall;
  798.  
  799.     function GetBlob(               { Return blob }
  800.         pRecBuf   : Pointer;
  801.         iFieldNo  : DWord;
  802.         iOffSet   : DWord;          { Starting position }
  803.         pBuf      : Pointer;
  804.     var iLength   : DWord          { No of bytes to be read/ returns number read }
  805.     ): DBResult; stdcall;
  806.  
  807.     function PutBlob(               { Write blob data }
  808.         pRecBuf   : Pointer;
  809.         iFieldNo  : DWord;
  810.         iOffSet   : DWord;          { Starting position }
  811.         pBuf      : Pointer;
  812.         iLength   : DWord
  813.     ): DBResult; stdcall;
  814.  
  815.     function InitRecord(            { Initialize record buffer (for insertion) }
  816.         pRecBuf  : Pointer
  817.     ): DBResult; stdcall;
  818.  
  819.     function DeleteRecord: DBResult; stdcall; { Delete current record }
  820.  
  821.     function ModifyRecord(          { Modify current record }
  822.         pRecBuf  : Pointer
  823.     ): DBResult; stdcall;
  824.  
  825.     function InsertRecord(          { Insert new record }
  826.         pRecBuf  : Pointer
  827.     ): DBResult; stdcall;
  828.  
  829.     function UndoLastChange(        { Undo last update }
  830.         bFollowChange  : Bool
  831.     ): DBResult; stdcall;
  832.  
  833.     function AddFilter(             { Add a canexpr-filter to this cursor }
  834.         pcanExpr  : Pointer;        { Can expr }
  835.         iLen      : DWord;          { Length of canexpr }
  836.     var hFilter   : hDSFilter
  837.     ): DBResult; stdcall;
  838.  
  839.     function DropFilter(            { Drop a filter }
  840.        hFilter  : hDSFilter
  841.     ): DBResult; stdcall;
  842.  
  843.     function SetRange(              { Set a range on a cursor }
  844.         iFields    : DWord;
  845.         pKey1      : Pointer;
  846.         bKey1Incl  : Bool;
  847.         pKey2      : Pointer;
  848.         bKey2Incl  : Bool
  849.     ): DBResult; stdcall;
  850.  
  851.     function DropRange: DBResult; stdcall; { Remove current range }
  852.  
  853.     function SortOnFields(          { Sort on fields }
  854.         iFields    : DWord;
  855.         piFields   : PDWord;        { NULL -> all fields }
  856.         pDescending: PBool;         { NULL -> all ascending }
  857.         pCaseInsensitive: PBool     { NULL -> all case-sensitive }
  858.     ): DBResult; stdcall;
  859.  
  860.     function UseIndexOrder(         { Switch to index order }
  861.         pszName  : PChar
  862.     ): DBResult; stdcall;
  863.  
  864.     function SetNotifyCallBack(     { Called when posting changes to dataset }
  865.         iClientData  : DWord;
  866.         pfCallBack   : pfCHANGECallBack   { Call back fn being registered }
  867.     ): DBResult; stdcall;
  868.  
  869.     function AddFilterCallBack(     { Add a canexpr-filter to this cursor }
  870.         iClientData  : DWord;     { Client supplied data }
  871.         pfFilter     : pfDSFilter;  { ptr to filter function }
  872.     var hFilter      : hDSFilter
  873.     ): DBResult; stdcall;
  874.  
  875.     function VerifyField(           { Verify if field value is valid }
  876.         iFieldNo  : DWord;
  877.         pFldBuf   : Pointer
  878.     ): DBResult; stdcall;
  879.  
  880.     function GetProp(               { Get property }
  881.         eProp        : CURProp;
  882.         piPropValue  : Pointer
  883.     ): DBResult; stdcall;
  884.  
  885.     function RevertRecord: DBResult; stdcall; { Restore current record }
  886.  
  887.     function LocateWithFilter(
  888.         pCanExpr  : Pointer;        { NULL -> use previous }
  889.         iLen      : DWord           { Length of canexpr }
  890.     ): DBResult; stdcall;
  891.  
  892.     function AddAggregate(
  893.         iFlds     : DWord;          { Defines grouping  (0 if global) }
  894.         iCanLen   : DWord;          { Length of canexpr (0 if grouping only) }
  895.         pCanExpr  : Pointer;        { Canexpression for aggregate }
  896.     var hAgg      : hDSAggregate    { returns aggregate handle }
  897.     ): DBResult; stdcall;
  898.  
  899.     function DropAggregate(
  900.         hAgg  : hDSAggregate
  901.     ): DBResult; stdcall;
  902.  
  903.     function GetAggregateValue(
  904.         hAgg     : hDSAggregate;
  905.         pValue   : Pointer;
  906.     var bBlank   : Bool
  907.     ): DBResult; stdcall;
  908.  
  909.     function GetAggregateDesc(
  910.         hAgg   : hDSAggregate;
  911.     var Desc   : DSFLDDesc
  912.     ): DBResult; stdcall;
  913.  
  914.     function MoveToNextSubGroup(
  915.         iFields  : DWord
  916.     ): DBResult; stdcall;
  917.  
  918.     function GetSubGroupState(
  919.         iFields        : DWord;
  920.     var iSubGroupState : GROUPSTATE
  921.     ): DBResult; stdcall;
  922.  
  923.     function LinkCursors(
  924.         iFieldsM   : DWord;
  925.         piFieldsM  : PDWord;         { Fields in Master }
  926.         piFieldsD  : PDWord;         { Fields in Detail }
  927.         hCurDet    : IDSCursor       { Detail cursor to link }
  928.     ): DBResult; stdcall;
  929.  
  930.     function ResyncWithMaster: DBResult; stdcall; { If this is a detail, reset range }
  931.  
  932.     function SetProp(               { Set property }
  933.         eProp       : CURProp;      { Property to set }
  934.         iPropValue  : DWord         { Property value (or pointer to value) }
  935.     ): DBResult; stdcall;
  936.  
  937.    function GetRecordNumber(  { Return record number of current record, if any }
  938.         var iRecNo: DWord
  939.     ): DBResult; stdcall;
  940.  
  941.  
  942.     function GetRowRequestPacket(   { Get packet describing the curent 'path',
  943.                                       for delayed fetching/refreshing }
  944.         bKeysOnly       : Bool;     { Only include unique keys in packet }
  945.         bFetchAllBlobs  : Bool;     { fetch all blobs for 'current'record }
  946.         bFetchAllDetails: Bool;     { fetch all details for 'current' record }
  947.         bInclMetaData   : Bool;     { Include metadata in packet }
  948.         out Packet      : PSafeArray{ returns datapacket with row description }
  949.     ): DBResult; stdcall;
  950.  
  951.    function RefreshRecord( { Refresh details/blobs for this record, and all
  952.                              'current' records above, if any }
  953.         Packet  : PSafeArray        { New updated pickle }
  954.     ): DBResult; stdcall;
  955.  
  956.   end;
  957.  
  958. { IDSWriter }
  959.  
  960.   IDSWriter = interface(IUnknown)
  961.     ['{9E8D2FA6-591C-11D0-BF52-0020AF32BD64}']
  962.  
  963.     function Init_Sequential(   { Initialze by sequentially adding columns }
  964.         Version: DWord;
  965.         Columns: Word
  966.     ): DBResult; stdcall;
  967.  
  968.     function Init(
  969.         Version: DWord;
  970.         Columns: Word;
  971.         FieldDesc: PDSDataPacketFldDesc
  972.     ): DBResult; stdcall;
  973.  
  974.     function AddAttribute(      { Add an optional parameter }
  975.         AttrArea: TPcktAttrArea;
  976.         Attr: PChar;
  977.         AttrType: DWord;
  978.         Len: DWord;
  979.         Value: Pointer
  980.     ): DBResult; stdcall;
  981.  
  982.     function GetDataPacket(     { Return pointer to the finished 'safearray' }
  983.     var SA: PSafeArray
  984.     ): DBResult; stdcall;
  985.  
  986.  
  987.     function GetSize(           { Get the size of the safearray. }
  988.     var DataPacketSize: DWord
  989.     ): DBResult; stdcall;
  990.  
  991.  
  992.     function PutField(          { Add this field to the data stream. }
  993.         FldStatus: TPcktFldStatus;
  994.         Len: DWord;
  995.         Src: Pointer
  996.     ): DBResult; stdcall;
  997.  
  998.     function AddColumnDesc(     { Add a column descriptor. }
  999.       const FldDes: TDSDataPacketFldDesc
  1000.     ): DBResult; stdcall;
  1001.  
  1002.     { Reset all data (in order to create partial data).  Datapackets will not
  1003.       contain meta-info. Last created datapacket must be released by caller. }
  1004.     function Reset: DBResult; stdcall;
  1005.  
  1006.     { Return number of fielddescriptors, including embedded tables etc. }
  1007.  
  1008.     function GetColumnCount(var Count: DWord): DBResult; stdcall;
  1009.  
  1010.  
  1011.     function GetColumnDescs(    { Return all fielddescriptors }
  1012.         FieldDes: PDSDataPacketFldDesc
  1013.     ): DBResult; stdcall;
  1014.  
  1015.     function GetErrorString(        { Retrieve error string }
  1016.         iErrCode  : DBResult;
  1017.         pString   : PChar
  1018.     ): DBResult; stdcall;
  1019.  
  1020.    { Signals last row for a nested table, in case rowcount was not known
  1021.      in advance }
  1022.    function EndOfNestedRows: DBResult; stdcall;
  1023.  
  1024.    function SetXMLMode(iMode: Integer): DBResult; stdcall;
  1025.  
  1026.    function GetXMLMode: DWord; stdcall;
  1027.  
  1028.   end;
  1029.  
  1030. const
  1031.   CLSID_DSBase: TGUID   = '{9E8D2FA1-591C-11D0-BF52-0020AF32BD64}';
  1032.   CLSID_DSCursor: TGUID = '{9E8D2FA3-591C-11D0-BF52-0020AF32BD64}';
  1033.   CLSID_DSWriter: TGUID = '{9E8D2FA5-591C-11D0-BF52-0020AF32BD64}';
  1034.  
  1035. { Utility Routines }
  1036.  
  1037. procedure FreeDataPacket(var DataPacket: TDataPacket);
  1038. function VarToDataPacket(const V: OleVariant): TDataPacket;
  1039. function DataPacketSize(const DataPacket: TDataPacket): Integer;
  1040. procedure DataPacketToVariant(const DataPacket: TDataPacket; var V: OleVariant);
  1041. procedure CreateDbClientObject(const CLSID, IID: TGUID; out Obj);
  1042. function VariantArrayToString(const V: OleVariant): string;
  1043. function StringToVariantArray(const S: string): OleVariant;
  1044.  
  1045. implementation
  1046.  
  1047. uses ComObj, MidConst, SysUtils;
  1048.  
  1049. { Utility Routines }
  1050.  
  1051. var
  1052.   DbClientHandle: THandle = 0;
  1053.   DllGetClassObject: function(const CLSID, IID: TGUID; var Obj): HResult; stdcall;
  1054.   Loading: TRTLCriticalSection;
  1055.  
  1056. procedure CheckDbClient(const CLSID: TGUID);
  1057. var
  1058.   Size: Integer;
  1059.   FileName: string;
  1060. begin
  1061.   if DbClientHandle = 0 then
  1062.   begin
  1063.     EnterCriticalSection(Loading);
  1064.     try
  1065.       if DbClientHandle = 0 then
  1066.       begin
  1067.         Size := 256;
  1068.         SetLength(FileName, Size);
  1069.         if RegQueryValue(HKEY_CLASSES_ROOT, PChar(Format('CLSID\%s\InProcServer32',
  1070.           [GUIDToString(CLSID)])), PChar(FileName), Size) = ERROR_SUCCESS then
  1071.           SetLength(FileName, Size) else
  1072.         begin
  1073.           FileName := MIDAS_DLL;
  1074.           try
  1075.             RegisterComServer(FileName);
  1076.           except
  1077.           end;
  1078.         end;
  1079.         DbClientHandle := LoadLibrary(PChar(FileName));
  1080.         if DbClientHandle = 0 then
  1081.           raise Exception.CreateRes(@SErrorLoadingMidas);
  1082.         DllGetClassObject := GetProcAddress(DbClientHandle, 'DllGetClassObject');
  1083.       end;
  1084.     finally
  1085.       LeaveCriticalSection(Loading);
  1086.     end;
  1087.   end;
  1088. end;
  1089.  
  1090. procedure CreateDbClientObject(const CLSID, IID: TGUID; out Obj);
  1091. var
  1092.   Factory: IClassFactory;
  1093. begin
  1094.   CheckDbClient(CLSID);
  1095.   OleCheck(DllGetClassObject(CLSID, IClassFactory, Factory));
  1096.   OleCheck(Factory.CreateInstance(nil, IID, Obj));
  1097. end;
  1098.  
  1099. procedure FreeDataPacket(var DataPacket: TDataPacket);
  1100. begin
  1101.   if Assigned(DataPacket) then
  1102.   begin
  1103.     SafeArrayDestroy(DataPacket);
  1104.     DataPacket := nil;
  1105.   end;
  1106. end;
  1107.  
  1108. function VarToDataPacket(const V: OleVariant): TDataPacket;
  1109. begin
  1110.   if VarIsNull(V) then Result := nil else
  1111.   begin
  1112.     if not (VarIsArray(V) and (VarArrayHighBound(V, 1) > 20)) then
  1113.       DatabaseError(SInvalidDataPacket);
  1114.     Result := tagVARIANT(V).PArray;
  1115.   end;
  1116. end;
  1117.  
  1118. function DataPacketSize(const DataPacket: TDataPacket): Integer;
  1119. begin
  1120.   OleCheck(SafeArrayGetUBound(DataPacket, 1, Result));
  1121.   Inc(Result);
  1122. end;
  1123.  
  1124. procedure DataPacketToVariant(const DataPacket: TDataPacket; var V: OleVariant);
  1125. begin
  1126.   if Assigned(DataPacket) then
  1127.   begin
  1128.     VarClear(V);
  1129.     tagVariant(V).vt := varByte or varArray;
  1130.     tagVariant(V).PArray := DataPacket;
  1131.   end else
  1132.     V := NULL;
  1133. end;
  1134.  
  1135. function VariantArrayToString(const V: OleVariant): string;
  1136. var
  1137.   P: Pointer;
  1138.   Size: Integer;
  1139. begin
  1140.   Result := '';
  1141.   if VarIsArray(V) and (VarType(V) and varTypeMask = varByte) then
  1142.   begin
  1143.     Size := VarArrayHighBound(V, 1) - VarArrayLowBound(V, 1) + 1;
  1144.     if Size > 0 then
  1145.     begin
  1146.       SetLength(Result, Size);
  1147.       P := VarArrayLock(V);
  1148.       try
  1149.         Move(P^, Result[1], Size);
  1150.       finally
  1151.         VarArrayUnlock(V);
  1152.       end;
  1153.     end;
  1154.   end;
  1155. end;
  1156.  
  1157. function StringToVariantArray(const S: string): OleVariant;
  1158. var
  1159.   P: Pointer;
  1160. begin
  1161.   Result := NULL;
  1162.   if Length(S) > 0 then
  1163.   begin
  1164.     Result := VarArrayCreate([0, Length(S) - 1], varByte);
  1165.     P := VarArrayLock(Result);
  1166.     try
  1167.       Move(S[1], P^, Length(S));
  1168.     finally
  1169.       VarArrayUnlock(Result);
  1170.     end;
  1171.   end;
  1172. end;
  1173.  
  1174. initialization
  1175.   InitializeCriticalSection(Loading);
  1176. finalization
  1177.   if DbClientHandle > 32 then FreeLibrary(DbClientHandle);
  1178.   DeleteCriticalSection(Loading);
  1179. end.
  1180.