Обсуждение: immutable functions and enumerate type casts in indexes
Hello, I have a problem with enumerated types in functions parameters. my enumerated type is (this is a subset) CREATE TYPE hibridation AS ENUM('none','genus','specie'); function declaration CREATE FUNCTION ename(text,boolean,text,text RETURNS text AS 'funzioniGDB.so' LANGUAGE C IMMUTABLE; index creation (the type of ibrido is hibridation) CREATE INDEX i_specie_nome_specie ON specie (esterna_nome(ibrido::text,proParte,genere,specie)); the result is ERROR: functions in index expression must be marked IMMUTABLE Searching on google I found some explanation: the problem arises with "non immutable" typea as "data" but I can't figure the problem (or better, the solution) with enumerate types. What can I do? thank you Edoardo
Edoardo Panfili <edoardo@aspix.it> writes: > my enumerated type is (this is a subset) > CREATE TYPE hibridation AS ENUM('none','genus','specie'); > function declaration > CREATE FUNCTION ename(text,boolean,text,text RETURNS text AS > 'funzioniGDB.so' LANGUAGE C IMMUTABLE; > index creation (the type of ibrido is hibridation) > CREATE INDEX i_specie_nome_specie ON specie > (esterna_nome(ibrido::text,proParte,genere,specie)); > the result is > ERROR: functions in index expression must be marked IMMUTABLE Yeah, enum_out is considered STABLE not IMMUTABLE. I think this is correct for the long term, even though right now you could make some argument for an IMMUTABLE marking. For instance, we might in future allow renaming of an enum member. (Actually, you can do that today if you don't mind poking pg_enum by hand ...) Now, maybe for your purposes here it's okay to consider it immutable. In that case what I'd suggest doing is redefining ename() to take the enum directly. You could invoke enum_out within the function if you really need a text equivalent. regards, tom lane
Tom Lane ha scritto: > Edoardo Panfili <edoardo@aspix.it> writes: >> my enumerated type is (this is a subset) >> CREATE TYPE hibridation AS ENUM('none','genus','specie'); > >> function declaration >> CREATE FUNCTION ename(text,boolean,text,text RETURNS text AS >> 'funzioniGDB.so' LANGUAGE C IMMUTABLE; > >> index creation (the type of ibrido is hibridation) >> CREATE INDEX i_specie_nome_specie ON specie >> (esterna_nome(ibrido::text,proParte,genere,specie)); > >> the result is >> ERROR: functions in index expression must be marked IMMUTABLE > > Now, maybe for your purposes here it's okay to consider it immutable. > In that case what I'd suggest doing is redefining ename() to take the > enum directly. You could invoke enum_out within the function if you > really need a text equivalent. thank you! this is the right way for me. Now it works. But i have a little question about parameters of enum_out. Datum enum_out(PG_FUNCTION_ARGS); this is a part of my function ----------------------------------------------------------- Datum esterna_nome2(PG_FUNCTION_ARGS){ int label; label = enum_out(fcinfo); sprintf(debug,"false enum_out: \"%s\" ",unrolled); elog(LOG, debug); ----------------------------------------------------------- but it works only because my enum parameter is the first (and using fcinfo is a little obscure). I must build a FunctionCallInfo structure (I think) but how? Edoardo
On Tue, Sep 02, 2008 at 10:53:03AM +0200, Edoardo Panfili wrote: > But i have a little question about parameters of enum_out. > Datum enum_out(PG_FUNCTION_ARGS); > this is a part of my function > ----------------------------------------------------------- > Datum esterna_nome2(PG_FUNCTION_ARGS){ > int label; > label = enum_out(fcinfo); > sprintf(debug,"false enum_out: \"%s\" ",unrolled); > elog(LOG, debug); > ----------------------------------------------------------- > but it works only because my enum parameter is the first (and using > fcinfo is a little obscure). Look in the fmgr.h header for functions like DirectFunctionCall1 and various other ways of calling functions. Have a nice day, -- Martijn van Oosterhout <kleptog@svana.org> http://svana.org/kleptog/ > Please line up in a tree and maintain the heap invariant while > boarding. Thank you for flying nlogn airlines.
Вложения
Martijn van Oosterhout ha scritto: > On Tue, Sep 02, 2008 at 10:53:03AM +0200, Edoardo Panfili wrote: >> But i have a little question about parameters of enum_out. >> Datum enum_out(PG_FUNCTION_ARGS); >> this is a part of my function >> ----------------------------------------------------------- >> Datum esterna_nome2(PG_FUNCTION_ARGS){ >> int label; >> label = enum_out(fcinfo); >> sprintf(debug,"false enum_out: \"%s\" ",unrolled); >> elog(LOG, debug); >> ----------------------------------------------------------- >> but it works only because my enum parameter is the first (and using >> fcinfo is a little obscure). > > > Look in the fmgr.h header for functions like DirectFunctionCall1 and > various other ways of calling functions. > Now it works! thank you to Martin and Tom. this is a code fragment: -------------------------------------------------------------- #include "utils/builtins.h" PG_FUNCTION_INFO_V1(esterna_nome); Datum esterna_nome(PG_FUNCTION_ARGS){ Datum datumIbrido = PG_GETARG_DATUM(0); Datum labelDatum; char *label; labelDatum = DirectFunctionCall1(enum_out,datumIbrido); label = (char *) DatumGetPointer(labelDatum); if(strcmp(label,("label_constant"))==0){ ... } ... } -------------------------------------------------------------- I don't know why but I need <<#include "utils/builtins.h">> The line "label = (char *) DatumGetPointer(labelDatum);" is essential to use the information in strcmp() if I use directly labelDatum it does not works (but it works inside a sprintf(buffer,"%s",labelDatum)). thank you again Edoardo
Edoardo Panfili <edoardo@aspix.it> writes: > labelDatum = DirectFunctionCall1(enum_out,datumIbrido); > label = (char *) DatumGetPointer(labelDatum); Just FYI, preferred style for the second line would be label = DatumGetCString(labelDatum); Nearly all standard data types have DatumGetFoo and FooGetDatum macros to hide the conversion details (even if it's only a cast). regards, tom lane
Tom Lane ha scritto: > Edoardo Panfili <edoardo@aspix.it> writes: >> labelDatum = DirectFunctionCall1(enum_out,datumIbrido); >> label = (char *) DatumGetPointer(labelDatum); > > Just FYI, preferred style for the second line would be > > label = DatumGetCString(labelDatum); > > Nearly all standard data types have DatumGetFoo and FooGetDatum > macros to hide the conversion details (even if it's only a cast). the clean version: -------------------------------------------------------------- #include "utils/builtins.h" PG_FUNCTION_INFO_V1(esterna_nome); Datum esterna_nome(PG_FUNCTION_ARGS){ Datum datumIbrido = PG_GETARG_DATUM(0); Datum labelDatum; char *label; labelDatum = DirectFunctionCall1(enum_out,datumIbrido); label = DatumGetCString(labelDatum); if(strcmp(label,("label_constant"))==0){ ... } ... } -------------------------------------------------------------- thank you again! Edoardo