Skip to content

Commit

Permalink
Resolve issue #7: Parse an incoming text representation of a collecti…
Browse files Browse the repository at this point in the history
…on in the correct memory context.
  • Loading branch information
jim-mlodgenski committed Feb 3, 2025
1 parent 5883ac1 commit a5d1739
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 8 deletions.
2 changes: 1 addition & 1 deletion include/collection.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
#undef uthash_nonfatal_oom
#define uthash_malloc(sz) palloc(sz)
#define uthash_free(ptr,sz) pfree(ptr)
#define uthash_nonfatal_oom(e) do{elog(ERROR, "Unable to allocate memory");}while(0)
#define uthash_nonfatal_oom(e) do{elog(ERROR, "unable to allocate memory");}while(0)

#define COLLECTION_MAGIC 8675309 /* ID for debugging crosschecks */

Expand Down
18 changes: 13 additions & 5 deletions src/collection_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ CollectionHeader *
parse_collection(char *json)
{
CollectionHeader *colhdr;
MemoryContext oldcxt;
ListCell *lc1;
ListCell *lc2;
Oid typInput;
Expand All @@ -79,6 +80,10 @@ parse_collection(char *json)
JsonCollectionParseState parse;
JsonCollectionParseContext context;

colhdr = construct_empty_collection(CurrentMemoryContext);

oldcxt = MemoryContextSwitchTo(colhdr->hdr.eoh_context);

context.private_data = json;

parse.context = &context;
Expand Down Expand Up @@ -118,21 +123,20 @@ parse_collection(char *json)
if (json_error != JSON_SUCCESS)
elog(ERROR, "Invalid format");

colhdr = construct_empty_collection(CurrentMemoryContext);


if (parse.typname)
{
Oid typid;

typid = DatumGetObjectId(DirectFunctionCall1(regtypein, CStringGetDatum(parse.typname)));
colhdr->value_type = typid;
colhdr->value_type_len = get_typlen(typid);
colhdr->value_byval = get_typbyval(typid);
}
else
{
colhdr->value_type = TEXTOID;
colhdr->value_type_len = -1;
colhdr->value_byval = false;
}

getTypeInputInfo(colhdr->value_type, &typInput, &typIOParam);
Expand All @@ -149,16 +153,20 @@ parse_collection(char *json)
item->key = key;

value = OidFunctionCall1(typInput, CStringGetDatum(vstr));
item->value = datumCopy(value, true, colhdr->value_type_len);
item->value = datumCopy(value, colhdr->value_byval, colhdr->value_type_len);

HASH_ADD_PTR(colhdr->current, key, item);
HASH_ADD_KEYPTR(hh, colhdr->current, key, strlen(key), item);

if (i == 0)
colhdr->head = colhdr->current;

i++;
}

colhdr->current = colhdr->head;

MemoryContextSwitchTo(oldcxt);

return colhdr;
}

Expand Down
4 changes: 2 additions & 2 deletions src/collection_subs.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ collection_subscript_fetch(ExprState *state,
/* Should not get here if source collection is null */
Assert(!(*op->resnull));

colhdr = (CollectionHeader *) DatumGetEOHP(*op->resvalue);
colhdr = (CollectionHeader *) DatumGetExpandedCollection(*op->resvalue);

/* Check for null subscript */
if (sbsrefstate->upperindexnull[0])
Expand Down Expand Up @@ -213,7 +213,7 @@ collection_subscript_assign(ExprState *state,
}
else
{
colhdr = (CollectionHeader *) DatumGetEOHP(*op->resvalue);
colhdr = (CollectionHeader *) DatumGetExpandedCollection(*op->resvalue);
}

pgstat_report_wait_start(collection_we_assign);
Expand Down
1 change: 1 addition & 0 deletions src/collection_userfuncs.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ collection_copy(PG_FUNCTION_ARGS)

copyhdr->value_type = colhdr->value_type;
copyhdr->value_type_len = colhdr->value_type_len;
copyhdr->value_byval = colhdr->value_byval;

head = colhdr->head;
for (iter = colhdr->head; iter != NULL; iter = iter->hh.next)
Expand Down
25 changes: 25 additions & 0 deletions test/expected/subscript.out
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,28 @@ NOTICE: Subscript test 14
ERROR: incompatible value data type
DETAIL: expecting bigint, but received text
CONTEXT: PL/pgSQL function inline_code_block line 8 at assignment
DO
$$
DECLARE
t collection('bigint');
x collection('bigint');
BEGIN
RAISE NOTICE 'Subscript test 15';
t['1'] := 1;
t['2'] := 2;
t['111'] := 11;

RAISE NOTICE 'The current val of t is %', t;

x := (t::text)::collection('bigint');
RAISE NOTICE 'The current val of x is %', x;
RAISE NOTICE 'The current val of t[2] is %', t['2'];

RAISE NOTICE 'The current val of x[2] is %', x['2'];
END
$$;
NOTICE: Subscript test 15
NOTICE: The current val of t is {"value_type": "bigint", "entries": {"1": "1", "2": "2", "111": "11"}}
NOTICE: The current val of x is {"value_type": "bigint", "entries": {"1": "1", "2": "2", "111": "11"}}
NOTICE: The current val of t[2] is 2
NOTICE: The current val of x[2] is 2
20 changes: 20 additions & 0 deletions test/sql/subscript.sql
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,23 @@ BEGIN
END
$$;

DO
$$
DECLARE
t collection('bigint');
x collection('bigint');
BEGIN
RAISE NOTICE 'Subscript test 15';
t['1'] := 1;
t['2'] := 2;
t['111'] := 11;

RAISE NOTICE 'The current val of t is %', t;

x := (t::text)::collection('bigint');
RAISE NOTICE 'The current val of x is %', x;
RAISE NOTICE 'The current val of t[2] is %', t['2'];

RAISE NOTICE 'The current val of x[2] is %', x['2'];
END
$$;

0 comments on commit a5d1739

Please sign in to comment.