v5-0001-Implement-jsonpath-.number-.decimal-precision-sca.patch

application/octet-stream

Filename: v5-0001-Implement-jsonpath-.number-.decimal-precision-sca.patch
Type: application/octet-stream
Part: 2
Message: Re: More new SQL/JSON item methods

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: format-patch
Series: patch v5-0001
Subject: Implement jsonpath .number(), .decimal([precision [, scale]]), .bigint(), and .integer() methods
File+
doc/src/sgml/func.sgml 56 0
src/backend/catalog/sql_features.txt 5 5
src/backend/utils/adt/jsonpath.c 49 3
src/backend/utils/adt/jsonpath_exec.c 266 0
src/backend/utils/adt/jsonpath_gram.y 43 2
src/backend/utils/adt/jsonpath_scan.l 4 0
src/include/utils/jsonpath.h 4 0
src/test/regress/expected/jsonb_jsonpath.out 534 0
src/test/regress/expected/jsonpath.out 12 0
src/test/regress/sql/jsonb_jsonpath.sql 133 0
src/test/regress/sql/jsonpath.sql 2 0
From 403ab92764d17cf77ddbc94f096655c7242a8a1a Mon Sep 17 00:00:00 2001
From: Jeevan Chalke <jeevan.chalke@enterprisedb.com>
Date: Wed, 10 Jan 2024 13:14:48 +0530
Subject: [PATCH v5 1/3] Implement jsonpath .number(), .decimal([precision [,
 scale]]), .bigint(), and .integer() methods

This commit implements jsonpath .number(), .decimal() with optional
precision and scale, .bigint(), and .integer() methods.  The JSON
string or a numeric value is converted to the numeric, numeric,
bigint, and int4 type representation respectively.  If precision and
scale are provided for .decimal(), then it is converted to the
equivalent numerictypmod and applied to the numeric number.

Jeevan Chalke.
---
 doc/src/sgml/func.sgml                       |  56 +++
 src/backend/catalog/sql_features.txt         |  10 +-
 src/backend/utils/adt/jsonpath.c             |  52 ++-
 src/backend/utils/adt/jsonpath_exec.c        | 266 +++++++++++++
 src/backend/utils/adt/jsonpath_gram.y        |  45 ++-
 src/backend/utils/adt/jsonpath_scan.l        |   4 +
 src/include/utils/jsonpath.h                 |   4 +
 src/test/regress/expected/jsonb_jsonpath.out | 534 +++++++++++++++++++++++++++
 src/test/regress/expected/jsonpath.out       |  12 +
 src/test/regress/sql/jsonb_jsonpath.sql      | 133 +++++++
 src/test/regress/sql/jsonpath.sql            |   2 +
 11 files changed, 1108 insertions(+), 10 deletions(-)

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index de78d58..b273af6 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -17733,6 +17733,62 @@ strict $.**.HR
 
       <row>
        <entry role="func_table_entry"><para role="func_signature">
+        <replaceable>value</replaceable> <literal>.</literal> <literal>number()</literal>
+        <returnvalue><replaceable>numeric</replaceable></returnvalue>
+       </para>
+       <para>
+        Numeric value converted from a JSON number or string
+       </para>
+       <para>
+        <literal>jsonb_path_query('{"len": "123.45"}', '$.len.number()')</literal>
+        <returnvalue>123.45</returnvalue>
+       </para></entry>
+      </row>
+
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <replaceable>value</replaceable> <literal>.</literal> <literal>decimal( [ <replaceable>precision</replaceable> [ , <replaceable>scale</replaceable> ] ] )</literal>
+        <returnvalue><replaceable>decimal</replaceable></returnvalue>
+       </para>
+       <para>
+        Rounded decimal value converted from a JSON number or string. <literal>precision</literal> and <literal>scale</literal> must be integer values.
+       </para>
+       <para>
+        <literal>jsonb_path_query('1234.5678', '$.decimal(6, 2)')</literal>
+        <returnvalue>1234.57</returnvalue>
+       </para></entry>
+      </row>
+
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <replaceable>value</replaceable> <literal>.</literal> <literal>bigint()</literal>
+        <returnvalue><replaceable>bigint</replaceable></returnvalue>
+       </para>
+       <para>
+        Big integer value converted from a JSON number or string
+       </para>
+       <para>
+        <literal>jsonb_path_query('{"len": "9876543219"}', '$.len.bigint()')</literal>
+        <returnvalue>9876543219</returnvalue>
+       </para></entry>
+      </row>
+
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <replaceable>value</replaceable> <literal>.</literal> <literal>integer()</literal>
+        <returnvalue><replaceable>integer</replaceable></returnvalue>
+       </para>
+       <para>
+        Integer value converted from a JSON number or string
+       </para>
+       <para>
+        <literal>jsonb_path_query('{"len": "12345"}', '$.len.integer()')</literal>
+        <returnvalue>12345</returnvalue>
+       </para></entry>
+      </row>
+
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
         <replaceable>string</replaceable> <literal>.</literal> <literal>datetime()</literal>
         <returnvalue><replaceable>datetime_type</replaceable></returnvalue>
         (see note)
diff --git a/src/backend/catalog/sql_features.txt b/src/backend/catalog/sql_features.txt
index 80c40ea..6a76579 100644
--- a/src/backend/catalog/sql_features.txt
+++ b/src/backend/catalog/sql_features.txt
@@ -574,13 +574,13 @@ T861	SQL/JSON simplified accessor: case-sensitive JSON member accessor			NO
 T862	SQL/JSON simplified accessor: wildcard member accessor			NO	
 T863	SQL/JSON simplified accessor: single-quoted string literal as member accessor			NO	
 T864	SQL/JSON simplified accessor			NO	
-T865	SQL/JSON item method: bigint()			NO	
+T865	SQL/JSON item method: bigint()			YES	
 T866	SQL/JSON item method: boolean()			NO	
 T867	SQL/JSON item method: date()			NO	
-T868	SQL/JSON item method: decimal()			NO	
-T869	SQL/JSON item method: decimal() with precision and scale			NO	
-T870	SQL/JSON item method: integer()			NO	
-T871	SQL/JSON item method: number()			NO	
+T868	SQL/JSON item method: decimal()			YES	
+T869	SQL/JSON item method: decimal() with precision and scale			YES	
+T870	SQL/JSON item method: integer()			YES	
+T871	SQL/JSON item method: number()			YES	
 T872	SQL/JSON item method: string()			NO	
 T873	SQL/JSON item method: time()			NO	
 T874	SQL/JSON item method: time_tz()			NO	
