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
[email protected]
https://lists.sourceforge.net/lists/listinfo/mseide-msegui-talk