freepascal  2.6


unit odbcconn;

function TODBCConnection.LoadField(cursor: TSQLCursor; FieldDef: 
TFieldDef; buffer: pointer; out CreateBlob : boolean): boolean;
{$ELSE}
function TODBCConnection.LoadField(cursor: TSQLCursor; FieldDef: 
TFieldDef; buffer: pointer):boolean;
{$ENDIF}
var
   ODBCCursor:TODBCCursor;
   StrLenOrInd:SQLINTEGER;
   ODBCDateStruct:SQL_DATE_STRUCT;
   ODBCTimeStruct:SQL_TIME_STRUCT;
   ODBCTimeStampStruct:SQL_TIMESTAMP_STRUCT;
   DateTime:TDateTime;
{$IF NOT((FPC_VERSION>=2) AND (FPC_RELEASE>=1))}
   BlobBuffer:pointer;
   BlobBufferSize,BytesRead:SQLINTEGER;
   BlobMemoryStream:TMemoryStream;
{$ENDIF}
   Res:SQLRETURN;
begin
{$IF (FPC_VERSION>=2) AND (FPC_RELEASE>=1)}
   CreateBlob := False;
{$ENDIF}
   ODBCCursor:=cursor as TODBCCursor;

   // load the field using SQLGetData
   // Note: optionally we can implement the use of SQLBindCol later for 
even more speed
   // TODO: finish this
   case FieldDef.DataType of
     ftWideString,ftFixedWideChar: // mapped to TWideStringField
       Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, 
SQL_C_WCHAR, buffer, FieldDef.Size+sizeof(WideChar), @StrLenOrInd); 
//buffer must contain space for the null-termination character
     ftGuid, ftFixedChar,ftString: // are mapped to a TStringField 
(including TGuidField)
       Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, 
SQL_C_CHAR, buffer, FieldDef.Size+1, @StrLenOrInd);
     ftSmallint:           // mapped to TSmallintField
       Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, 
SQL_C_SSHORT, buffer, SizeOf(Smallint), @StrLenOrInd);
     ftInteger,ftWord,ftAutoInc:     // mapped to TLongintField
       Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, 
SQL_C_SLONG, buffer, SizeOf(Longint), @StrLenOrInd);
     ftLargeint:           // mapped to TLargeintField
       Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, 
SQL_C_SBIGINT, buffer, SizeOf(Largeint), @StrLenOrInd);
     ftFloat:              // mapped to TFloatField
       Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, 
SQL_C_DOUBLE, buffer, SizeOf(Double), @StrLenOrInd);
     ftTime:               // mapped to TTimeField
     begin
       Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, 
SQL_C_TYPE_TIME, @ODBCTimeStruct, SizeOf(SQL_TIME_STRUCT), @StrLenOrInd);
       if StrLenOrInd<>SQL_NULL_DATA then
       begin
         DateTime:=TimeStructToDateTime(@ODBCTimeStruct);
         Move(DateTime, buffer^, SizeOf(TDateTime));
       end;
     end;
     ftDate:               // mapped to TDateField
     begin
       Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, 
SQL_C_TYPE_DATE, @ODBCDateStruct, SizeOf(SQL_DATE_STRUCT), @StrLenOrInd);
       if StrLenOrInd<>SQL_NULL_DATA then
       begin
         DateTime:=DateStructToDateTime(@ODBCDateStruct);
         Move(DateTime, buffer^, SizeOf(TDateTime));
       end;
     end;
     ftDateTime:           // mapped to TDateTimeField
     begin
       // Seems like not all ODBC-drivers (mysql on Linux) set the 
fractional part. Initialize
       // it's value to avoid 'random' data.
       ODBCTimeStampStruct.Fraction:=0;
       Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, 
SQL_C_TYPE_TIMESTAMP, @ODBCTimeStampStruct, 
SizeOf(SQL_TIMESTAMP_STRUCT), @StrLenOrInd);
       if StrLenOrInd<>SQL_NULL_DATA then
       begin
         DateTime:=TimeStampStructToDateTime(@ODBCTimeStampStruct);
         Move(DateTime, buffer^, SizeOf(TDateTime));
       end;
     end;
     ftBoolean:            // mapped to TBooleanField
       Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, 
