Exemplo n.º 1
0
Datum
jsonb_exists_all(PG_FUNCTION_ARGS)
{
	Jsonb	   *jb = PG_GETARG_JSONB(0);
	ArrayType  *keys = PG_GETARG_ARRAYTYPE_P(1);
	int			i;
	Datum	   *key_datums;
	bool	   *key_nulls;
	int			elem_count;

	deconstruct_array(keys, TEXTOID, -1, false, 'i', &key_datums, &key_nulls,
					  &elem_count);

	for (i = 0; i < elem_count; i++)
	{
		JsonbValue	strVal;

		if (key_nulls[i])
			continue;

		strVal.type = jbvString;
		strVal.val.string.val = VARDATA(key_datums[i]);
		strVal.val.string.len = VARSIZE(key_datums[i]) - VARHDRSZ;

		if (findJsonbValueFromContainer(&jb->root,
										JB_FOBJECT | JB_FARRAY,
										&strVal) == NULL)
			PG_RETURN_BOOL(false);
	}

	PG_RETURN_BOOL(true);
}
Exemplo n.º 2
0
Datum
jsonb_exists(PG_FUNCTION_ARGS)
{
	Jsonb	   *jb = PG_GETARG_JSONB(0);
	text	   *key = PG_GETARG_TEXT_PP(1);
	JsonbValue	kval;
	JsonbValue *v = NULL;

	/*
	 * We only match Object keys (which are naturally always Strings), or
	 * string elements in arrays.  In particular, we do not match non-string
	 * scalar elements.  Existence of a key/element is only considered at the
	 * top level.  No recursion occurs.
	 */
	kval.type = jbvString;
	kval.val.string.val = VARDATA_ANY(key);
	kval.val.string.len = VARSIZE_ANY_EXHDR(key);

	v = findJsonbValueFromContainer(&jb->root,
									JB_FOBJECT | JB_FARRAY,
									&kval);

	PG_RETURN_BOOL(v != NULL);
}
Exemplo n.º 3
0
static bool
recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg)
{
	JsQueryItem		elem;
	bool			res = false;

	check_stack_depth();

	switch(jsq->type) {
		case jqiAnd:
			jsqGetLeftArg(jsq, &elem);
			res = recursiveExecute(&elem, jb, jsqLeftArg);
			if (res == true)
			{
				jsqGetRightArg(jsq, &elem);
				res = recursiveExecute(&elem, jb, jsqLeftArg);
			}
			break;
		case jqiOr:
			jsqGetLeftArg(jsq, &elem);
			res = recursiveExecute(&elem, jb, jsqLeftArg);
			if (res == false)
			{
				jsqGetRightArg(jsq, &elem);
				res = recursiveExecute(&elem, jb, jsqLeftArg);
			}
			break;
		case jqiNot:
			jsqGetArg(jsq, &elem);
			res = !recursiveExecute(&elem, jb, jsqLeftArg);
			break;
		case jqiKey:
			if (JsonbType(jb) == jbvObject) {
				JsonbValue	*v, key;

				key.type = jbvString;
				key.val.string.val = jsqGetString(jsq, &key.val.string.len);

				v = findJsonbValueFromContainer(jb->val.binary.data, JB_FOBJECT, &key);

				if (v != NULL)
				{
					jsqGetNext(jsq, &elem);
					res = recursiveExecute(&elem, v, NULL);
					pfree(v);
				}
			}
			break;
		case jqiCurrent:
			jsqGetNext(jsq, &elem);
			if (JsonbType(jb) == jbvScalar)
			{
				JsonbIterator	*it;
				int32			r;
				JsonbValue		v;

				it = JsonbIteratorInit(jb->val.binary.data);

				r = JsonbIteratorNext(&it, &v, true);
				Assert(r == WJB_BEGIN_ARRAY);
				Assert(v.val.array.rawScalar == 1);
				Assert(v.val.array.nElems == 1);

				r = JsonbIteratorNext(&it, &v, true);
				Assert(r == WJB_ELEM);

				res = recursiveExecute(&elem, &v, jsqLeftArg);
			}
			else
			{
				res = recursiveExecute(&elem, jb, jsqLeftArg);
			}
			break;
		case jqiAny:
			jsqGetNext(jsq, &elem);
			if (recursiveExecute(&elem, jb, NULL))
				res = true;
			else if (jb->type == jbvBinary)
				res = recursiveAny(&elem, jb);
			break;
		case jqiAll:
			jsqGetNext(jsq, &elem);
			if ((res = recursiveExecute(&elem, jb, NULL)) == true)
			{
				if (jb->type == jbvBinary)
					res = recursiveAll(&elem, jb);
			}
			break;
		case jqiAnyArray:
		case jqiAllArray:
			if (JsonbType(jb) == jbvArray)
			{
				JsonbIterator	*it;
				int32			r;
				JsonbValue		v;

				jsqGetNext(jsq, &elem);
				it = JsonbIteratorInit(jb->val.binary.data);

				if (jsq->type == jqiAllArray)
					res = true;

				while((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
				{
					if (r == WJB_ELEM)
					{
						res = recursiveExecute(&elem, &v, NULL);

						if (jsq->type == jqiAnyArray)
						{
							if (res == true)
								break;
						}
						else if (jsq->type == jqiAllArray)
						{
							if (res == false)
								break;
						}
					}
				}
			}
			break;
		case jqiAnyKey:
		case jqiAllKey:
			if (JsonbType(jb) == jbvObject)
			{
				JsonbIterator	*it;
				int32			r;
				JsonbValue		v;

				jsqGetNext(jsq, &elem);
				it = JsonbIteratorInit(jb->val.binary.data);

				if (jsq->type == jqiAllKey)
					res = true;

				while((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
				{
					if (r == WJB_VALUE)
					{
						res = recursiveExecute(&elem, &v, NULL);

						if (jsq->type == jqiAnyKey)
						{
							if (res == true)
								break;
						}
						else if (jsq->type == jqiAllKey)
						{
							if (res == false)
								break;
						}
					}
				}
			}
			break;
		case jqiEqual:
		case jqiIn:
		case jqiLess:
		case jqiGreater:
		case jqiLessOrEqual:
		case jqiGreaterOrEqual:
		case jqiContains:
		case jqiContained:
		case jqiOverlap:
			jsqGetArg(jsq, &elem);
			res = executeExpr(&elem, jsq->type, jb, jsqLeftArg);
			break;
		case jqiLength:
			jsqGetNext(jsq, &elem);
			res = recursiveExecute(&elem, jb, jsq);
			break;
		case jqiIs:
			if (JsonbType(jb) == jbvScalar)
			{
				JsonbIterator	*it;
				int32			r;
				JsonbValue		v;

				it = JsonbIteratorInit(jb->val.binary.data);

				r = JsonbIteratorNext(&it, &v, true);
				Assert(r == WJB_BEGIN_ARRAY);
				Assert(v.val.array.rawScalar == 1);
				Assert(v.val.array.nElems == 1);

				r = JsonbIteratorNext(&it, &v, true);
				Assert(r == WJB_ELEM);

				res = (jsqGetIsType(jsq) == JsonbType(&v));
			}
			else
			{
				res = (jsqGetIsType(jsq) == JsonbType(jb));
			}
			break;
		default:
			elog(ERROR,"Wrong state: %d", jsq->type);
	}

	return res;
}