Обсуждение: help defining a basic type operator
Hi all, I'm trying to define a custom data type that would represent a number of bytes in a lossy human way. The type is defined as: typedef struct HFSize { double size; int scaling; } HFSize; and the operator function is defined as: Datum hfsize_add(PG_FUNCTION_ARGS) { HFSize *first = (HFSize *) PG_GETARG_POINTER(0); HFSize *second = (HFSize *) PG_GETARG_POINTER(1); HFSize *sum = new_HFSize(); to_bytes( first ); to_bytes( second ); elog( DEBUG1, "sum %s + %s ", to_string( first ), to_string( second ) ); sum->size = first->size + second->size; elog( DEBUG1, "Final sum %s ", to_string( sum ) ); PG_RETURN_POINTER( sum ); } The problem is that, even if the last elog shows a correct result, the final value returned via PG_RETURN_POINTER is something totally different with the double value set to zero and an apparently random 'scaling': # set client_min_messages to debug; SET testdb=# SELECT '1030'::hfsize + '2030'::hfsize; DEBUG: Converting to human text format 1030.00-bytes LINE 1: SELECT '1030'::hfsize + '2030'::hfsize; ^ DEBUG: Converting to human text format 2030.00-bytes LINE 1: SELECT '1030'::hfsize + '2030'::hfsize; ^ DEBUG: sum 1030.00-bytes + 2030.00-bytes DEBUG: Final sum 3060.00-bytes ?column? ---------- 0.00-64 I've tried also to return one of the two operands from the add function, so something like: Datum hfsize_add(PG_FUNCTION_ARGS) { HFSize *first = (HFSize *) PG_GETARG_POINTER(0); HFSize *second = (HFSize *) PG_GETARG_POINTER(1); PG_RETURN_POINTER( first ); } but again the result has a zero value and a random scaling, and most notably is not the first operand. Also memory addresses (used with %x) are different from inside and outside the add function. Is there something I'm missing? Thanks, Luca
Luca Ferrari <fluca1978@gmail.com> writes: > I'm trying to define a custom data type that would represent a number > of bytes in a lossy human way. You did not show us the SQL definition of the type. I don't see anything obviously wrong in what you showed (other than hfsize_add not setting the result's scaling), so the problem is somewhere else. Given this C declaration, the type probably needs to be size 16, double alignment, pass-by-reference; maybe you messed up part of that? > HFSize *sum = new_HFSize(); What is new_HFSize? regards, tom lane
On Mon, Aug 20, 2018 at 4:51 PM Tom Lane <tgl@sss.pgh.pa.us> wrote: > > Luca Ferrari <fluca1978@gmail.com> writes: > > I'm trying to define a custom data type that would represent a number > > of bytes in a lossy human way. > > You did not show us the SQL definition of the type. I don't see anything > obviously wrong in what you showed (other than hfsize_add not setting the > result's scaling), so the problem is somewhere else. Given this C > declaration, the type probably needs to be size 16, double alignment, > pass-by-reference; maybe you messed up part of that? > Shame on me: when I issued a create type I didn't realize that I was miswriting the length attribute from 'internallength' to 'internalsize', and while an error was reported, the type was created. Fixing the type creation into: CREATE TYPE hfsize ( internallength = 16, input = hfsize_input_function, output = hfsize_output_function ); solved the problem, so it was a length mismatch. > > HFSize *sum = new_HFSize(); > > What is new_HFSize? An helper function to allocate a new object (and that was why scaling did not get referenced in the add function): HFSize* new_HFSize() { HFSize *size = (HFSize*) palloc( sizeof( HFSize ) ); size->scaling = 0; size->size = 0.0f; return size; } Thanks, Luca
Luca Ferrari <fluca1978@gmail.com> writes: > Fixing the type creation into: > CREATE TYPE hfsize ( > internallength = 16, > input = hfsize_input_function, > output = hfsize_output_function > ); > solved the problem, so it was a length mismatch. You really need to specify double alignment too; IIRC the default assumption is only "int" alignment. Intel processors will usually let you get away with being sloppy about that, but it's still wrong (and there *are* cases where Intel will complain too). regards, tom lane