SQL_C_BIT, buffer, SizeOf(Wordbool), @StrLenOrInd);
     ftBytes:              // mapped to TBytesField
       Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, 
SQL_C_BINARY, buffer, FieldDef.Size, @StrLenOrInd);
     ftVarBytes:           // mapped to TVarBytesField
       Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, 
SQL_C_BINARY, buffer, FieldDef.Size, @StrLenOrInd);
{$IF (FPC_VERSION>=2) AND (FPC_RELEASE>=1)}
     ftWideMemo,
{$ENDIF}
     ftBlob, ftMemo:       // BLOBs
     begin
       //Writeln('BLOB');
       // Try to discover BLOB data length
       Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, 
SQL_C_BINARY, buffer, 0, @StrLenOrInd);
       ODBCCheckResult(Res, SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, 
'Could not get field data for field "%s" (index %d).',[FieldDef.Name, 
FieldDef.Index+1]);
       // Read the data if not NULL
       if StrLenOrInd<>SQL_NULL_DATA then
       begin
{$IF (FPC_VERSION>=2) AND (FPC_RELEASE>=1)}
         CreateBlob:=true; // defer actual loading of blob data to 
LoadBlobIntoBuffer method
         //WriteLn('Deferring loading of blob of length ',StrLenOrInd);
{$ELSE}
         // Determine size of buffer to use
         if StrLenOrInd<>SQL_NO_TOTAL then
           BlobBufferSize:=StrLenOrInd
         else
           BlobBufferSize:=DEFAULT_BLOB_BUFFER_SIZE;
         try
           // init BlobBuffer and BlobMemoryStream to nil pointers
           BlobBuffer:=nil;
           BlobMemoryStream:=nil;
           if BlobBufferSize>0 then // Note: zero-length BLOB is 
represented as nil pointer in the field buffer to save memory usage
           begin
             // Allocate the buffer and memorystream
             BlobBuffer:=GetMem(BlobBufferSize);
             BlobMemoryStream:=TMemoryStream.Create;
             // Retrieve data in parts (or effectively in one part if 
StrLenOrInd<>SQL_NO_TOTAL above)
             repeat
               Res:=SQLGetData(ODBCCursor.FSTMTHandle, FieldDef.Index+1, 
SQL_C_BINARY, BlobBuffer, BlobBufferSize, @StrLenOrInd);
               ODBCCheckResult(Res, SQL_HANDLE_STMT, 
ODBCCursor.FSTMTHandle, 'Could not get field data for field "%s" (index 
%d).',[FieldDef.Name, FieldDef.Index+1]);
               // Append data in buffer to memorystream
               if (StrLenOrInd=SQL_NO_TOTAL) or 
(StrLenOrInd>BlobBufferSize) then
                 BytesRead:=BlobBufferSize
               else
                 BytesRead:=StrLenOrInd;
               BlobMemoryStream.Write(BlobBuffer^, BytesRead);
             until Res=SQL_SUCCESS;
           end;
           // Store memorystream pointer in Field buffer and in the 
cursor's FBlobStreams list
           TObject(buffer^):=BlobMemoryStream;
           if BlobMemoryStream<>nil then
             ODBCCursor.FBlobStreams.Add(BlobMemoryStream);
           // Set BlobMemoryStream to nil, so it won't get freed in the 
finally block below
           BlobMemoryStream:=nil;
         finally
           BlobMemoryStream.Free;
           if BlobBuffer<>nil then
             Freemem(BlobBuffer,BlobBufferSize);
         end;
{$ENDIF}
       end;
     end;
     // TODO: Loading of other field types
   else
     raise EODBCException.CreateFmt('Tried to load field of unsupported 
field type %s',[Fieldtypenames[FieldDef.DataType]]);
   end;
   ODBCCheckResult(Res, SQL_HANDLE_STMT, ODBCCursor.FSTMTHandle, 'Could 
not get field data for field "%s" (index %d).',[FieldDef.Name, 
FieldDef.Index+1]);
   Result:=StrLenOrInd<>SQL_NULL_DATA; // Result indicates whether the 
value is non-null

   //writeln(Format('Field.Size: %d; StrLenOrInd: %d',[FieldDef.Size, 
StrLenOrInd]));
end;

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
mseide-msegui-talk mailing list
mseide-msegui-talk@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mseide-msegui-talk

Reply via email to