FirebirdSQL / firebird

Firebird server, client and tools
https://www.firebirdsql.org/
1.26k stars 216 forks source link

invalid BLOB type for operation (x86_64) [CORE2377] #2799

Closed firebird-automations closed 15 years ago

firebird-automations commented 15 years ago

Submitted by: Alexander (coopht)

I recieve this error only x86_64 architecture, on the same firebird version, but on X86 Gentoo linux everithing is fine.

I have following UDF function: void my_func (BLOB b, BLOB out)) { char *buf = NULL; short length = 0; short actual_length = 0;

if (!b->blob_handle) return;

length = (short) (b->blob_max_segment);

buf = malloc (length + 1L);

(*b->blob_get_segment) (b->blob_handle, buf, length, &actual_length); buf [actual_length] = 0;

  if \(out\-\>blob\_handle\)
\(\*out\-\>blob\_put\_segment\) \(out\-\>blob\_handle, buf, actual\_length\);    

if (buf) free (buf); }

declare query:

DECLARE EXTERNAL FUNCTION BSTR BLOB, BLOB RETURNS PARAMETER 2 ENTRY_POINT 'my_func' MODULE_NAME 'my_udf.so'

Creating table for input blob: CREATE TABLE test_table (B BLOB (80,1))

Insert blob into table: INSERT INTO test_table VALUES (?) I insert blob into test table from my program, and it is a TEXT BLOB, and it is correct, because i can view it's content with flamerobin.

And when i execute select: SELECT BSTR (B) FROM test_table

i got such error:

*** IBPP::SQLException *** Context: Statement::Fetch Message: isc_dsql_fetch failed.

SQL Message : -685 invalid ARRAY or BLOB operation

Engine Code : 335544465 Engine Message : invalid BLOB type for operation

firebird-automations commented 15 years ago

Commented by: @AlexPeshkoff

How is defined BLOB in your UDF? Where from is BLOB definition taken?

firebird-automations commented 15 years ago

Commented by: Alexander (coopht)

BLOB is defined as followed in my UDF typedef struct blob { short (*blob_get_segment)(); int *blob_handle; long blob_number_segments; long blob_max_segment; long blob_total_length; void (*blob_put_segment)(); long (*blob_seek)(); } *BLOB;

firebird-automations commented 15 years ago

Commented by: @AlexPeshkoff

X64 played rather typical joke with you. You have declared a few entities as long: long blob_number_segments; and this is 64-bit on X64, but must be - 32-bit. The safest way is to use BLOBCALLBACK (declared in ibase.h) in all your UDFs instead of your BLOB.

Please confirm - did it fix your problem or not.

firebird-automations commented 15 years ago

Commented by: Alexander (coopht)

I defined BLOB type as followed, and fixed the problem .

typedef struct blob { short (*blob_get_segment)(); void *blob_handle; int blob_number_segments; int blob_max_segment; int blob_total_length; void (*blob_put_segment)(); int (*blob_seek)(); } *BLOB;

Thank you for your help.

P.S. There no any information about ISC_BLOB_CALLBACK structure in Developers guide, that is why i did not use it.

firebird-automations commented 15 years ago
Modified by: @dyemanov status: Open \[ 1 \] =\> Resolved \[ 5 \] resolution: Won't Fix \[ 2 \]
firebird-automations commented 15 years ago
Modified by: @pcisar status: Resolved \[ 5 \] =\> Closed \[ 6 \]
firebird-automations commented 15 years ago

Commented by: SITA VINCENZO (sita)

Hello,

I tried to do the same with lazarus for firebird64 but il doesn't work. In win32 it works but in vista64 it doesn't. I did something wrong. Perhaps you have some idea for help.

Thank you

New declaration TISC_BlobGetSegment = function(BlobHandle: PInt; Buffer: PChar; BufferSize: Int; var ResultLength: Int): Short; cdecl; Old declaration TISC_BlobGetSegment = function(BlobHandle: PInt; Buffer: PChar; BufferSize: Long; var ResultLength: Long): Short; cdecl;

New declaration TISC_BlobPutSegment = procedure(BlobHandle: PInt; Buffer: PChar; BufferLength: Short); cdecl;
Old declaration TISC_BlobPutSegment = procedure(BlobHandle: PInt; Buffer: PChar; BufferLength: Short); cdecl;

New declaration TISC_BlobSeekSegment = procedure(BlobHandle:PInt; Mode:Short; Offset:Int); cdecl;

New declaration TBlob = record GetSegment : TISC_BlobGetSegment; BlobHandle : PInt; SegmentCount : Int; MaxSegmentLength : Int; TotalSize : Int; PutSegment : TISC_BlobPutSegment; SeekSegment : TISC_BlobSeekSegment; end; PBlob = ^TBlob;

Old declaration TBlob = record GetSegment :TISC_BlobGetSegment; BlobHandle : PInt; SegmentCount : Long; MaxSegmentLength : Long; TotalSize : Long; PutSegment : TISC_BlobPutSegment; end; PBlob = ^TBlob;

//Example of IB_EXTERNALS.PAS how it was before

(* * ib_externals.pas * copyright (c) 1998 by * Gregory Deatz * mailto:gdeatz@hlmdd.com *) unit ib_externals;

{$IFDEF FPC} {$PACKRECORDS 1} {$ENDIF}

