citus/src/backend/distributed/utils/jsonbutils.c

133 lines
3.2 KiB
C

#include "postgres.h"
#include "fmgr.h"
#include "catalog/namespace.h"
#include "catalog/pg_class.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/json.h"
#include "utils/lsyscache.h"
#include "pg_version_compat.h"
#include "distributed/jsonbutils.h"
#include "distributed/metadata_cache.h"
/*
* ExtractFieldJsonb gets value of fieldName from jsonbDoc and puts it
* into result. If not found, returns false. Otherwise, returns true.
* The field is returned as a Text* Datum if as_text is true, or a Jsonb*
* Datum if as_text is false.
*/
static bool
ExtractFieldJsonb(Datum jsonbDoc, const char *fieldName, Datum *result, bool as_text)
{
Datum pathArray[1] = { CStringGetTextDatum(fieldName) };
bool pathNulls[1] = { false };
bool typeByValue = false;
char typeAlignment = 0;
int16 typeLength = 0;
int dimensions[1] = { 1 };
int lowerbounds[1] = { 1 };
get_typlenbyvalalign(TEXTOID, &typeLength, &typeByValue, &typeAlignment);
ArrayType *pathArrayObject = construct_md_array(pathArray, pathNulls, 1, dimensions,
lowerbounds, TEXTOID, typeLength,
typeByValue, typeAlignment);
Datum pathDatum = PointerGetDatum(pathArrayObject);
FmgrInfo fmgrInfo;
if (as_text)
{
fmgr_info(JsonbExtractPathTextFuncId(), &fmgrInfo);
}
else
{
fmgr_info(JsonbExtractPathFuncId(), &fmgrInfo);
}
LOCAL_FCINFO(functionCallInfo, 2);
InitFunctionCallInfoData(*functionCallInfo, &fmgrInfo, 2, DEFAULT_COLLATION_OID, NULL,
NULL);
fcSetArg(functionCallInfo, 0, jsonbDoc);
fcSetArg(functionCallInfo, 1, pathDatum);
*result = FunctionCallInvoke(functionCallInfo);
return !functionCallInfo->isnull;
}
/*
* ExtractFieldBoolean gets value of fieldName from jsonbDoc, or returns
* defaultValue if it doesn't exist.
*/
bool
ExtractFieldBoolean(Datum jsonbDoc, const char *fieldName, bool defaultValue)
{
Datum jsonbDatum = 0;
bool found = ExtractFieldJsonb(jsonbDoc, fieldName, &jsonbDatum, false);
if (!found)
{
return defaultValue;
}
Datum boolDatum = DirectFunctionCall1(jsonb_bool, jsonbDatum);
return DatumGetBool(boolDatum);
}
/*
* ExtractFieldInt32 gets value of fieldName from jsonbDoc, or returns
* defaultValue if it doesn't exist.
*/
int32
ExtractFieldInt32(Datum jsonbDoc, const char *fieldName, int32 defaultValue)
{
Datum jsonbDatum = 0;
bool found = ExtractFieldJsonb(jsonbDoc, fieldName, &jsonbDatum, false);
if (!found)
{
return defaultValue;
}
Datum int32Datum = DirectFunctionCall1(jsonb_int4, jsonbDatum);
return DatumGetInt32(int32Datum);
}
/*
* ExtractFieldTextP gets value of fieldName as text* from jsonbDoc, or
* returns NULL if it doesn't exist.
*/
text *
ExtractFieldTextP(Datum jsonbDoc, const char *fieldName)
{
Datum jsonbDatum = 0;
bool found = ExtractFieldJsonb(jsonbDoc, fieldName, &jsonbDatum, true);
if (!found)
{
return NULL;
}
return DatumGetTextP(jsonbDatum);
}
/*
* ExtractFieldJsonbDatum gets value of fieldName from jsonbDoc and puts it
* into result. If not found, returns false. Otherwise, returns true.
*/
bool
ExtractFieldJsonbDatum(Datum jsonbDoc, const char *fieldName, Datum *result)
{
return ExtractFieldJsonb(jsonbDoc, fieldName, result, false);
}