From 4aa731ebe57d1edc04caf332821341fd25e6a24f Mon Sep 17 00:00:00 2001 From: Jeevan Chalke Date: Mon, 6 Nov 2023 18:09:10 +0530 Subject: [PATCH v3 4/4] Implement jsonpath .boolean() and .string() methods This commit implements jsonpath .boolean() and .string() methods. .boolean() method converts the given JSON string, numeric, or boolean value to the boolean type representation. In the numeric case, only integers are allowed, whereas we use the parse_bool() backend function to convert string to a bool. .string() method uses the datatype's out function to convert numeric and various date/time types to the string representation. Jeevan Chalke. --- doc/src/sgml/func.sgml | 32 ++++ src/backend/catalog/sql_features.txt | 4 +- src/backend/utils/adt/jsonpath.c | 16 ++ src/backend/utils/adt/jsonpath_exec.c | 147 +++++++++++++++ src/backend/utils/adt/jsonpath_gram.y | 6 +- src/backend/utils/adt/jsonpath_scan.l | 2 + src/include/utils/jsonpath.h | 2 + src/test/regress/expected/jsonb_jsonpath.out | 263 +++++++++++++++++++++++++++ src/test/regress/expected/jsonpath.out | 12 ++ src/test/regress/sql/jsonb_jsonpath.sql | 58 ++++++ src/test/regress/sql/jsonpath.sql | 2 + 11 files changed, 541 insertions(+), 3 deletions(-) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index cbaed1b..c878349 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -17672,6 +17672,38 @@ strict $.**.HR + value . boolean() + boolean + + + Boolean value converted from a JSON boolean, number, or string + + + jsonb_path_query_array('[1, "yes", false]', '$[*].boolean()') + [true, true, false] + + + + + + value . string() + string + + + String value converted from a JSON boolean, number, string, or datetime + + + jsonb_path_query_array('[1.23, "xyz", false]', '$[*].string()') + ["1.23", "xyz", "false"] + + + jsonb_path_query('"2023-08-15"', '$.datetime().string()') + "2023-08-15" + + + + + value . double() number diff --git a/src/backend/catalog/sql_features.txt b/src/backend/catalog/sql_features.txt index aa80634..4085a2d 100644 --- a/src/backend/catalog/sql_features.txt +++ b/src/backend/catalog/sql_features.txt @@ -575,13 +575,13 @@ 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() YES -T866 SQL/JSON item method: boolean() NO +T866 SQL/JSON item method: boolean() YES T867 SQL/JSON item method: date() YES 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 +T872 SQL/JSON item method: string() YES T873 SQL/JSON item method: time() YES T874 SQL/JSON item method: time_tz() YES T875 SQL/JSON item method: time precision YES diff --git a/src/backend/utils/adt/jsonpath.c b/src/backend/utils/adt/jsonpath.c index 2ebd11c..19cf79d 100644 --- a/src/backend/utils/adt/jsonpath.c +++ b/src/backend/utils/adt/jsonpath.c @@ -444,6 +444,8 @@ flattenJsonPathParseItem(StringInfo buf, int *result, struct Node *escontext, break; case jpiType: case jpiSize: + case jpiBoolean: + case jpiStringFunc: case jpiDouble: case jpiNumber: case jpiBigint: @@ -727,6 +729,12 @@ printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey, case jpiSize: appendStringInfoString(buf, ".size()"); break; + case jpiBoolean: + appendStringInfoString(buf, ".boolean()"); + break; + case jpiStringFunc: + appendStringInfoString(buf, ".string()"); + break; case jpiDouble: appendStringInfoString(buf, ".double()"); break; @@ -859,6 +867,10 @@ jspOperationName(JsonPathItemType type) return "type"; case jpiSize: return "size"; + case jpiBoolean: + return "boolean"; + case jpiStringFunc: + return "string"; case jpiDouble: return "double"; case jpiNumber: @@ -983,6 +995,8 @@ jspInitByBuffer(JsonPathItem *v, char *base, int32 pos) case jpiAnyKey: case jpiType: case jpiSize: + case jpiBoolean: + case jpiStringFunc: case jpiDouble: case jpiNumber: case jpiBigint: @@ -1111,6 +1125,8 @@ jspGetNext(JsonPathItem *v, JsonPathItem *a) v->type == jpiMod || v->type == jpiType || v->type == jpiSize || + v->type == jpiBoolean || + v->type == jpiStringFunc || v->type == jpiDouble || v->type == jpiNumber || v->type == jpiDecimal || diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c index deeee76..62571f7 100644 --- a/src/backend/utils/adt/jsonpath_exec.c +++ b/src/backend/utils/adt/jsonpath_exec.c @@ -1021,6 +1021,153 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, } break; + case jpiBoolean: + { + JsonbValue jbv; + bool bval; + + if (unwrap && JsonbType(jb) == jbvArray) + return executeItemUnwrapTargetArray(cxt, jsp, jb, found, + false); + + if (jb->type == jbvBool) + { + bval = jb->val.boolean; + + res = jperOk; + } + else if (jb->type == jbvNumeric) + { + int ival; + Datum datum; + bool noerr; + char *tmp = DatumGetCString(DirectFunctionCall1(numeric_out, + NumericGetDatum(jb->val.numeric))); + ErrorSaveContext escontext = {T_ErrorSaveContext}; + + 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("numeric argument of jsonpath item method .%s() is out of range for type boolean", + jspOperationName(jsp->type))))); + + ival = DatumGetInt32(datum); + if (ival == 0) + bval = false; + else + bval = true; + + res = jperOk; + } + else if (jb->type == jbvString) + { + /* cast string as boolean */ + char *tmp = pnstrdup(jb->val.string.val, + jb->val.string.len); + + if (!parse_bool(tmp, &bval)) + 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 boolean", + 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 bool, string, or numeric value", + jspOperationName(jsp->type))))); + + jb = &jbv; + jb->type = jbvBool; + jb->val.boolean = bval; + + res = executeNextItem(cxt, jsp, NULL, jb, found, true); + } + break; + + case jpiStringFunc: + { + JsonbValue jbv; + char *tmp = NULL; + + switch (JsonbType(jb)) + { + case jbvString: + /* + * Value is not necessarily null-terminated, so we do + * pnstrdup() here. + */ + tmp = pnstrdup(jb->val.string.val, + jb->val.string.len); + break; + case jbvNumeric: + tmp = DatumGetCString(DirectFunctionCall1(numeric_out, + NumericGetDatum(jb->val.numeric))); + break; + case jbvBool: + tmp = (jb->val.boolean) ? "true" : "false"; + break; + case jbvDatetime: + { + switch (jb->val.datetime.typid) + { + case DATEOID: + tmp = DatumGetCString(DirectFunctionCall1(date_out, + jb->val.datetime.value)); + break; + case TIMEOID: + tmp = DatumGetCString(DirectFunctionCall1(time_out, + jb->val.datetime.value)); + break; + case TIMETZOID: + tmp = DatumGetCString(DirectFunctionCall1(timetz_out, + jb->val.datetime.value)); + break; + case TIMESTAMPOID: + tmp = DatumGetCString(DirectFunctionCall1(timestamp_out, + jb->val.datetime.value)); + break; + case TIMESTAMPTZOID: + tmp = DatumGetCString(DirectFunctionCall1(timestamptz_out, + jb->val.datetime.value)); + break; + default: + elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u", + jb->val.datetime.typid); + } + } + break; + case jbvNull: + case jbvArray: + case jbvObject: + case jbvBinary: + RETURN_ERROR(ereport(ERROR, + (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM), + errmsg("jsonpath item method .%s() can only be applied to a bool, string, numeric, or datetime value", + jspOperationName(jsp->type))))); + break; + } + + res = jperOk; + + jb = &jbv; + Assert(tmp != NULL); /* We must have set tmp above */ + jb->val.string.val = (jb->type == jbvString) ? tmp : pstrdup(tmp); + jb->val.string.len = strlen(jb->val.string.val); + jb->type = jbvString; + + res = executeNextItem(cxt, jsp, NULL, jb, found, true); + } + break; + case jpiDouble: { JsonbValue jbv; diff --git a/src/backend/utils/adt/jsonpath_gram.y b/src/backend/utils/adt/jsonpath_gram.y index 7162d37..eee16cc 100644 --- a/src/backend/utils/adt/jsonpath_gram.y +++ b/src/backend/utils/adt/jsonpath_gram.y @@ -80,7 +80,7 @@ static bool makeItemLikeRegex(JsonPathParseItem *expr, %token OR_P AND_P NOT_P %token LESS_P LESSEQUAL_P EQUAL_P NOTEQUAL_P GREATEREQUAL_P GREATER_P %token ANY_P STRICT_P LAX_P LAST_P STARTS_P WITH_P LIKE_REGEX_P FLAG_P -%token TYPE_P SIZE_P +%token TYPE_P SIZE_P BOOLEAN_P STRINGFUNC_P %token DOUBLE_P NUMBER_P DECIMAL_P BIGINT_P INTEGER_P %token ABS_P CEILING_P FLOOR_P KEYVALUE_P %token DATETIME_P DATE_P TIME_P TIME_TZ_P TIMESTAMP_P TIMESTAMP_TZ_P @@ -339,6 +339,8 @@ key_name: | FLAG_P | TYPE_P | SIZE_P + | BOOLEAN_P + | STRINGFUNC_P | DOUBLE_P | NUMBER_P | DECIMAL_P @@ -362,6 +364,8 @@ key_name: method: TYPE_P { $$ = jpiType; } | SIZE_P { $$ = jpiSize; } + | BOOLEAN_P { $$ = jpiBoolean; } + | STRINGFUNC_P { $$ = jpiStringFunc; } | DOUBLE_P { $$ = jpiDouble; } | NUMBER_P { $$ = jpiNumber; } | BIGINT_P { $$ = jpiBigint; } diff --git a/src/backend/utils/adt/jsonpath_scan.l b/src/backend/utils/adt/jsonpath_scan.l index 6a7d72a..d87da14 100644 --- a/src/backend/utils/adt/jsonpath_scan.l +++ b/src/backend/utils/adt/jsonpath_scan.l @@ -418,6 +418,8 @@ static const JsonPathKeyword keywords[] = { { 6, false, NUMBER_P, "number"}, { 6, false, STARTS_P, "starts"}, { 6, false, STRICT_P, "strict"}, + { 6, false, STRINGFUNC_P, "string"}, + { 7, false, BOOLEAN_P, "boolean"}, { 7, false, CEILING_P, "ceiling"}, { 7, false, DECIMAL_P, "decimal"}, { 7, false, INTEGER_P, "integer"}, diff --git a/src/include/utils/jsonpath.h b/src/include/utils/jsonpath.h index 5577086..92989c8 100644 --- a/src/include/utils/jsonpath.h +++ b/src/include/utils/jsonpath.h @@ -91,6 +91,8 @@ typedef enum JsonPathItemType jpiMod, /* expr % expr */ jpiType, /* .type() item method */ jpiSize, /* .size() item method */ + jpiBoolean, /* .boolean() item method */ + jpiStringFunc, /* .string() item method */ jpiDouble, /* .double() item method */ jpiNumber, /* .number() item method */ jpiDecimal, /* .decimal() item method */ diff --git a/src/test/regress/expected/jsonb_jsonpath.out b/src/test/regress/expected/jsonb_jsonpath.out index 0231265..f07eb90 100644 --- a/src/test/regress/expected/jsonb_jsonpath.out +++ b/src/test/regress/expected/jsonb_jsonpath.out @@ -1348,6 +1348,269 @@ select jsonb_path_query('[1,null,true,"11",[],[1],[1,2,3],{},{"a":1,"b":2}]', 'l 1 (9 rows) +select jsonb_path_query('null', '$.boolean()'); +ERROR: jsonpath item method .boolean() can only be applied to a bool, string, or numeric value +select jsonb_path_query('null', '$.boolean()', silent => true); + jsonb_path_query +------------------ +(0 rows) + +select jsonb_path_query('[]', '$.boolean()'); + jsonb_path_query +------------------ +(0 rows) + +select jsonb_path_query('[]', 'strict $.boolean()'); +ERROR: jsonpath item method .boolean() can only be applied to a bool, string, or numeric value +select jsonb_path_query('{}', '$.boolean()'); +ERROR: jsonpath item method .boolean() can only be applied to a bool, string, or numeric value +select jsonb_path_query('[]', 'strict $.boolean()', silent => true); + jsonb_path_query +------------------ +(0 rows) + +select jsonb_path_query('{}', '$.boolean()', silent => true); + jsonb_path_query +------------------ +(0 rows) + +select jsonb_path_query('1.23', '$.boolean()'); +ERROR: numeric argument of jsonpath item method .boolean() is out of range for type boolean +select jsonb_path_query('"1.23"', '$.boolean()'); +ERROR: string argument of jsonpath item method .boolean() is not a valid representation of a boolean +select jsonb_path_query('"1.23aaa"', '$.boolean()'); +ERROR: string argument of jsonpath item method .boolean() is not a valid representation of a boolean +select jsonb_path_query('1e1000', '$.boolean()'); +ERROR: numeric argument of jsonpath item method .boolean() is out of range for type boolean +select jsonb_path_query('"nan"', '$.boolean()'); +ERROR: string argument of jsonpath item method .boolean() is not a valid representation of a boolean +select jsonb_path_query('"NaN"', '$.boolean()'); +ERROR: string argument of jsonpath item method .boolean() is not a valid representation of a boolean +select jsonb_path_query('"inf"', '$.boolean()'); +ERROR: string argument of jsonpath item method .boolean() is not a valid representation of a boolean +select jsonb_path_query('"-inf"', '$.boolean()'); +ERROR: string argument of jsonpath item method .boolean() is not a valid representation of a boolean +select jsonb_path_query('"inf"', '$.boolean()', silent => true); + jsonb_path_query +------------------ +(0 rows) + +select jsonb_path_query('"-inf"', '$.boolean()', silent => true); + jsonb_path_query +------------------ +(0 rows) + +select jsonb_path_query('"100"', '$.boolean()'); +ERROR: string argument of jsonpath item method .boolean() is not a valid representation of a boolean +select jsonb_path_query('true', '$.boolean()'); + jsonb_path_query +------------------ + true +(1 row) + +select jsonb_path_query('false', '$.boolean()'); + jsonb_path_query +------------------ + false +(1 row) + +select jsonb_path_query('1', '$.boolean()'); + jsonb_path_query +------------------ + true +(1 row) + +select jsonb_path_query('0', '$.boolean()'); + jsonb_path_query +------------------ + false +(1 row) + +select jsonb_path_query('-1', '$.boolean()'); + jsonb_path_query +------------------ + true +(1 row) + +select jsonb_path_query('100', '$.boolean()'); + jsonb_path_query +------------------ + true +(1 row) + +select jsonb_path_query('"1"', '$.boolean()'); + jsonb_path_query +------------------ + true +(1 row) + +select jsonb_path_query('"0"', '$.boolean()'); + jsonb_path_query +------------------ + false +(1 row) + +select jsonb_path_query('"true"', '$.boolean()'); + jsonb_path_query +------------------ + true +(1 row) + +select jsonb_path_query('"false"', '$.boolean()'); + jsonb_path_query +------------------ + false +(1 row) + +select jsonb_path_query('"TRUE"', '$.boolean()'); + jsonb_path_query +------------------ + true +(1 row) + +select jsonb_path_query('"FALSE"', '$.boolean()'); + jsonb_path_query +------------------ + false +(1 row) + +select jsonb_path_query('"yes"', '$.boolean()'); + jsonb_path_query +------------------ + true +(1 row) + +select jsonb_path_query('"NO"', '$.boolean()'); + jsonb_path_query +------------------ + false +(1 row) + +select jsonb_path_query('"T"', '$.boolean()'); + jsonb_path_query +------------------ + true +(1 row) + +select jsonb_path_query('"f"', '$.boolean()'); + jsonb_path_query +------------------ + false +(1 row) + +select jsonb_path_query('"y"', '$.boolean()'); + jsonb_path_query +------------------ + true +(1 row) + +select jsonb_path_query('"N"', '$.boolean()'); + jsonb_path_query +------------------ + false +(1 row) + +select jsonb_path_query('true', '$.boolean().type()'); + jsonb_path_query +------------------ + "boolean" +(1 row) + +select jsonb_path_query('123', '$.boolean().type()'); + jsonb_path_query +------------------ + "boolean" +(1 row) + +select jsonb_path_query('"Yes"', '$.boolean().type()'); + jsonb_path_query +------------------ + "boolean" +(1 row) + +select jsonb_path_query_array('[1, "yes", false]', '$[*].boolean()'); + jsonb_path_query_array +------------------------ + [true, true, false] +(1 row) + +select jsonb_path_query('null', '$.string()'); +ERROR: jsonpath item method .string() can only be applied to a bool, string, numeric, or datetime value +select jsonb_path_query('null', '$.string()', silent => true); + jsonb_path_query +------------------ +(0 rows) + +select jsonb_path_query('[]', '$.string()'); +ERROR: jsonpath item method .string() can only be applied to a bool, string, numeric, or datetime value +select jsonb_path_query('[]', 'strict $.string()'); +ERROR: jsonpath item method .string() can only be applied to a bool, string, numeric, or datetime value +select jsonb_path_query('{}', '$.string()'); +ERROR: jsonpath item method .string() can only be applied to a bool, string, numeric, or datetime value +select jsonb_path_query('[]', 'strict $.string()', silent => true); + jsonb_path_query +------------------ +(0 rows) + +select jsonb_path_query('{}', '$.string()', silent => true); + jsonb_path_query +------------------ +(0 rows) + +select jsonb_path_query('1.23', '$.string()'); + jsonb_path_query +------------------ + "1.23" +(1 row) + +select jsonb_path_query('"1.23"', '$.string()'); + jsonb_path_query +------------------ + "1.23" +(1 row) + +select jsonb_path_query('"1.23aaa"', '$.string()'); + jsonb_path_query +------------------ + "1.23aaa" +(1 row) + +select jsonb_path_query('1234', '$.string()'); + jsonb_path_query +------------------ + "1234" +(1 row) + +select jsonb_path_query('true', '$.string()'); + jsonb_path_query +------------------ + "true" +(1 row) + +select jsonb_path_query('1234', '$.string().type()'); + jsonb_path_query +------------------ + "string" +(1 row) + +select jsonb_path_query('"2023-08-15 12:34:56 +5:30"', '$.timestamp().string()'); + jsonb_path_query +---------------------------- + "Tue Aug 15 00:04:56 2023" +(1 row) + +select jsonb_path_query_array('[1.23, "yes", false]', '$[*].string()'); + jsonb_path_query_array +-------------------------- + ["1.23", "yes", "false"] +(1 row) + +select jsonb_path_query_array('[1.23, "yes", false]', '$[*].string().type()'); + jsonb_path_query_array +-------------------------------- + ["string", "string", "string"] +(1 row) + select jsonb_path_query('[0, 1, -2, -3.4, 5.6]', '$[*].abs()'); jsonb_path_query ------------------ diff --git a/src/test/regress/expected/jsonpath.out b/src/test/regress/expected/jsonpath.out index b47b2e9..6b16cda 100644 --- a/src/test/regress/expected/jsonpath.out +++ b/src/test/regress/expected/jsonpath.out @@ -381,6 +381,18 @@ select 'true.type()'::jsonpath; true.type() (1 row) +select '$.boolean()'::jsonpath; + jsonpath +------------- + $.boolean() +(1 row) + +select '$.string()'::jsonpath; + jsonpath +------------ + $.string() +(1 row) + select '$.double().floor().ceiling().abs()'::jsonpath; jsonpath ------------------------------------ diff --git a/src/test/regress/sql/jsonb_jsonpath.sql b/src/test/regress/sql/jsonb_jsonpath.sql index 06a9548..c10fb2b 100644 --- a/src/test/regress/sql/jsonb_jsonpath.sql +++ b/src/test/regress/sql/jsonb_jsonpath.sql @@ -283,6 +283,64 @@ select jsonb_path_query('[1,null,true,"11",[],[1],[1,2,3],{},{"a":1,"b":2}]', 's select jsonb_path_query('[1,null,true,"11",[],[1],[1,2,3],{},{"a":1,"b":2}]', 'strict $[*].size()', silent => true); select jsonb_path_query('[1,null,true,"11",[],[1],[1,2,3],{},{"a":1,"b":2}]', 'lax $[*].size()'); +select jsonb_path_query('null', '$.boolean()'); +select jsonb_path_query('null', '$.boolean()', silent => true); +select jsonb_path_query('[]', '$.boolean()'); +select jsonb_path_query('[]', 'strict $.boolean()'); +select jsonb_path_query('{}', '$.boolean()'); +select jsonb_path_query('[]', 'strict $.boolean()', silent => true); +select jsonb_path_query('{}', '$.boolean()', silent => true); +select jsonb_path_query('1.23', '$.boolean()'); +select jsonb_path_query('"1.23"', '$.boolean()'); +select jsonb_path_query('"1.23aaa"', '$.boolean()'); +select jsonb_path_query('1e1000', '$.boolean()'); +select jsonb_path_query('"nan"', '$.boolean()'); +select jsonb_path_query('"NaN"', '$.boolean()'); +select jsonb_path_query('"inf"', '$.boolean()'); +select jsonb_path_query('"-inf"', '$.boolean()'); +select jsonb_path_query('"inf"', '$.boolean()', silent => true); +select jsonb_path_query('"-inf"', '$.boolean()', silent => true); +select jsonb_path_query('"100"', '$.boolean()'); +select jsonb_path_query('true', '$.boolean()'); +select jsonb_path_query('false', '$.boolean()'); +select jsonb_path_query('1', '$.boolean()'); +select jsonb_path_query('0', '$.boolean()'); +select jsonb_path_query('-1', '$.boolean()'); +select jsonb_path_query('100', '$.boolean()'); +select jsonb_path_query('"1"', '$.boolean()'); +select jsonb_path_query('"0"', '$.boolean()'); +select jsonb_path_query('"true"', '$.boolean()'); +select jsonb_path_query('"false"', '$.boolean()'); +select jsonb_path_query('"TRUE"', '$.boolean()'); +select jsonb_path_query('"FALSE"', '$.boolean()'); +select jsonb_path_query('"yes"', '$.boolean()'); +select jsonb_path_query('"NO"', '$.boolean()'); +select jsonb_path_query('"T"', '$.boolean()'); +select jsonb_path_query('"f"', '$.boolean()'); +select jsonb_path_query('"y"', '$.boolean()'); +select jsonb_path_query('"N"', '$.boolean()'); +select jsonb_path_query('true', '$.boolean().type()'); +select jsonb_path_query('123', '$.boolean().type()'); +select jsonb_path_query('"Yes"', '$.boolean().type()'); +select jsonb_path_query_array('[1, "yes", false]', '$[*].boolean()'); + +select jsonb_path_query('null', '$.string()'); +select jsonb_path_query('null', '$.string()', silent => true); +select jsonb_path_query('[]', '$.string()'); +select jsonb_path_query('[]', 'strict $.string()'); +select jsonb_path_query('{}', '$.string()'); +select jsonb_path_query('[]', 'strict $.string()', silent => true); +select jsonb_path_query('{}', '$.string()', silent => true); +select jsonb_path_query('1.23', '$.string()'); +select jsonb_path_query('"1.23"', '$.string()'); +select jsonb_path_query('"1.23aaa"', '$.string()'); +select jsonb_path_query('1234', '$.string()'); +select jsonb_path_query('true', '$.string()'); +select jsonb_path_query('1234', '$.string().type()'); +select jsonb_path_query('"2023-08-15 12:34:56 +5:30"', '$.timestamp().string()'); +select jsonb_path_query_array('[1.23, "yes", false]', '$[*].string()'); +select jsonb_path_query_array('[1.23, "yes", false]', '$[*].string().type()'); + select jsonb_path_query('[0, 1, -2, -3.4, 5.6]', '$[*].abs()'); select jsonb_path_query('[0, 1, -2, -3.4, 5.6]', '$[*].floor()'); select jsonb_path_query('[0, 1, -2, -3.4, 5.6]', '$[*].ceiling()'); diff --git a/src/test/regress/sql/jsonpath.sql b/src/test/regress/sql/jsonpath.sql index 44275c9..8f07b71 100644 --- a/src/test/regress/sql/jsonpath.sql +++ b/src/test/regress/sql/jsonpath.sql @@ -69,6 +69,8 @@ select '(1).type()'::jsonpath; select '1.2.type()'::jsonpath; select '"aaa".type()'::jsonpath; select 'true.type()'::jsonpath; +select '$.boolean()'::jsonpath; +select '$.string()'::jsonpath; select '$.double().floor().ceiling().abs()'::jsonpath; select '$.bigint().integer().number().decimal()'::jsonpath; select '$.decimal(4,2)'::jsonpath; -- 1.8.3.1