{ Some structures, declarations that we need for the IB stuff to work, but that aren't really part of the ib header file. } interface

{$IFDEF FPC} {$IFDEF MSWINDOWS} uses Windows, StdFuncs; {$ENDIF} {$ELSE} uses Windows, StdFuncs; {$ENDIF}

type Int = LongInt; // 32 bit signed UInt = DWord; // 32 bit unsigned Long = LongInt; // 32 bit signed ULong = DWord; // 32 bit unsigned Short = SmallInt;// 16 bit signed UShort = Word; // 16 bit unsigned Float = Single; // 32 bit UChar = Byte; // 8 bit unsigned ISC_LONG = Long; // 32 bit signed UISC_LONG = ULong; // 32 bit unsigned ISC_STATUS = Long; // 32 bit signed UISC_STATUS = ULong; // 32 bit unsigned Void = Pointer; // Delphi "Pointer types" PPChar = ^PChar; PSmallInt = ^SmallInt; PInt = ^Int; PInteger = ^Integer; PShort = ^Short; PUShort = ^UShort; PLong = ^Long; PULong = ^ULong; PFloat = ^Float; PUChar = ^UChar; PVoid = ^Pointer; PDouble = ^Double; PISC_LONG = ^ISC_LONG; PUISC_LONG = ^UISC_LONG; PISC_STATUS = ^ISC_STATUS; PPISC_STATUS = ^PISC_STATUS; PUISC_STATUS = ^UISC_STATUS;

{ C Date/Time Structure } {$IFDEF FPC} TCTimeStructure = packed record tm_sec : longint; // Seconds tm_min : longint; // Minutes tm_hour : longint; // Hour (0--23) tm_mday : longint; // Day of month (1--31) tm_mon : longint; // Month (0--11) tm_year : longint; // Year (calendar year minus 1900) tm_wday : longint; // Weekday (0--6) Sunday = 0) tm_yday : longint; // Day of year (0--365) tm_isdst : longint; // 0 if daylight savings time is not in effect) __tm_gmtoof: longint; __tm_zone: PChar; end; {$ELSE} TCTimeStructure = record tm_sec : integer; // Seconds tm_min : integer; // Minutes tm_hour : integer; // Hour (0--23) tm_mday : integer; // Day of month (1--31) tm_mon : integer; // Month (0--11) tm_year : integer; // Year (calendar year minus 1900) tm_wday : integer; // Weekday (0--6) Sunday = 0) tm_yday : integer; // Day of year (0--365) tm_isdst : integer; // 0 if daylight savings time is not in effect) end; {$ENDIF}

PCTimeStructure = ^TCTimeStructure; TM = TCTimeStructure; PTM = ^TM;

TISC_VARYING = record strlen: Short; str: array[0..0] of Char; end;

{***************************} {* Some blob ctl structs *} {* from IB help files for *} {* implementing UDFs . *} {* -- Taken from docs, not *} {* in original ibase.h *} {***************************} TISC_BlobGetSegment = function(BlobHandle: PInt; Buffer: PChar; BufferSize: Long; var ResultLength: Long): Short; cdecl;

TISC_BlobPutSegment = procedure(BlobHandle: PInt; Buffer: PChar; BufferLength: Short); cdecl;

TBlob = record GetSegment :TISC_BlobGetSegment; BlobHandle : PInt; SegmentCount : Long; MaxSegmentLength : Long; TotalSize : Long; PutSegment : TISC_BlobPutSegment; end; PBlob = ^TBlob;

const // Delphi consts // Days of week dSun = 1; dMon = 2; dTue = 3; dWed = 4; dThu = 5; dFri = 6; dSat = 7; // Months of year dJan = 1; dFeb = 2; dMar = 3; dApr = 4; dMay = 5; dJun = 6; dJul = 7; dAug = 8; dSep = 9; dOct = 10; dNov = 11; dDec = 12; // C Consts cYearOffset = 1900; // Days of week cSun = 0; cMon = 1; cTue = 2; cWed = 3; cThu = 4; cFri = 5; cSat = 6; // Months of year cJan = 0; cFeb = 1; cMar = 2; cApr = 3; cMay = 4; cJun = 5; cJul = 6; cAug = 7; cSep = 8; cOct = 9; cNov = 10; cDec = 11;

procedure InitializeTCTimeStructure(var tm_record: TCTimeStructure);

implementation

procedure InitializeTCTimeStructure(var tm_record: TCTimeStructure); begin with tm_record do begin tm_sec := 0; tm_min := 0; tm_hour := 0; tm_mday := 0; tm_mon := 0; tm_year := 0; tm_wday := 0; tm_yday := 0; tm_isdst := 0; end; end;

end.

firebird-automations commented 15 years ago

Commented by: @asfernandes

Are you sure that "Int = LongInt; // 32 bit signed" really defines it as 32 bit integer?

firebird-automations commented 15 years ago

Commented by: SITA VINCENZO (sita)

No but I'don't know which type i shut use in free-pascal.

firebird-automations commented 15 years ago

Commented by: @asfernandes

Integer?

firebird-automations commented 15 years ago

Commented by: SITA VINCENZO (sita)

I've tried but without sucess.

firebird-automations commented 15 years ago

Commented by: SITA VINCENZO (sita)

Hello

I ask me if you have an idea why --> Getsegment works

                          TISC\_BlobGetSegment = function\(BlobHandle: PInt; Buffer: PChar; BufferSize: Long; var ResultLength: Long\): Short; cdecl; 
                          Exemple

with Blob^ do begin SetString(S, nil, TotalSize); total_bytes_read := 0; bytes_left := TotalSize; if (bytes_left = 0) then exit; repeat GetSegment(BlobHandle, @S[total_bytes_read + 1], bytes_left, bytes_read); Inc(total_bytes_read, bytes_read); Dec(bytes_left, bytes_read); until bytes_left <= 0; end;

and PutSegment don't works

                          TISC\_BlobPutSegment = procedure\(BlobHandle: PInt; const Buffer: PChar; BufferLength: UShort\); cdecl;

thank you

firebird-automations commented 15 years ago

Commented by: @asfernandes

Blob handle is not pointer, it's 32 bit value.

You shall better move your questions to the support list.