KaiGai Kohei wrote:
> (1) Who/Where should allocate a string area?
>
> + /* Note that this assumes that the variable is already allocated! */
> + #define HANDLE_STRING_RELOPTION(optname, var, option) \
> + if (HAVE_RELOPTION(optname, option)) \
> + { \
> + strcpy(var, \
> + option.isset ? option.values.string_val : \
> + ((relopt_string *) option.gen)->default_val); \
> + continue; \
> + }
>
> I think HANDLE_STRING_RELOPTION() should allocate a string area via
> pstrdup(). If we have to put individual pstrdup() for each reloptions,
> it will make noisy listing of codes.
>
> How do you think:
>
> #define HANDLE_STRING_RELOPTION(optname, var, option) \
> if (HAVE_RELOPTION(optname, option)) \
> { \
> char *tmp = (option.isset ? option.values.string_val : \
> ((relopt_string *) option.gen)->default_val); \
> var = pstrdup(tmp); \
> continue; \
> }
Well, that's precisely the problem with string options. If we want
memory to be freed properly, we can only allocate a single chunk which
is what's going to be stored under the rd_options bytea pointer.
Allocating separately doesn't work because we need to rebuild the
relcache entry (freeing it and allocating a new one) when it is
invalidated for whatever reason. Since the relcache code cannot follow
a pointer stored in the bytea area, this would result in a permanent
memory leak.
So the rule I came up with is that the caller is responsible for
allocating it -- but it must be inside the bytea area to be returned.
Below is a sample amoptions routine to show how it works. Note that
this is exactly why I said that only a single string option can be
supported.
If you have a better idea, I'm all ears.
> (2) How does it represent NULL in string_option?
>
> It seems to me we cannot represent a NULL string in the default.
> Is it possible to add a mark to indicate NULL, like "bool default_null"
> within struct relopt_string?
Ah, good point. I'll have a look at this.
> (3) heap_reloptions() from RelationParseRelOptions() makes a trouble.
This is the same as (1) actually.
--
Alvaro Herrera http://www.CommandPrompt.com/
The PostgreSQL Company - Command Prompt, Inc.
/* must follow StdRdOptions conventions */
typedef struct BtOptions
{
int32 vl_len_;
int fillfactor;
char teststring[1];
} BtOptions;
Datum
btoptions(PG_FUNCTION_ARGS)
{
Datum reloptions = PG_GETARG_DATUM(0);
bool validate = PG_GETARG_BOOL(1);
bytea *result;
relopt_value *options;
int numoptions;
int i;
static bool initialized = false;
if (!initialized)
{
add_string_reloption(RELOPT_KIND_BTREE, "teststring", NULL,
"helluva string here
and there!");
initialized = true;
}
options = parseRelOptions(reloptions, validate, RELOPT_KIND_BTREE,
&numoptions);
/* if none set, we're done */
if (numoptions == 0)
result = NULL;
else
{
BtOptions *rdopts;
int tstrlen;
for (i = 0; i < numoptions; i++)
{
if (HAVE_RELOPTION("teststring", options[i]))
{
tstrlen = options[i].isset ?
strlen(options[i].values.string_val) :
((relopt_string *)
options[i].gen)->default_len;
break;
}
}
rdopts = palloc0(sizeof(BtOptions) + tstrlen + 1);
for (i = 0; i < numoptions; i++)
{
HANDLE_INT_RELOPTION("fillfactor", rdopts->fillfactor,
options[i]);
HANDLE_STRING_RELOPTION("teststring",
rdopts->teststring, options[i]);
}
pfree(options);
SET_VARSIZE(rdopts, sizeof(BtOptions) + tstrlen + 1);
result = (bytea *) rdopts;
}
if (result)
PG_RETURN_BYTEA_P(result);
PG_RETURN_NULL();
}
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers