diff --git a/include/collection.h b/include/collection.h index 7eb3541..5b57ee1 100644 --- a/include/collection.h +++ b/include/collection.h @@ -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 */ diff --git a/src/collection_parse.c b/src/collection_parse.c index 410fc3b..646a5bd 100644 --- a/src/collection_parse.c +++ b/src/collection_parse.c @@ -68,6 +68,7 @@ CollectionHeader * parse_collection(char *json) { CollectionHeader *colhdr; + MemoryContext oldcxt; ListCell *lc1; ListCell *lc2; Oid typInput; @@ -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; @@ -118,9 +123,6 @@ parse_collection(char *json) if (json_error != JSON_SUCCESS) elog(ERROR, "Invalid format"); - colhdr = construct_empty_collection(CurrentMemoryContext); - - if (parse.typname) { Oid typid; @@ -128,11 +130,13 @@ parse_collection(char *json) 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); @@ -149,9 +153,9 @@ 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; @@ -159,6 +163,10 @@ parse_collection(char *json) i++; } + colhdr->current = colhdr->head; + + MemoryContextSwitchTo(oldcxt); + return colhdr; } diff --git a/src/collection_subs.c b/src/collection_subs.c index 4d4398c..8894108 100644 --- a/src/collection_subs.c +++ b/src/collection_subs.c @@ -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]) @@ -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); diff --git a/src/collection_userfuncs.c b/src/collection_userfuncs.c index cbf2ecc..5213b6d 100644 --- a/src/collection_userfuncs.c +++ b/src/collection_userfuncs.c @@ -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) diff --git a/test/expected/subscript.out b/test/expected/subscript.out index 6b0477a..432bade 100644 --- a/test/expected/subscript.out +++ b/test/expected/subscript.out @@ -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 diff --git a/test/sql/subscript.sql b/test/sql/subscript.sql index 2e75bc8..881314c 100644 --- a/test/sql/subscript.sql +++ b/test/sql/subscript.sql @@ -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 +$$;