diff --git a/src/backend/utils/adt/jsonpath.c b/src/backend/utils/adt/jsonpath.c
index d02c03e..85b0b07 100644
--- a/src/backend/utils/adt/jsonpath.c
+++ b/src/backend/utils/adt/jsonpath.c
@@ -295,6 +295,7 @@ flattenJsonPathParseItem(StringInfo buf, int *result, struct Node *escontext,
 		case jpiDiv:
 		case jpiMod:
 		case jpiStartsWith:
+		case jpiDecimal:
 			{
 				/*
 				 * First, reserve place for left/right arg's positions, then
@@ -444,6 +445,9 @@ flattenJsonPathParseItem(StringInfo buf, int *result, struct Node *escontext,
 		case jpiCeiling:
 		case jpiDouble:
 		case jpiKeyValue:
+		case jpiNumber:
+		case jpiBigint:
+		case jpiInteger:
 			break;
 		default:
 			elog(ERROR, "unrecognized jsonpath item type: %d", item->type);
@@ -742,6 +746,30 @@ printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey,
 			if (printBracketes)
 				appendStringInfoChar(buf, ')');
 			break;
+		case jpiNumber:
+			appendStringInfoString(buf, ".number()");
+			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 jpiBigint:
+			appendStringInfoString(buf, ".bigint()");
+			break;
+		case jpiInteger:
+			appendStringInfoString(buf, ".integer()");
+			break;
 		default:
 			elog(ERROR, "unrecognized jsonpath item type: %d", v->type);
 	}
@@ -803,6 +831,14 @@ jspOperationName(JsonPathItemType type)
 			return "starts with";
 		case jpiLikeRegex:
 			return "like_regex";
+		case jpiNumber:
+			return "number";
+		case jpiDecimal:
+			return "decimal";
+		case jpiBigint:
+			return "bigint";
+		case jpiInteger:
+			return "integer";
 		default:
 			elog(ERROR, "unrecognized jsonpath item type: %d", type);
 			return NULL;
@@ -899,6 +935,9 @@ jspInitByBuffer(JsonPathItem *v, char *base, int32 pos)
 		case jpiDouble:
 		case jpiKeyValue:
 		case jpiLast:
+		case jpiNumber:
+		case jpiBigint:
+		case jpiInteger:
 			break;
 		case jpiString:
 		case jpiKey:
@@ -923,6 +962,7 @@ jspInitByBuffer(JsonPathItem *v, char *base, int32 pos)
 		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;
@@ -1015,7 +1055,11 @@ jspGetNext(JsonPathItem *v, JsonPathItem *a)
 			   v->type == jpiKeyValue ||
 			   v->type == jpiLast ||
 			   v->type == jpiStartsWith ||
-			   v->type == jpiLikeRegex);
+			   v->type == jpiLikeRegex ||
+			   v->type == jpiNumber ||
+			   v->type == jpiDecimal ||
+			   v->type == jpiBigint ||
+			   v->type == jpiInteger);
 
 		if (a)
 			jspInitByBuffer(a, v->base, v->nextPos);
@@ -1041,7 +1085,8 @@ jspGetLeftArg(JsonPathItem *v, JsonPathItem *a)
 		   v->type == jpiMul ||
 		   v->type == jpiDiv ||
 		   v->type == jpiMod ||
-		   v->type == jpiStartsWith);
+		   v->type == jpiStartsWith ||
+		   v->type == jpiDecimal);
 
 	jspInitByBuffer(a, v->base, v->content.args.left);
 }
@@ -1062,7 +1107,8 @@ jspGetRightArg(JsonPathItem *v, JsonPathItem *a)
 		   v->type == jpiMul ||
 		   v->type == jpiDiv ||
 		   v->type == jpiMod ||
-		   v->type == jpiStartsWith);
+		   v->type == jpiStartsWith ||
+		   v->type == jpiDecimal);
 
 	jspInitByBuffer(a, v->base, v->content.args.right);
 }
diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c
index ac16f5c..a361c45 100644
--- a/src/backend/utils/adt/jsonpath_exec.c
+++ b/src/backend/utils/adt/jsonpath_exec.c
@@ -1110,6 +1110,272 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
 			}
 			break;
 
+		case jpiNumber:
+		case jpiDecimal:
+			{
+				JsonbValue	jbv;
+				Numeric		num;
+				char	   *numstr = NULL;
+
+				if (unwrap && JsonbType(jb) == jbvArray)
+					return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
+														false);
+
+				if (jb->type == jbvNumeric)
+				{
+					num = jb->val.numeric;
+					if (numeric_is_nan(num) || numeric_is_inf(num))
+						RETURN_ERROR(ereport(ERROR,
+											 (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
+											  errmsg("numeric argument of jsonpath item method .%s() is out of range for type decimal or number",
+													 jspOperationName(jsp->type)))));
+
+					if (jsp->type == jpiDecimal)
+						numstr = DatumGetCString(DirectFunctionCall1(numeric_out,
+																	 NumericGetDatum(num)));
+					res = jperOk;
+				}
+				else if (jb->type == jbvString)
+				{
+					/* cast string as number */
+					Datum		datum;
+					bool		noerr;
+					ErrorSaveContext escontext = {T_ErrorSaveContext};
+
+					numstr = pnstrdup(jb->val.string.val, jb->val.string.len);
+
+					noerr = DirectInputFunctionCallSafe(numeric_in, numstr,
+														InvalidOid, -1,
+														(Node *) &escontext,
+														&datum);
+
+					if (!noerr || escontext.error_occurred)
+						RETURN_ERROR(ereport(ERROR,
+											 (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
+											  errmsg("string argument of jsonpath item method .%s() is not a valid representation of a decimal or number",
+													 jspOperationName(jsp->type)))));
+
+					num = DatumGetNumeric(datum);
+					if (numeric_is_nan(num) || numeric_is_inf(num))
+						RETURN_ERROR(ereport(ERROR,
+											 (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
+											  errmsg("string argument of jsonpath item method .%s() is not a valid representation of a decimal or number",
+													 jspOperationName(jsp->type)))));
+
+					res = jperOk;
+				}
+
+				if (res == jperNotFound)
+					RETURN_ERROR(ereport(ERROR,
+										 (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
+										  errmsg("jsonpath item method .%s() can only be applied to a string or numeric value",
+												 jspOperationName(jsp->type)))));
+
+				/*
+				 * If we have arguments, then they must be the precision and
+				 * optional scale used in .decimal().  Convert them to the
+				 * typmod equivalent and then truncate the numeric value per
+				 * this typmod details.
+				 */
+				if (jsp->type == jpiDecimal && jsp->content.args.left)
+				{
+					Datum		numdatum;
+					Datum		dtypmod;
+					int32		precision;
+					int32		scale = 0;
+					bool		have_error;
+					bool		noerr;
+					ArrayType  *arrtypmod;
+					Datum		datums[2];
+					char		pstr[12];	/* sign, 10 digits and '\0' */
+					char		sstr[12];	/* sign, 10 digits and '\0' */
+					ErrorSaveContext escontext = {T_ErrorSaveContext};
+
+					jspGetLeftArg(jsp, &elem);
+					if (elem.type != jpiNumeric)
+						elog(ERROR, "invalid jsonpath item type for .decimal() precision");
+
+					precision = numeric_int4_opt_error(jspGetNumeric(&elem),
+													   &have_error);
+					if (have_error)
+						RETURN_ERROR(ereport(ERROR,
+											 (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
+											  errmsg("precision of jsonpath item method .%s() is out of range for type integer",
+													 jspOperationName(jsp->type)))));
+
+					if (jsp->content.args.right)
+					{
+						jspGetRightArg(jsp, &elem);
+						if (elem.type != jpiNumeric)
+							elog(ERROR, "invalid jsonpath item type for .decimal() scale");
+
+						scale = numeric_int4_opt_error(jspGetNumeric(&elem),
+													   &have_error);
+						if (have_error)
+							RETURN_ERROR(ereport(ERROR,
+												 (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
+												  errmsg("scale of jsonpath item method .%s() is out of range for type integer",
+														 jspOperationName(jsp->type)))));
+					}
+
+					/*
+					 * numerictypmodin() takes the precision and scale in the
+					 * form of CString arrays.
+					 */
+					pg_ltoa(precision, pstr);
+					datums[0] = CStringGetDatum(pstr);
+					pg_ltoa(scale, sstr);
+					datums[1] = CStringGetDatum(sstr);
+					arrtypmod = construct_array_builtin(datums, 2, CSTRINGOID);
+
+					dtypmod = DirectFunctionCall1(numerictypmodin,
+												  PointerGetDatum(arrtypmod));
+
+					/* Convert numstr to Numeric with typmod */
+					Assert(numstr != NULL);
+					noerr = DirectInputFunctionCallSafe(numeric_in, numstr,
+														InvalidOid, dtypmod,
+														(Node *) &escontext,
+														&numdatum);
+
+					if (!noerr || escontext.error_occurred)
+						RETURN_ERROR(ereport(ERROR,
+											 (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
+											  errmsg("string argument of jsonpath item method .%s() is not a valid representation of a decimal or number",
+													 jspOperationName(jsp->type)))));
+
+					num = DatumGetNumeric(numdatum);
+					pfree(arrtypmod);
+				}
+
+				jb = &jbv;
+				jb->type = jbvNumeric;
+				jb->val.numeric = num;
+
+				res = executeNextItem(cxt, jsp, NULL, jb, found, true);
+			}
+			break;
+
+		case jpiBigint:
+			{
+				JsonbValue	jbv;
+				Datum		datum;
+
+				if (unwrap && JsonbType(jb) == jbvArray)
+					return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
+														false);
+
+				if (jb->type == jbvNumeric)
+				{
+					bool		have_error;
+					int64		val;
+
+					val = numeric_int8_opt_error(jb->val.numeric, &have_error);
+					if (have_error)
+						RETURN_ERROR(ereport(ERROR,
+											 (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
+											  errmsg("numeric argument of jsonpath item method .%s() is out of range for type bigint",
+													 jspOperationName(jsp->type)))));
+
+					datum = Int64GetDatum(val);
+					res = jperOk;
+				}
+				else if (jb->type == jbvString)
+				{
+					/* cast string as bigint */
+					char	   *tmp = pnstrdup(jb->val.string.val,
+											   jb->val.string.len);
+					ErrorSaveContext escontext = {T_ErrorSaveContext};
+					bool		noerr;
+
+					noerr = DirectInputFunctionCallSafe(int8in, tmp,
+														InvalidOid, -1,
+														(Node *) &escontext,
+														&datum);
+
+					if (!noerr || escontext.error_occurred)
+						RETURN_ERROR(ereport(ERROR,
+											 (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
+											  errmsg("string argument of jsonpath item method .%s() is not a valid representation of a big integer",
+													 jspOperationName(jsp->type)))));
+					res = jperOk;
+				}
+
+				if (res == jperNotFound)
+					RETURN_ERROR(ereport(ERROR,
+										 (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
+										  errmsg("jsonpath item method .%s() can only be applied to a string or numeric value",
+												 jspOperationName(jsp->type)))));
+
+				jb = &jbv;
+				jb->type = jbvNumeric;
+				jb->val.numeric = DatumGetNumeric(DirectFunctionCall1(int8_numeric,
+																	  datum));
+
+				res = executeNextItem(cxt, jsp, NULL, jb, found, true);
+			}
+			break;
+
+		case jpiInteger:
+			{
+				JsonbValue	jbv;
+				Datum		datum;
+
+				if (unwrap && JsonbType(jb) == jbvArray)
+					return executeItemUnwrapTargetArray(cxt, jsp, jb, found,
+														false);
+
+				if (jb->type == jbvNumeric)
+				{
+					bool		have_error;
+					int32		val;
+
+					val = numeric_int4_opt_error(jb->val.numeric, &have_error);
+					if (have_error)
+						RETURN_ERROR(ereport(ERROR,
+											 (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
+											  errmsg("numeric argument of jsonpath item method .%s() is out of range for type integer",
+													 jspOperationName(jsp->type)))));
+
+					datum = Int32GetDatum(val);
+					res = jperOk;
+				}
+				else if (jb->type == jbvString)
+				{
+					/* cast string as integer */
+					char	   *tmp = pnstrdup(jb->val.string.val,
+											   jb->val.string.len);
+					ErrorSaveContext escontext = {T_ErrorSaveContext};
+					bool		noerr;
+
+					noerr = DirectInputFunctionCallSafe(int4in, tmp,
+														InvalidOid, -1,
+														(Node *) &escontext,
+														&datum);
+
+					if (!noerr || escontext.error_occurred)
+						RETURN_ERROR(ereport(ERROR,
+											 (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
+											  errmsg("string argument of jsonpath item method .%s() is not a valid representation of an integer",
+													 jspOperationName(jsp->type)))));
+					res = jperOk;
+				}
+
+				if (res == jperNotFound)
+					RETURN_ERROR(ereport(ERROR,
+										 (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
+										  errmsg("jsonpath item method .%s() can only be applied to a string or numeric value",
+												 jspOperationName(jsp->type)))));
+
+				jb = &jbv;
+				jb->type = jbvNumeric;
+				jb->val.numeric = DatumGetNumeric(DirectFunctionCall1(int4_numeric,
+																	  datum));
+
+				res = executeNextItem(cxt, jsp, NULL, jb, found, true);
+			}
+			break;
+
 		default:
 			elog(ERROR, "unrecognized jsonpath item type: %d", jsp->type);
 	}
