if (SOFT_ERROR_OCCURRED(escontext)) return (Datum) 0;
if (!jsonpath)
ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for type %s: \"%s\"", "jsonpath",
in)));
initStringInfo(&buf);
enlargeStringInfo(&buf, 4 * len /* estimation */ );
appendStringInfoSpaces(&buf, JSONPATH_HDRSZ);
if (!flattenJsonPathParseItem(&buf, NULL, escontext,
jsonpath->expr, 0, false)) return (Datum) 0;
res = (JsonPath *) buf.data;
SET_VARSIZE(res, buf.len);
res->header = JSONPATH_VERSION; if (jsonpath->lax)
res->header |= JSONPATH_LAX;
/* *Reservespacefornextitempointer.Actualvaluewillberecorded *later,afternextandchildrenitemsprocessing.
*/
next = reserveSpaceForItemPointer(buf);
switch (item->type)
{ case jpiString: case jpiVariable: case jpiKey:
appendBinaryStringInfo(buf, &item->value.string.len, sizeof(item->value.string.len));
appendBinaryStringInfo(buf, item->value.string.val,
item->value.string.len);
appendStringInfoChar(buf, '\0'); break; case jpiNumeric:
appendBinaryStringInfo(buf, item->value.numeric,
VARSIZE(item->value.numeric)); break; case jpiBool:
appendBinaryStringInfo(buf, &item->value.boolean, sizeof(item->value.boolean)); break; case jpiAnd: case jpiOr: case jpiEqual: case jpiNotEqual: case jpiLess: case jpiGreater: case jpiLessOrEqual: case jpiGreaterOrEqual: case jpiAdd: case jpiSub: case jpiMul: case jpiDiv: case jpiMod: case jpiStartsWith: case jpiDecimal:
{ /* *First,reserveplaceforleft/rightarg'spositions,then *recordbothargsandsetsactualpositioninreserved *places.
*/
int32 left = reserveSpaceForItemPointer(buf);
int32 right = reserveSpaceForItemPointer(buf);
if (!flattenJsonPathParseItem(buf, &chld, escontext,
item->value.like_regex.expr,
nestingLevel,
insideArraySubscript)) returnfalse;
*(int32 *) (buf->data + offs) = chld - pos;
} break; case jpiFilter:
argNestingLevel++; /* FALLTHROUGH */ case jpiIsUnknown: case jpiNot: case jpiPlus: case jpiMinus: case jpiExists: case jpiDatetime: case jpiTime: case jpiTimeTz: case jpiTimestamp: case jpiTimestampTz:
{
int32 arg = reserveSpaceForItemPointer(buf);
if (!item->value.arg)
chld = pos; elseif (!flattenJsonPathParseItem(buf, &chld, escontext,
item->value.arg,
nestingLevel + argNestingLevel,
insideArraySubscript)) returnfalse;
*(int32 *) (buf->data + arg) = chld - pos;
} break; case jpiNull: break; case jpiRoot: break; case jpiAnyArray: case jpiAnyKey: break; case jpiCurrent: if (nestingLevel <= 0)
ereturn(escontext, false,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("@ is not allowed in root expressions"))); break; case jpiLast: if (!insideArraySubscript)
ereturn(escontext, false,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("LAST is allowed only in array subscripts"))); break; case jpiIndexArray:
{
int32 nelems = item->value.array.nelems; int offset; int i;
ppos[0] = frompos;
ppos[1] = topos;
}
} break; case jpiAny:
appendBinaryStringInfo(buf,
&item->value.anybounds.first, sizeof(item->value.anybounds.first));
appendBinaryStringInfo(buf,
&item->value.anybounds.last, sizeof(item->value.anybounds.last)); break; case jpiType: case jpiSize: case jpiAbs: case jpiFloor: case jpiCeiling: case jpiDouble: case jpiKeyValue: case jpiBigint: case jpiBoolean: case jpiDate: case jpiInteger: case jpiNumber: case jpiStringFunc: break; default:
elog(ERROR, "unrecognized jsonpath item type: %d", item->type);
}
if (v->content.like_regex.flags)
{
appendStringInfoString(buf, " flag \"");
if (v->content.like_regex.flags & JSP_REGEX_ICASE)
appendStringInfoChar(buf, 'i'); if (v->content.like_regex.flags & JSP_REGEX_DOTALL)
appendStringInfoChar(buf, 's'); if (v->content.like_regex.flags & JSP_REGEX_MLINE)
appendStringInfoChar(buf, 'm'); if (v->content.like_regex.flags & JSP_REGEX_WSPACE)
appendStringInfoChar(buf, 'x'); if (v->content.like_regex.flags & JSP_REGEX_QUOTE)
appendStringInfoChar(buf, 'q');
appendStringInfoChar(buf, '"');
}
if (printBracketes)
appendStringInfoChar(buf, ')'); break; case jpiBigint:
appendStringInfoString(buf, ".bigint()"); break; case jpiBoolean:
appendStringInfoString(buf, ".boolean()"); break; case jpiDate:
appendStringInfoString(buf, ".date()"); break; case jpiDecimal:
appendStringInfoString(buf, ".decimal("); if (v->content.args.left)
{
jspGetLeftArg(v, &elem);
printJsonPathItem(buf, &elem, false, false);
} if (v->content.args.right)
{
appendStringInfoChar(buf, ',');
jspGetRightArg(v, &elem);
printJsonPathItem(buf, &elem, false, false);
}
appendStringInfoChar(buf, ')'); break; case jpiInteger:
appendStringInfoString(buf, ".integer()"); break; case jpiNumber:
appendStringInfoString(buf, ".number()"); break; case jpiStringFunc:
appendStringInfoString(buf, ".string()"); break; case jpiTime:
appendStringInfoString(buf, ".time("); if (v->content.arg)
{
jspGetArg(v, &elem);
printJsonPathItem(buf, &elem, false, false);
}
appendStringInfoChar(buf, ')'); break; case jpiTimeTz:
appendStringInfoString(buf, ".time_tz("); if (v->content.arg)
{
jspGetArg(v, &elem);
printJsonPathItem(buf, &elem, false, false);
}
appendStringInfoChar(buf, ')'); break; case jpiTimestamp:
appendStringInfoString(buf, ".timestamp("); if (v->content.arg)
{
jspGetArg(v, &elem);
printJsonPathItem(buf, &elem, false, false);
}
appendStringInfoChar(buf, ')'); break; case jpiTimestampTz:
appendStringInfoString(buf, ".timestamp_tz("); if (v->content.arg)
{
jspGetArg(v, &elem);
printJsonPathItem(buf, &elem, false, false);
}
appendStringInfoChar(buf, ')'); break; default:
elog(ERROR, "unrecognized jsonpath item type: %d", v->type);
}
if (jspGetNext(v, &elem))
printJsonPathItem(buf, &elem, true, true);
}
constchar *
jspOperationName(JsonPathItemType type)
{ switch (type)
{ case jpiAnd: return"&&"; case jpiOr: return"||"; case jpiEqual: return"=="; case jpiNotEqual: return"!="; case jpiLess: return"<"; case jpiGreater: return">"; case jpiLessOrEqual: return"<="; case jpiGreaterOrEqual: return">="; case jpiAdd: case jpiPlus: return"+"; case jpiSub: case jpiMinus: return"-"; case jpiMul: return"*"; case jpiDiv: return"/"; case jpiMod: return"%"; case jpiType: return"type"; case jpiSize: return"size"; case jpiAbs: return"abs"; case jpiFloor: return"floor"; case jpiCeiling: return"ceiling"; case jpiDouble: return"double"; case jpiDatetime: return"datetime"; case jpiKeyValue: return"keyvalue"; case jpiStartsWith: return"starts with"; case jpiLikeRegex: return"like_regex"; case jpiBigint: return"bigint"; case jpiBoolean: return"boolean"; case jpiDate: return"date"; case jpiDecimal: return"decimal"; case jpiInteger: return"integer"; case jpiNumber: return"number"; case jpiStringFunc: return"string"; case jpiTime: return"time"; case jpiTimeTz: return"time_tz"; case jpiTimestamp: return"timestamp"; case jpiTimestampTz: return"timestamp_tz"; default:
elog(ERROR, "unrecognized jsonpath item type: %d", type); return NULL;
}
}
staticint
operationPriority(JsonPathItemType op)
{ switch (op)
{ case jpiOr: return0; case jpiAnd: return1; case jpiEqual: case jpiNotEqual: case jpiLess: case jpiGreater: case jpiLessOrEqual: case jpiGreaterOrEqual: case jpiStartsWith: return2; case jpiAdd: case jpiSub: return3; case jpiMul: case jpiDiv: case jpiMod: return4; case jpiPlus: case jpiMinus: return5; default: return6;
}
}
/******************* Support functions for JsonPath *************************/
switch (v->type)
{ case jpiNull: case jpiRoot: case jpiCurrent: case jpiAnyArray: case jpiAnyKey: case jpiType: case jpiSize: case jpiAbs: case jpiFloor: case jpiCeiling: case jpiDouble: case jpiKeyValue: case jpiLast: case jpiBigint: case jpiBoolean: case jpiDate: case jpiInteger: case jpiNumber: case jpiStringFunc: break; case jpiString: case jpiKey: case jpiVariable:
read_int32(v->content.value.datalen, base, pos); /* FALLTHROUGH */ case jpiNumeric: case jpiBool:
v->content.value.data = base + pos; break; case jpiAnd: case jpiOr: case jpiEqual: case jpiNotEqual: case jpiLess: case jpiGreater: case jpiLessOrEqual: case jpiGreaterOrEqual: case jpiAdd: case jpiSub: case jpiMul: case jpiDiv: case jpiMod: case jpiStartsWith: case jpiDecimal:
read_int32(v->content.args.left, base, pos);
read_int32(v->content.args.right, base, pos); break; case jpiNot: case jpiIsUnknown: case jpiExists: case jpiPlus: case jpiMinus: case jpiFilter: case jpiDatetime: case jpiTime: case jpiTimeTz: case jpiTimestamp: case jpiTimestampTz:
read_int32(v->content.arg, base, pos); break; case jpiIndexArray:
read_int32(v->content.array.nelems, base, pos);
read_int32_n(v->content.array.elems, base, pos,
v->content.array.nelems * 2); break; case jpiAny:
read_int32(v->content.anybounds.first, base, pos);
read_int32(v->content.anybounds.last, base, pos); break; case jpiLikeRegex:
read_int32(v->content.like_regex.flags, base, pos);
read_int32(v->content.like_regex.expr, base, pos);
read_int32(v->content.like_regex.patternlen, base, pos);
v->content.like_regex.pattern = base + pos; break; default:
elog(ERROR, "unrecognized jsonpath item type: %d", v->type);
}
}
/* Context for jspIsMutableWalker() */ struct JsonPathMutableContext
{
List *varnames; /* list of variable names */
List *varexprs; /* list of variable expressions */ enum JsonPathDatatypeStatus current; /* status of @ item */ bool lax; /* jsonpath is lax or strict */ boolmutable; /* resulting mutability status */
};
switch (exprType(varexpr))
{ case DATEOID: case TIMEOID: case TIMESTAMPOID:
status = jpdsDateTimeNonZoned; break;
case TIMETZOID: case TIMESTAMPTZOID:
status = jpdsDateTimeZoned; break;
default:
status = jpdsNonDateTime; break;
}
break;
} break;
}
case jpiEqual: case jpiNotEqual: case jpiLess: case jpiGreater: case jpiLessOrEqual: case jpiGreaterOrEqual:
Assert(status == jpdsNonDateTime);
jspGetLeftArg(jpi, &arg);
leftStatus = jspIsMutableWalker(&arg, cxt);
case jpiNot: case jpiIsUnknown: case jpiExists: case jpiPlus: case jpiMinus:
Assert(status == jpdsNonDateTime);
jspGetArg(jpi, &arg);
jspIsMutableWalker(&arg, cxt); break;
case jpiAnd: case jpiOr: case jpiAdd: case jpiSub: case jpiMul: case jpiDiv: case jpiMod: case jpiStartsWith:
Assert(status == jpdsNonDateTime);
jspGetLeftArg(jpi, &arg);
jspIsMutableWalker(&arg, cxt);
jspGetRightArg(jpi, &arg);
jspIsMutableWalker(&arg, cxt); break;
case jpiIndexArray: for (int i = 0; i < jpi->content.array.nelems; i++)
{
JsonPathItem from;
JsonPathItem to;
if (jspGetArraySubscript(jpi, &from, &to, i))
jspIsMutableWalker(&to, cxt);
/* literals */ case jpiNull: case jpiString: case jpiNumeric: case jpiBool: break; /* accessors */ case jpiKey: case jpiAnyKey: /* special items */ case jpiSubscript: case jpiLast: /* item methods */ case jpiType: case jpiSize: case jpiAbs: case jpiFloor: case jpiCeiling: case jpiDouble: case jpiKeyValue: case jpiBigint: case jpiBoolean: case jpiDecimal: case jpiInteger: case jpiNumber: case jpiStringFunc:
status = jpdsNonDateTime; break;
case jpiTime: case jpiDate: case jpiTimestamp:
status = jpdsDateTimeNonZoned;
cxt->mutable = true; break;
case jpiTimeTz: case jpiTimestampTz:
status = jpdsDateTimeNonZoned;
cxt->mutable = true; break;
}
if (!jspGetNext(jpi, &next)) break;
jpi = &next;
}
return status;
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.23 Sekunden
(vorverarbeitet am 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.