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