diff --git a/src/backend/utils/adt/jsonpath_gram.y b/src/backend/utils/adt/jsonpath_gram.y
index 5e4eb52..24c3104 100644
--- a/src/backend/utils/adt/jsonpath_gram.y
+++ b/src/backend/utils/adt/jsonpath_gram.y
@@ -81,6 +81,7 @@ static bool makeItemLikeRegex(JsonPathParseItem *expr,
 %token	<str>		LESS_P LESSEQUAL_P EQUAL_P NOTEQUAL_P GREATEREQUAL_P GREATER_P
 %token	<str>		ANY_P STRICT_P LAX_P LAST_P STARTS_P WITH_P LIKE_REGEX_P FLAG_P
 %token	<str>		ABS_P SIZE_P TYPE_P FLOOR_P DOUBLE_P CEILING_P KEYVALUE_P
+%token	<str>		NUMBER_P DECIMAL_P BIGINT_P INTEGER_P
 %token	<str>		DATETIME_P
 
 %type	<result>	result
@@ -88,9 +89,9 @@ static bool makeItemLikeRegex(JsonPathParseItem *expr,
 %type	<value>		scalar_value path_primary expr array_accessor
 					any_path accessor_op key predicate delimited_predicate
 					index_elem starts_with_initial expr_or_predicate
-					datetime_template opt_datetime_template
+					datetime_template opt_datetime_template csv_elem
 
-%type	<elems>		accessor_expr
+%type	<elems>		accessor_expr csv_list opt_csv_list
 
 %type	<indexs>	index_list
 
@@ -251,6 +252,39 @@ accessor_op:
 	| '.' DATETIME_P '(' opt_datetime_template ')'
 									{ $$ = makeItemUnary(jpiDatetime, $4); }
 	| '?' '(' predicate ')'			{ $$ = makeItemUnary(jpiFilter, $3); }
+	| '.' DECIMAL_P '(' opt_csv_list ')'
+	{
+		if (list_length($4) == 0)
+			$$ = makeItemBinary(jpiDecimal, NULL, NULL);
+		else if (list_length($4) == 1)
+			$$ = makeItemBinary(jpiDecimal, linitial($4), NULL);
+		else if (list_length($4) == 2)
+			$$ = makeItemBinary(jpiDecimal, linitial($4), lsecond($4));
+		else
+			ereturn(escontext, false,
+					(errcode(ERRCODE_SYNTAX_ERROR),
+					 errmsg("invalid input syntax for type %s", "jsonpath"),
+					 errdetail(".decimal() can only have an optional precision[,scale].")));
+	}
+	;
+
+csv_elem:
+	INT_P
+		{ $$ = makeItemNumeric(&$1); }
+	| '+' INT_P %prec UMINUS
+		{ $$ = makeItemUnary(jpiPlus, makeItemNumeric(&$2)); }
+	| '-' INT_P %prec UMINUS
+		{ $$ = makeItemUnary(jpiMinus, makeItemNumeric(&$2)); }
+	;
+
+csv_list:
+	csv_elem						{ $$ = list_make1($1); }
+	| csv_list ',' csv_elem			{ $$ = lappend($1, $3); }
+	;
+
+opt_csv_list:
+	csv_list						{ $$ = $1; }
+	| /* EMPTY */					{ $$ = NULL; }
 	;
 
 datetime_template:
@@ -291,6 +325,10 @@ key_name:
 	| WITH_P
 	| LIKE_REGEX_P
 	| FLAG_P
+	| NUMBER_P
+	| DECIMAL_P
+	| BIGINT_P
+	| INTEGER_P
 	;
 
 method:
@@ -301,6 +339,9 @@ method:
 	| DOUBLE_P						{ $$ = jpiDouble; }
 	| CEILING_P						{ $$ = jpiCeiling; }
 	| KEYVALUE_P					{ $$ = jpiKeyValue; }
+	| NUMBER_P						{ $$ = jpiNumber; }
+	| BIGINT_P						{ $$ = jpiBigint; }
+	| INTEGER_P						{ $$ = jpiInteger; }
 	;
 %%
 
diff --git a/src/backend/utils/adt/jsonpath_scan.l b/src/backend/utils/adt/jsonpath_scan.l
index 757cd95..07d229d 100644
--- a/src/backend/utils/adt/jsonpath_scan.l
+++ b/src/backend/utils/adt/jsonpath_scan.l
@@ -410,11 +410,15 @@ static const JsonPathKeyword keywords[] = {
 	{ 4, false,	WITH_P,		"with"},
 	{ 5, true,	FALSE_P,	"false"},
 	{ 5, false,	FLOOR_P,	"floor"},
+	{ 6, false,	BIGINT_P,	"bigint"},
 	{ 6, false,	DOUBLE_P,	"double"},
 	{ 6, false,	EXISTS_P,	"exists"},
+	{ 6, false,	NUMBER_P,	"number"},
 	{ 6, false,	STARTS_P,	"starts"},
 	{ 6, false,	STRICT_P,	"strict"},
 	{ 7, false,	CEILING_P,	"ceiling"},
+	{ 7, false,	DECIMAL_P,	"decimal"},
+	{ 7, false,	INTEGER_P,	"integer"},
 	{ 7, false,	UNKNOWN_P,	"unknown"},
 	{ 8, false,	DATETIME_P,	"datetime"},
 	{ 8, false,	KEYVALUE_P,	"keyvalue"},
diff --git a/src/include/utils/jsonpath.h b/src/include/utils/jsonpath.h
index 9d55c25..ef81d1d 100644
--- a/src/include/utils/jsonpath.h
+++ b/src/include/utils/jsonpath.h
@@ -102,6 +102,10 @@ typedef enum JsonPathItemType
 	jpiLast,					/* LAST array subscript */
 	jpiStartsWith,				/* STARTS WITH predicate */
 	jpiLikeRegex,				/* LIKE_REGEX predicate */
+	jpiNumber,					/* .number() item method */
+	jpiDecimal,					/* .decimal() item method */
+	jpiBigint,					/* .bigint() item method */
+	jpiInteger,					/* .integer() item method */
 } JsonPathItemType;
 
 /* XQuery regex mode flags for LIKE_REGEX predicate */
diff --git a/src/test/regress/expected/jsonb_jsonpath.out b/src/test/regress/expected/jsonb_jsonpath.out
index 6659bc9..60af215 100644
--- a/src/test/regress/expected/jsonb_jsonpath.out
+++ b/src/test/regress/expected/jsonb_jsonpath.out
@@ -1517,6 +1517,540 @@ select jsonb_path_query('"-inf"', '$.double()', silent => true);
 ------------------
 (0 rows)
 
+select jsonb_path_query('null', '$.bigint()');
+ERROR:  jsonpath item method .bigint() can only be applied to a string or numeric value
+select jsonb_path_query('true', '$.bigint()');
+ERROR:  jsonpath item method .bigint() can only be applied to a string or numeric value
+select jsonb_path_query('null', '$.bigint()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('true', '$.bigint()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('[]', '$.bigint()');
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('[]', 'strict $.bigint()');
+ERROR:  jsonpath item method .bigint() can only be applied to a string or numeric value
+select jsonb_path_query('{}', '$.bigint()');
+ERROR:  jsonpath item method .bigint() can only be applied to a string or numeric value
+select jsonb_path_query('[]', 'strict $.bigint()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('{}', '$.bigint()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('"1.23"', '$.bigint()');
+ERROR:  string argument of jsonpath item method .bigint() is not a valid representation of a big integer
+select jsonb_path_query('"1.23aaa"', '$.bigint()');
+ERROR:  string argument of jsonpath item method .bigint() is not a valid representation of a big integer
+select jsonb_path_query('1e1000', '$.bigint()');
+ERROR:  numeric argument of jsonpath item method .bigint() is out of range for type bigint
+select jsonb_path_query('"nan"', '$.bigint()');
+ERROR:  string argument of jsonpath item method .bigint() is not a valid representation of a big integer
+select jsonb_path_query('"NaN"', '$.bigint()');
+ERROR:  string argument of jsonpath item method .bigint() is not a valid representation of a big integer
+select jsonb_path_query('"inf"', '$.bigint()');
+ERROR:  string argument of jsonpath item method .bigint() is not a valid representation of a big integer
+select jsonb_path_query('"-inf"', '$.bigint()');
+ERROR:  string argument of jsonpath item method .bigint() is not a valid representation of a big integer
+select jsonb_path_query('"inf"', '$.bigint()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('"-inf"', '$.bigint()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('123', '$.bigint()');
+ jsonb_path_query 
+------------------
+ 123
+(1 row)
+
+select jsonb_path_query('"123"', '$.bigint()');
+ jsonb_path_query 
+------------------
+ 123
+(1 row)
+
+select jsonb_path_query('1.23', '$.bigint()');
+ jsonb_path_query 
+------------------
+ 1
+(1 row)
+
+select jsonb_path_query('1.83', '$.bigint()');
+ jsonb_path_query 
+------------------
+ 2
+(1 row)
+
+select jsonb_path_query('1234567890123', '$.bigint()');
+ jsonb_path_query 
+------------------
+ 1234567890123
+(1 row)
+
+select jsonb_path_query('"1234567890123"', '$.bigint()');
+ jsonb_path_query 
+------------------
+ 1234567890123
+(1 row)
+
+select jsonb_path_query('12345678901234567890', '$.bigint()');
+ERROR:  numeric argument of jsonpath item method .bigint() is out of range for type bigint
+select jsonb_path_query('"12345678901234567890"', '$.bigint()');
+ERROR:  string argument of jsonpath item method .bigint() is not a valid representation of a big integer
+select jsonb_path_query('"+123"', '$.bigint()');
+ jsonb_path_query 
+------------------
+ 123
+(1 row)
+
+select jsonb_path_query('-123', '$.bigint()');
+ jsonb_path_query 
+------------------
+ -123
+(1 row)
+
+select jsonb_path_query('"-123"', '$.bigint()');
+ jsonb_path_query 
+------------------
+ -123
+(1 row)
+
+select jsonb_path_query('123', '$.bigint() * 2');
+ jsonb_path_query 
+------------------
+ 246
+(1 row)
+
+select jsonb_path_query('null', '$.integer()');
+ERROR:  jsonpath item method .integer() can only be applied to a string or numeric value
+select jsonb_path_query('true', '$.integer()');
+ERROR:  jsonpath item method .integer() can only be applied to a string or numeric value
+select jsonb_path_query('null', '$.integer()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('true', '$.integer()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('[]', '$.integer()');
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('[]', 'strict $.integer()');
+ERROR:  jsonpath item method .integer() can only be applied to a string or numeric value
+select jsonb_path_query('{}', '$.integer()');
+ERROR:  jsonpath item method .integer() can only be applied to a string or numeric value
+select jsonb_path_query('[]', 'strict $.integer()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('{}', '$.integer()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('"1.23"', '$.integer()');
+ERROR:  string argument of jsonpath item method .integer() is not a valid representation of an integer
+select jsonb_path_query('"1.23aaa"', '$.integer()');
+ERROR:  string argument of jsonpath item method .integer() is not a valid representation of an integer
+select jsonb_path_query('1e1000', '$.integer()');
+ERROR:  numeric argument of jsonpath item method .integer() is out of range for type integer
+select jsonb_path_query('"nan"', '$.integer()');
+ERROR:  string argument of jsonpath item method .integer() is not a valid representation of an integer
+select jsonb_path_query('"NaN"', '$.integer()');
+ERROR:  string argument of jsonpath item method .integer() is not a valid representation of an integer
+select jsonb_path_query('"inf"', '$.integer()');
+ERROR:  string argument of jsonpath item method .integer() is not a valid representation of an integer
+select jsonb_path_query('"-inf"', '$.integer()');
+ERROR:  string argument of jsonpath item method .integer() is not a valid representation of an integer
+select jsonb_path_query('"inf"', '$.integer()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('"-inf"', '$.integer()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('123', '$.integer()');
+ jsonb_path_query 
+------------------
+ 123
+(1 row)
+
+select jsonb_path_query('"123"', '$.integer()');
+ jsonb_path_query 
+------------------
+ 123
+(1 row)
+
+select jsonb_path_query('1.23', '$.integer()');
+ jsonb_path_query 
+------------------
+ 1
+(1 row)
+
+select jsonb_path_query('1.83', '$.integer()');
+ jsonb_path_query 
+------------------
+ 2
+(1 row)
+
+select jsonb_path_query('12345678901', '$.integer()');
+ERROR:  numeric argument of jsonpath item method .integer() is out of range for type integer
+select jsonb_path_query('"12345678901"', '$.integer()');
+ERROR:  string argument of jsonpath item method .integer() is not a valid representation of an integer
+select jsonb_path_query('"+123"', '$.integer()');
+ jsonb_path_query 
+------------------
+ 123
+(1 row)
+
+select jsonb_path_query('-123', '$.integer()');
+ jsonb_path_query 
+------------------
+ -123
+(1 row)
+
+select jsonb_path_query('"-123"', '$.integer()');
+ jsonb_path_query 
+------------------
+ -123
+(1 row)
+
+select jsonb_path_query('123', '$.integer() * 2');
+ jsonb_path_query 
+------------------
+ 246
+(1 row)
+
+select jsonb_path_query('null', '$.number()');
+ERROR:  jsonpath item method .number() can only be applied to a string or numeric value
+select jsonb_path_query('true', '$.number()');
+ERROR:  jsonpath item method .number() can only be applied to a string or numeric value
+select jsonb_path_query('null', '$.number()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('true', '$.number()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('[]', '$.number()');
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('[]', 'strict $.number()');
+ERROR:  jsonpath item method .number() can only be applied to a string or numeric value
+select jsonb_path_query('{}', '$.number()');
+ERROR:  jsonpath item method .number() can only be applied to a string or numeric value
+select jsonb_path_query('[]', 'strict $.number()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('{}', '$.number()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('1.23', '$.number()');
+ jsonb_path_query 
+------------------
+ 1.23
+(1 row)
+
+select jsonb_path_query('"1.23"', '$.number()');
+ jsonb_path_query 
+------------------
+ 1.23
+(1 row)
+
+select jsonb_path_query('"1.23aaa"', '$.number()');
+ERROR:  string argument of jsonpath item method .number() is not a valid representation of a decimal or number
+select jsonb_path_query('1e1000', '$.number()');
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             jsonb_path_query                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+(1 row)
+
+select jsonb_path_query('"nan"', '$.number()');
+ERROR:  string argument of jsonpath item method .number() is not a valid representation of a decimal or number
+select jsonb_path_query('"NaN"', '$.number()');
+ERROR:  string argument of jsonpath item method .number() is not a valid representation of a decimal or number
+select jsonb_path_query('"inf"', '$.number()');
+ERROR:  string argument of jsonpath item method .number() is not a valid representation of a decimal or number
+select jsonb_path_query('"-inf"', '$.number()');
+ERROR:  string argument of jsonpath item method .number() is not a valid representation of a decimal or number
+select jsonb_path_query('"inf"', '$.number()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('"-inf"', '$.number()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('123', '$.number()');
+ jsonb_path_query 
+------------------
+ 123
+(1 row)
+
+select jsonb_path_query('"123"', '$.number()');
+ jsonb_path_query 
+------------------
+ 123
+(1 row)
+
+select jsonb_path_query('12345678901234567890', '$.number()');
+   jsonb_path_query   
+----------------------
+ 12345678901234567890
+(1 row)
+
+select jsonb_path_query('"12345678901234567890"', '$.number()');
+   jsonb_path_query   
+----------------------
+ 12345678901234567890
+(1 row)
+
+select jsonb_path_query('"+12.3"', '$.number()');
+ jsonb_path_query 
+------------------
+ 12.3
+(1 row)
+
+select jsonb_path_query('-12.3', '$.number()');
+ jsonb_path_query 
+------------------
+ -12.3
+(1 row)
+
+select jsonb_path_query('"-12.3"', '$.number()');
+ jsonb_path_query 
+------------------
+ -12.3
+(1 row)
+
+select jsonb_path_query('12.3', '$.number() * 2');
+ jsonb_path_query 
+------------------
+ 24.6
+(1 row)
+
+select jsonb_path_query('null', '$.decimal()');
+ERROR:  jsonpath item method .decimal() can only be applied to a string or numeric value
+select jsonb_path_query('true', '$.decimal()');
+ERROR:  jsonpath item method .decimal() can only be applied to a string or numeric value
+select jsonb_path_query('null', '$.decimal()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('true', '$.decimal()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('[]', '$.decimal()');
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('[]', 'strict $.decimal()');
+ERROR:  jsonpath item method .decimal() can only be applied to a string or numeric value
+select jsonb_path_query('{}', '$.decimal()');
+ERROR:  jsonpath item method .decimal() can only be applied to a string or numeric value
+select jsonb_path_query('[]', 'strict $.decimal()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('{}', '$.decimal()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('1.23', '$.decimal()');
+ jsonb_path_query 
+------------------
+ 1.23
+(1 row)
+
+select jsonb_path_query('"1.23"', '$.decimal()');
+ jsonb_path_query 
+------------------
+ 1.23
+(1 row)
+
+select jsonb_path_query('"1.23aaa"', '$.decimal()');
+ERROR:  string argument of jsonpath item method .decimal() is not a valid representation of a decimal or number
+select jsonb_path_query('1e1000', '$.decimal()');
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             jsonb_path_query                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+(1 row)
+
+select jsonb_path_query('"nan"', '$.decimal()');
+ERROR:  string argument of jsonpath item method .decimal() is not a valid representation of a decimal or number
+select jsonb_path_query('"NaN"', '$.decimal()');
+ERROR:  string argument of jsonpath item method .decimal() is not a valid representation of a decimal or number
+select jsonb_path_query('"inf"', '$.decimal()');
+ERROR:  string argument of jsonpath item method .decimal() is not a valid representation of a decimal or number
+select jsonb_path_query('"-inf"', '$.decimal()');
+ERROR:  string argument of jsonpath item method .decimal() is not a valid representation of a decimal or number
+select jsonb_path_query('"inf"', '$.decimal()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('"-inf"', '$.decimal()', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('123', '$.decimal()');
+ jsonb_path_query 
+------------------
+ 123
+(1 row)
+
+select jsonb_path_query('"123"', '$.decimal()');
+ jsonb_path_query 
+------------------
+ 123
+(1 row)
+
+select jsonb_path_query('12345678901234567890', '$.decimal()');
+   jsonb_path_query   
+----------------------
+ 12345678901234567890
+(1 row)
+
+select jsonb_path_query('"12345678901234567890"', '$.decimal()');
+   jsonb_path_query   
+----------------------
+ 12345678901234567890
+(1 row)
+
+select jsonb_path_query('"+12.3"', '$.decimal()');
+ jsonb_path_query 
+------------------
+ 12.3
+(1 row)
+
+select jsonb_path_query('-12.3', '$.decimal()');
+ jsonb_path_query 
+------------------
+ -12.3
+(1 row)
+
+select jsonb_path_query('"-12.3"', '$.decimal()');
+ jsonb_path_query 
+------------------
+ -12.3
+(1 row)
+
+select jsonb_path_query('12.3', '$.decimal() * 2');
+ jsonb_path_query 
+------------------
+ 24.6
+(1 row)
+
+select jsonb_path_query('12345.678', '$.decimal(6, 1)');
+ jsonb_path_query 
+------------------
+ 12345.7
+(1 row)
+
+select jsonb_path_query('12345.678', '$.decimal(6, 2)');
+ERROR:  string argument of jsonpath item method .decimal() is not a valid representation of a decimal or number
+select jsonb_path_query('1234.5678', '$.decimal(6, 2)');
+ jsonb_path_query 
+------------------
+ 1234.57
+(1 row)
+
+select jsonb_path_query('12345.678', '$.decimal(4, 6)');
+ERROR:  string argument of jsonpath item method .decimal() is not a valid representation of a decimal or number
+select jsonb_path_query('12345.678', '$.decimal(0, 6)');
+ERROR:  NUMERIC precision 0 must be between 1 and 1000
+select jsonb_path_query('12345.678', '$.decimal(1001, 6)');
+ERROR:  NUMERIC precision 1001 must be between 1 and 1000
+select jsonb_path_query('1234.5678', '$.decimal(+6, +2)');
+ jsonb_path_query 
+------------------
+ 1234.57
+(1 row)
+
+select jsonb_path_query('1234.5678', '$.decimal(+6, -2)');
+ jsonb_path_query 
+------------------
+ 1200
+(1 row)
+
+select jsonb_path_query('1234.5678', '$.decimal(-6, +2)');
+ERROR:  NUMERIC precision -6 must be between 1 and 1000
+select jsonb_path_query('1234.5678', '$.decimal(6, -1001)');
+ERROR:  NUMERIC scale -1001 must be between -1000 and 1000
+select jsonb_path_query('1234.5678', '$.decimal(6, 1001)');
+ERROR:  NUMERIC scale 1001 must be between -1000 and 1000
+select jsonb_path_query('-1234.5678', '$.decimal(+6, -2)');
+ jsonb_path_query 
+------------------
+ -1200
+(1 row)
+
+select jsonb_path_query('0.0123456', '$.decimal(1,2)');
+ jsonb_path_query 
+------------------
+ 0.01
+(1 row)
+
+select jsonb_path_query('0.0012345', '$.decimal(2,4)');
+ jsonb_path_query 
+------------------
+ 0.0012
+(1 row)
+
+select jsonb_path_query('-0.00123456', '$.decimal(2,-4)');
+ jsonb_path_query 
+------------------
+ 0
+(1 row)
+
+select jsonb_path_query('12.3', '$.decimal(12345678901,1)');
+ERROR:  precision of jsonpath item method .decimal() is out of range for type integer
+select jsonb_path_query('12.3', '$.decimal(1,12345678901)');
+ERROR:  scale of jsonpath item method .decimal() is out of range for type integer
 select jsonb_path_query('{}', '$.abs()');
 ERROR:  jsonpath item method .abs() can only be applied to a numeric value
 select jsonb_path_query('true', '$.floor()');
diff --git a/src/test/regress/expected/jsonpath.out b/src/test/regress/expected/jsonpath.out
index eeffb38..15fb717 100644
--- a/src/test/regress/expected/jsonpath.out
+++ b/src/test/regress/expected/jsonpath.out
@@ -387,6 +387,18 @@ select '$.double().floor().ceiling().abs()'::jsonpath;
  $.double().floor().ceiling().abs()
 (1 row)
 
+select '$.bigint().integer().number().decimal()'::jsonpath;
+                jsonpath                 
+-----------------------------------------
+ $.bigint().integer().number().decimal()
+(1 row)
+
+select '$.decimal(4,2)'::jsonpath;
+    jsonpath    
+----------------
+ $.decimal(4,2)
+(1 row)
+
 select '$.keyvalue().key'::jsonpath;
       jsonpath      
 --------------------
diff --git a/src/test/regress/sql/jsonb_jsonpath.sql b/src/test/regress/sql/jsonb_jsonpath.sql
index e0ce509..4006a75 100644
--- a/src/test/regress/sql/jsonb_jsonpath.sql
+++ b/src/test/regress/sql/jsonb_jsonpath.sql
@@ -320,6 +320,139 @@ select jsonb_path_query('"-inf"', '$.double()');
 select jsonb_path_query('"inf"', '$.double()', silent => true);
 select jsonb_path_query('"-inf"', '$.double()', silent => true);
 
+select jsonb_path_query('null', '$.bigint()');
+select jsonb_path_query('true', '$.bigint()');
+select jsonb_path_query('null', '$.bigint()', silent => true);
+select jsonb_path_query('true', '$.bigint()', silent => true);
+select jsonb_path_query('[]', '$.bigint()');
+select jsonb_path_query('[]', 'strict $.bigint()');
+select jsonb_path_query('{}', '$.bigint()');
+select jsonb_path_query('[]', 'strict $.bigint()', silent => true);
+select jsonb_path_query('{}', '$.bigint()', silent => true);
+select jsonb_path_query('"1.23"', '$.bigint()');
+select jsonb_path_query('"1.23aaa"', '$.bigint()');
+select jsonb_path_query('1e1000', '$.bigint()');
+select jsonb_path_query('"nan"', '$.bigint()');
+select jsonb_path_query('"NaN"', '$.bigint()');
+select jsonb_path_query('"inf"', '$.bigint()');
+select jsonb_path_query('"-inf"', '$.bigint()');
+select jsonb_path_query('"inf"', '$.bigint()', silent => true);
+select jsonb_path_query('"-inf"', '$.bigint()', silent => true);
+select jsonb_path_query('123', '$.bigint()');
+select jsonb_path_query('"123"', '$.bigint()');
+select jsonb_path_query('1.23', '$.bigint()');
+select jsonb_path_query('1.83', '$.bigint()');
+select jsonb_path_query('1234567890123', '$.bigint()');
+select jsonb_path_query('"1234567890123"', '$.bigint()');
+select jsonb_path_query('12345678901234567890', '$.bigint()');
+select jsonb_path_query('"12345678901234567890"', '$.bigint()');
+select jsonb_path_query('"+123"', '$.bigint()');
+select jsonb_path_query('-123', '$.bigint()');
+select jsonb_path_query('"-123"', '$.bigint()');
+select jsonb_path_query('123', '$.bigint() * 2');
+
+select jsonb_path_query('null', '$.integer()');
+select jsonb_path_query('true', '$.integer()');
+select jsonb_path_query('null', '$.integer()', silent => true);
+select jsonb_path_query('true', '$.integer()', silent => true);
+select jsonb_path_query('[]', '$.integer()');
+select jsonb_path_query('[]', 'strict $.integer()');
+select jsonb_path_query('{}', '$.integer()');
+select jsonb_path_query('[]', 'strict $.integer()', silent => true);
+select jsonb_path_query('{}', '$.integer()', silent => true);
+select jsonb_path_query('"1.23"', '$.integer()');
+select jsonb_path_query('"1.23aaa"', '$.integer()');
+select jsonb_path_query('1e1000', '$.integer()');
+select jsonb_path_query('"nan"', '$.integer()');
+select jsonb_path_query('"NaN"', '$.integer()');
+select jsonb_path_query('"inf"', '$.integer()');
+select jsonb_path_query('"-inf"', '$.integer()');
+select jsonb_path_query('"inf"', '$.integer()', silent => true);
+select jsonb_path_query('"-inf"', '$.integer()', silent => true);
+select jsonb_path_query('123', '$.integer()');
+select jsonb_path_query('"123"', '$.integer()');
+select jsonb_path_query('1.23', '$.integer()');
+select jsonb_path_query('1.83', '$.integer()');
+select jsonb_path_query('12345678901', '$.integer()');
+select jsonb_path_query('"12345678901"', '$.integer()');
+select jsonb_path_query('"+123"', '$.integer()');
+select jsonb_path_query('-123', '$.integer()');
+select jsonb_path_query('"-123"', '$.integer()');
+select jsonb_path_query('123', '$.integer() * 2');
+
+select jsonb_path_query('null', '$.number()');
+select jsonb_path_query('true', '$.number()');
+select jsonb_path_query('null', '$.number()', silent => true);
+select jsonb_path_query('true', '$.number()', silent => true);
+select jsonb_path_query('[]', '$.number()');
+select jsonb_path_query('[]', 'strict $.number()');
+select jsonb_path_query('{}', '$.number()');
+select jsonb_path_query('[]', 'strict $.number()', silent => true);
+select jsonb_path_query('{}', '$.number()', silent => true);
+select jsonb_path_query('1.23', '$.number()');
+select jsonb_path_query('"1.23"', '$.number()');
+select jsonb_path_query('"1.23aaa"', '$.number()');
+select jsonb_path_query('1e1000', '$.number()');
+select jsonb_path_query('"nan"', '$.number()');
+select jsonb_path_query('"NaN"', '$.number()');
+select jsonb_path_query('"inf"', '$.number()');
+select jsonb_path_query('"-inf"', '$.number()');
+select jsonb_path_query('"inf"', '$.number()', silent => true);
+select jsonb_path_query('"-inf"', '$.number()', silent => true);
+select jsonb_path_query('123', '$.number()');
+select jsonb_path_query('"123"', '$.number()');
+select jsonb_path_query('12345678901234567890', '$.number()');
+select jsonb_path_query('"12345678901234567890"', '$.number()');
+select jsonb_path_query('"+12.3"', '$.number()');
+select jsonb_path_query('-12.3', '$.number()');
+select jsonb_path_query('"-12.3"', '$.number()');
+select jsonb_path_query('12.3', '$.number() * 2');
+
+select jsonb_path_query('null', '$.decimal()');
+select jsonb_path_query('true', '$.decimal()');
+select jsonb_path_query('null', '$.decimal()', silent => true);
+select jsonb_path_query('true', '$.decimal()', silent => true);
+select jsonb_path_query('[]', '$.decimal()');
+select jsonb_path_query('[]', 'strict $.decimal()');
+select jsonb_path_query('{}', '$.decimal()');
+select jsonb_path_query('[]', 'strict $.decimal()', silent => true);
+select jsonb_path_query('{}', '$.decimal()', silent => true);
+select jsonb_path_query('1.23', '$.decimal()');
+select jsonb_path_query('"1.23"', '$.decimal()');
+select jsonb_path_query('"1.23aaa"', '$.decimal()');
+select jsonb_path_query('1e1000', '$.decimal()');
+select jsonb_path_query('"nan"', '$.decimal()');
+select jsonb_path_query('"NaN"', '$.decimal()');
+select jsonb_path_query('"inf"', '$.decimal()');
+select jsonb_path_query('"-inf"', '$.decimal()');
+select jsonb_path_query('"inf"', '$.decimal()', silent => true);
+select jsonb_path_query('"-inf"', '$.decimal()', silent => true);
+select jsonb_path_query('123', '$.decimal()');
+select jsonb_path_query('"123"', '$.decimal()');
+select jsonb_path_query('12345678901234567890', '$.decimal()');
+select jsonb_path_query('"12345678901234567890"', '$.decimal()');
+select jsonb_path_query('"+12.3"', '$.decimal()');
+select jsonb_path_query('-12.3', '$.decimal()');
+select jsonb_path_query('"-12.3"', '$.decimal()');
+select jsonb_path_query('12.3', '$.decimal() * 2');
+select jsonb_path_query('12345.678', '$.decimal(6, 1)');
+select jsonb_path_query('12345.678', '$.decimal(6, 2)');
+select jsonb_path_query('1234.5678', '$.decimal(6, 2)');
+select jsonb_path_query('12345.678', '$.decimal(4, 6)');
+select jsonb_path_query('12345.678', '$.decimal(0, 6)');
+select jsonb_path_query('12345.678', '$.decimal(1001, 6)');
+select jsonb_path_query('1234.5678', '$.decimal(+6, +2)');
+select jsonb_path_query('1234.5678', '$.decimal(+6, -2)');
+select jsonb_path_query('1234.5678', '$.decimal(-6, +2)');
+select jsonb_path_query('1234.5678', '$.decimal(6, -1001)');
+select jsonb_path_query('1234.5678', '$.decimal(6, 1001)');
+select jsonb_path_query('-1234.5678', '$.decimal(+6, -2)');
+select jsonb_path_query('0.0123456', '$.decimal(1,2)');
+select jsonb_path_query('0.0012345', '$.decimal(2,4)');
+select jsonb_path_query('-0.00123456', '$.decimal(2,-4)');
+select jsonb_path_query('12.3', '$.decimal(12345678901,1)');
+select jsonb_path_query('12.3', '$.decimal(1,12345678901)');
+
 select jsonb_path_query('{}', '$.abs()');
 select jsonb_path_query('true', '$.floor()');
 select jsonb_path_query('"1.2"', '$.ceiling()');
diff --git a/src/test/regress/sql/jsonpath.sql b/src/test/regress/sql/jsonpath.sql
index 56e0bef..1f25f89 100644
--- a/src/test/regress/sql/jsonpath.sql
+++ b/src/test/regress/sql/jsonpath.sql
@@ -70,6 +70,8 @@ select '1.2.type()'::jsonpath;
 select '"aaa".type()'::jsonpath;
 select 'true.type()'::jsonpath;
 select '$.double().floor().ceiling().abs()'::jsonpath;
+select '$.bigint().integer().number().decimal()'::jsonpath;
+select '$.decimal(4,2)'::jsonpath;
 select '$.keyvalue().key'::jsonpath;
 select '$.datetime()'::jsonpath;
 select '$.datetime("datetime template")'::jsonpath;
-- 
1.8.3.1