Useful utilities for PostgreSQL to process json objects, to build templates and to map data
Open pg_utilities.sql file, copy its content, and paste in PostgreSQL in required database. A new "ub" scheme with multiple functions will be created.
List of all functions, with detailed description and examples, is below:
- Array Utilities
- JSONB Utilities
ub.util_jsonb_array
ub.agg_jsonb_array
ub.util_jsonb_concat
ub.agg_jsonb_concat
ub.util_jsonb_merge
ub.agg_jsonb_merge
ub.util_jsonb_merge_null
ub.util_jsonb_multi_array
ub.util_jsonb_multi_concat
ub.util_jsonb_multi_merge
ub.util_jsonb_nest
ub.util_jsonb_unnest
ub.util_jsonb_update
ub.util_jsonb_differ
ub.util_jsonb_process
- Data Modifiers & Templating
- Security & Scheduling
- Validation
These functions provide advanced operations for PostgreSQL's native double precision[]
and integer[]
arrays.
Processes ("SUM", "MERGE") two float arrays. Arrays with different sizes are automatically expanded to the largest one.
Parameters:
lntotaldata double precision[]
: Initial float array.lnupdatedata double precision[]
: Float array to sum up or merge with.lcaggfunc text DEFAULT 'SUM'
: Aggregate function to apply:SUM
: Sum two float arrays, with adjusting their length.MERGE
: Concatenate two float arrays.MERGE_UNIQUE
: Merge two float arrays with eliminating duplicates.MERGE_NNN
: Merge the second array at NNN position (e.g.,MERGE5
).
Returns: double precision[]
- Processed float array.
Examples:
SELECT ub.util_array_float(ARRAY[0.5, 2.1], ARRAY[0.3, 3.2, 5.5], 'SUM');
--> {0.8,5.3,5.5}
SELECT ub.util_array_float(ARRAY[0.5, 2.1], ARRAY[0.3, 2.1, 5.5], 'MERGE');
--> {0.5,2.1,0.3,2.1,5.5}
SELECT ub.util_array_float(ARRAY[0.5, 2.1], ARRAY[0.3, 2.1, 5.5], 'MERGE_UNIQUE');
--> {0.3,2.1,5.5,0.5}
SELECT ub.util_array_float(ARRAY[0.5, 2.1], ARRAY[0.3, 2.1, 5.5], 'MERGE5');
--> {0.5,2.1,0,0,0.3,2.1,5.5}
An aggregate function for operations with float arrays. It uses ub.util_array_float
internally.
Operations supported (via lcaggfunc
): SUM
, MERGE
, MERGE_UNIQUE
, MERGE_NNN
.
Example (conceptual usage):
-- Assuming a table 'my_data' with a 'values' column of type double precision[]
-- SELECT ub.agg_array_float(values, 'SUM') FROM my_data;
Processes ("SUM", "MERGE") two integer arrays. Arrays with different sizes are automatically expanded to the largest one.
Parameters:
lntotaldata integer[]
: Initial integer array.lnupdatedata integer[]
: Integer array to sum up or merge with.lcaggfunc text DEFAULT 'SUM'
: Aggregate function to apply:SUM
: Sum two integer arrays, with adjusting their length.MERGE
: Concatenate two integer arrays.MERGE_UNIQUE
: Merge two integer arrays with eliminating duplicates.MERGE_NNN
: Merge the second array at NNN position (e.g.,MERGE5
).
Returns: integer[]
- Processed integer array.
Examples:
SELECT ub.util_array_integer(ARRAY[5, 2], ARRAY[3, 2, 8], 'SUM');
--> {8,4,8}
SELECT ub.util_array_integer(ARRAY[5, 2], ARRAY[3, 2, 8], 'MERGE');
--> {5,2,3,2,8}
SELECT ub.util_array_integer(ARRAY[5, 2], ARRAY[3, 2, 8], 'MERGE_UNIQUE');
--> {2,3,5,8}
SELECT ub.util_array_integer(ARRAY[5, 2], ARRAY[3, 2, 8], 'MERGE5');
--> {5,2,0,0,3,2,8}
An aggregate function for operations with integer arrays. It uses ub.util_array_integer
internally.
Operations supported (via lcaggfunc
): SUM
, MERGE
, MERGE_UNIQUE
, MERGE_NNN
.
Example (conceptual usage):
-- Assuming a table 'my_integer_data' with a 'counts' column of type integer[]
-- SELECT ub.agg_array_integer(counts, 'MERGE') FROM my_integer_data;
Quickly merges the second float array at a specified position (lnPosID
) of the first float array.
Parameters:
lntotaldata double precision[]
: Initial float array.lnupdatedata double precision[]
: Float array to merge atlnPosID
.lnposid integer
: Position where the second array should be inserted.
Returns: double precision[]
- Merged float array.
Examples:
SELECT ub.util_array_merge(ARRAY[0.5, 2.1], ARRAY[0.3, 2.1, 5.5], 5);
--> {0.5,2.1,0,0,0.3,2.1,5.5}
An aggregate function to merge two float arrays at an arbitrary position. It uses ub.util_array_merge
internally.
Example (conceptual usage):
-- Assuming a table 'events' with a 'measurements' column (double precision[]) and 'start_pos' (integer)
-- SELECT ub.agg_array_merge(measurements, start_pos) FROM events;
These functions provide powerful capabilities for manipulating and querying JSONB data, including merging, transforming, and comparing objects and arrays.
Combines two JSONB arrays based on a specified merge flag. Useful for non-standard merge operations, e.g. with duplicate elimination
Parameters:
ljinitialarray jsonb
: Initial JSONB array.ljmergedarray jsonb
: JSONB array to merge with.lcarrayflag text DEFAULT 'add'
: How to merge arrays:replace
: Replaces theinitial
array with themerged
array.expand
: Adds all new elements from themerged
array to theinitial
array, excluding duplicates (fornumber
,string
,boolean
types).add
: Concatenates all elements from themerged
array to theinitial
array (duplicates are possible). (Default)sub
: Subtracts elements of themerged
array from theinitial
array.intersect
: Calculates common elements in both arrays.
Returns: jsonb
- Processed JSONB array.
Examples:
SELECT ub.util_jsonb_array('[2,3]'::jsonb, '[4,3]'::jsonb, 'expand');
--> [2,3,4]
SELECT ub.util_jsonb_array('[2,3]'::jsonb, '[4,3]'::jsonb, 'replace');
--> [4,3]
SELECT ub.util_jsonb_array('[2,3]'::jsonb, '[4,3]'::jsonb, 'add');
--> [2,3,4,3]
SELECT ub.util_jsonb_array('[2,3,4,5]'::jsonb, '[4,3]'::jsonb, 'sub');
--> [2,5]
SELECT ub.util_jsonb_array('[2,3,4,5]'::jsonb, '[4,3,1]'::jsonb, 'intersect');
--> [3,4]
An aggregate function to process two JSONB arrays. It uses ub.util_jsonb_array
internally.
Operations supported (via lcarrayflag
): replace
, expand
, add
, sub
, intersect
.
Example (conceptual usage):
-- Assuming a table 'log_entries' with a 'tags' column of type jsonb[]
-- SELECT ub.agg_jsonb_array(tags, 'expand') FROM log_entries;
NULL-friendly concatenator of two JSONB objects. If either input is not an object, it defaults to an empty object or returns the valid object.
Parameters:
ljinitialobject jsonb
: Initial JSONB object.ljconcatobject jsonb
: JSONB object to concatenate.
Returns: jsonb
- Concatenated JSONB object.
Examples:
SELECT ub.util_jsonb_concat('{"a":{"b":{"c": 1}}}'::jsonb, '{"a":{"b":{"d": 5}}}'::jsonb);
-- {"a":{"b":{"d": 5}}}
SELECT ub.util_jsonb_concat('{"a":{"b":{"c": 1}}}'::jsonb, NULL::jsonb);
-- {"a":{"b":{"c": 1}}}
SELECT ub.util_jsonb_concat(NULL::jsonb, '{"a":{"b":{"c": 1}}}'::jsonb);
-- {"a":{"b":{"c": 1}}}
An aggregate function to concatenate multiple JSONB objects. It uses ub.util_jsonb_concat
internally.
Example (conceptual usage):
-- Assuming a table 'config_parts' with a 'settings' column of type jsonb
-- SELECT ub.agg_jsonb_concat(settings) FROM config_parts;
Merges JSON objects, arrays, or any JSON type following specific rules:
- An appropriate key in the initial object is expanded with a non-
NULL
value. - If an updated key ends with ".", the appropriate key in the initial object is replaced with the updated value.
- Arrays are merged using the
lcArrayFlag
parameter. string
,number
,boolean
types are replaced.
Useful to merge multi-level objects, e.g. {"a": {"b": {"c": 1}}} and {"a": {"b": {"d": 5}}}
Parameters:
ljinitialobject jsonb
: Initial object or any other JSON type.ljupdatedkeys jsonb
: Object with updated keys and values, or any other JSON type to merge.lcarrayflag text DEFAULT 'expand'
: How to merge arrays:expand
(default): Adds new elements, excluding duplicates.add
: Concatenates all elements.replace
: Replaces the array.
Returns: jsonb
- Expanded/merged object or array.
Examples:
SELECT ub.util_jsonb_merge('{"a": {"b": {"c": 1}}}'::jsonb, '{"a": {"b": {"d": 5}}}'::jsonb, 'expand');
--> {"a": {"b": {"c": 1, "d": 5}}} (objects are expanded)
SELECT ub.util_jsonb_merge('{"a.b": {"c": 5}}'::jsonb, '{"a.b": {"d": 8}}'::jsonb, 'expand');
--> {"a.b": {"c": 5, "d": 8}} (objects are expanded)
SELECT ub.util_jsonb_merge('{"a": {"c": 5, "d": [1,2]}}'::jsonb, '{"a": {"b": 8, "d": [3,4]}}'::jsonb, 'replace');
--> {"a":{"b":8,"c":5,"d":[3,4]}} (arrays are replaced)
SELECT ub.util_jsonb_merge('{"a": {"c": 5, "d": [1,2]}}'::jsonb, '{"a": {"b": 8, "d": [3,4]}}'::jsonb, 'add');
--> {"a":{"b":8,"c":5,"d":[1,2,3,4]}} (arrays are concatenated)
An aggregate function to merge two multi-level JSONB objects or arrays. It uses ub.util_jsonb_merge
internally.
Operations supported (via lcarrayflag
): expand
, add
, replace
.
Example (conceptual usage):
-- Assuming a table 'user_profiles' with a 'profile_data' column of type jsonb
-- SELECT ub.agg_jsonb_merge(profile_data, 'expand') FROM user_profiles;
Concatenates two JSONB objects and sets any keys present only in the initial object to NULL
in the result.
Parameters:
ljinitialobject jsonb
: Initial JSONB object.ljconcatobject jsonb
: JSONB object to concatenate.
Returns: jsonb
- Concatenated JSONB object with old keys set to NULL
if not present in the new object.
Examples:
SELECT ub.util_jsonb_merge_null('{"a": 1, "b": 2}'::jsonb, '{"b": 3}'::jsonb);
--> {"a": null, "b": 3}
Processes multiple JSONB arrays, considering NULL
values and specified merge rules.
Parameters:
lcarrayflag text
: How to merge arrays:expand
: Adds all new elements, excluding duplicates.add
: Concatenates all elements.sub
: Subtracts elements.intersect
: Calculates common elements.
VARIADIC ljarray jsonb[]
: A variadic array of JSONB arrays to process.
Returns: jsonb
- Processed JSONB array.
Examples:
SELECT ub.util_jsonb_multi_array('expand', '[2,3]'::jsonb, '[4,3]'::jsonb, '[5,3,2]'::jsonb);
--> [2,3,4,5]
SELECT ub.util_jsonb_multi_array('add', '[2,3]'::jsonb, '[4,3]'::jsonb, '[5,3,2]'::jsonb);
--> [2,3,4,3,5,3,2]
SELECT ub.util_jsonb_multi_array('intersect', '[2,3]'::jsonb, '[4,3]'::jsonb, '[5,3,2]'::jsonb);
--> [3]
Concatenates multiple JSONB objects, handling NULL
values.
Parameters:
VARIADIC ljobject jsonb[]
: A variadic array of JSONB objects to concatenate.
Returns: jsonb
- Concatenated JSONB object.
Examples:
SELECT ub.util_jsonb_multi_concat('{"a": 1}'::jsonb, '{"b": 2}'::jsonb, NULL::jsonb, '{"c": 3}'::jsonb);
--> {"a": 1, "b": 2, "c": 3}
Merges multiple JSON objects, arrays, or any JSON type following specific rules, similar to ub.util_jsonb_merge
but for multiple inputs.
Parameters:
lcarrayflag text
: How to merge arrays:expand
(default): Adds new elements, excluding duplicates.add
: Concatenates all elements.replace
: Replaces the array.
VARIADIC ljdata jsonb[]
: A variadic array of JSONB data (objects, arrays, or other types) to merge.
Returns: jsonb
- Merged JSONB data.
Examples:
SELECT ub.util_jsonb_multi_merge('expand', '{"a": {"b": {"c": 1}}}'::jsonb, '{"a": {"b": {"d": 5}}}'::jsonb, '{"a": {"b": {"f": 5}}}'::jsonb);
--> {"a":{"b":{"c":1,"d":5,"f":5}}} (objects are expanded)
SELECT ub.util_jsonb_multi_merge('replace', '{"a": {"c": 5, "d": [1,2], "e": [2,3]}}'::jsonb, '{"a": {"b": 8, "d": [3,4]}}'::jsonb, '{"a": {"b": 8, "e": [5,6]}}'::jsonb);
--> {"a":{"b":8,"c":5,"d":[3,4],"e":[5,6]}} (arrays are replaced)
SELECT ub.util_jsonb_multi_merge('add', '{"a": {"c": 5, "d": [1,2]}}'::jsonb, '{"a": {"b": 8, "d": [3,4]}}'::jsonb, '{"a": {"b": 8, "d": [5,6]}}'::jsonb);
--> {"a":{"b":8,"c":5,"d":[1,2,3,4,5,6]}} (arrays are concatenated)
Converts a flattened JSONB object (e.g., {"key1.key2.key3": value}
) into a nested JSONB object (e.g., {"key1": {"key2": {"key3": value}}}
).
Parameters:
ljinitial jsonb
: Initial JSONB object to nest.lcarrayflag text DEFAULT 'replace'
: How to merge arrays within the nesting process:replace
(default): Replaces arrays.expand
: Adds new elements, excluding duplicates.add
: Concatenates all elements.
Returns: jsonb
- Nested JSONB object.
Examples:
SELECT ub.util_jsonb_nest('{"a.b.c": 1, "a.b.d": 5}'::jsonb);
-- {"a":{"b":{"c":1,"d":5}}}
SELECT ub.util_jsonb_nest('{"a.b.c": [1,2], "a.b": {"c": [2,3]}}'::jsonb, 'add');
-- {"a":{"b":{"c":[2,3,1,2]}}}
SELECT ub.util_jsonb_nest('{"a.b.c": 1, "\"a.b.d\"": 5}'::jsonb);
-- {"a":{"b":{"c":1}},"a.b.d":5}
Converts a nested JSONB object (e.g., {"key1": {"key2": {"key3": value}}}
) into a flattened JSONB object (e.g., {"key1.key2.key3": value}
). Supports custom key prefixes and delimiters.
Parameters:
ljinitial jsonb
: Initial JSONB object to unnest.lckeyprefix text DEFAULT NULL
: Key prefix for the keys in the output object.lcdelimiter text DEFAULT '.'
: Delimiter to use between nested keys.
Returns: jsonb
- Unnested JSONB object.
Examples:
SELECT ub.util_jsonb_unnest('{"a":{"b":{"c": 1, "d": 5}}}'::jsonb);
-- {"a.b.c":1,"a.b.d":5}
SELECT ub.util_jsonb_unnest('{"a":{"b":{"c": 1, "d": 5}}}'::jsonb, 'prefix_', '#');
-- {"prefix_#a#b.c":1,"prefix_#a#b.d":5}
Updates a JSONB object with new values at specified paths. It supports various path syntaxes, including dot notation, quoted keys, and JSONPath expressions for arrays. Useful to update json attributes inside multi-level objects and/or arrays
Parameters:
ljinitialobject jsonb
: Initial JSONB object to update.ljpathvalue jsonb
: An object where keys represent paths and values are the new data.- Special Keys:
"*"
: Replaces the entire initial object with its value."||"
: Expands the initial object usingub.util_jsonb_merge
(replace mode).
- Path Syntax:
a.b.c
: Standard dot notation."a.b".c
: Quoted key (e.g., a key named "a.b").(($.array_key[*] ? (@.id == 2)).nested_array[*] ? (@.sub_id == 1)).final_key
: JSONPath for array elements.- Path ending in
null
: Deletes the element. - Path with
id == 0
: Inserts a new element into an array (requires an 'id' field in the new object to be assigned automatically).
- Special Keys:
Returns: jsonb
- Updated JSONB object.
Examples:
SELECT ub.util_jsonb_update('{"a":{"b":{"c": 1}, "f": 10}}'::jsonb, '{"a.b":{"d": 5}}'::jsonb);
--> {"a":{"b":{"d":5},"f":10}} (update at specific json path)
SELECT ub.util_jsonb_update(
'{"a":[{"id": 1, "b": 1}, {"id": 2, "b": [{"id": 1, "f": 3}] }]}'::jsonb,
'{"(($.a[*] ? (@.id == 2)).b[*] ? (@.id == 1)).g": 10}'::jsonb
);
--> {"a":[{"id":1, "b":1}, {"id":2, "b":[{"f":3,"g":10,"id":1}]}]} (update keys in the object at specific jsonpath)
SELECT ub.util_jsonb_update(
'{"a":[{"id": 1, "b": 1}, {"id": 2, "b": [{"id": 1, "f": 3}] }]}'::jsonb,
'{"(($.a[*] ? (@.id == 2)).b[*] ? (@.id == 1))": {"id": 1, "a": 10} }'::jsonb
);
--> {"a":[{"b":1, "id":1}, {"b":[{"a":10,"id":1}], "id":2}]} (replace object at specific jsonpath)
SELECT ub.util_jsonb_update(
'{"a":[{"id": 1, "b": 1}, {"id": 2, "b": [{"id": 1, "f": 3}] }] }'::jsonb,
'{"(($.a[*] ? (@.id == 2)).b[*] ? (@.id == 0 && 17689 > 0))": {"f": 5}}'::jsonb
);
--> {"a":[{"b":1,"id":1}, {"b":[{"f":3,"id":1},{"f":5,"id":2}], "id":2}]} (add object at specific jsonpath. Add a random value (e.g. 17689) to keep the whole key name unique)
SELECT ub.util_jsonb_update(
'{"a":[{"id": 1, "b": 1}, {"id": 2, "b": [{"id": 1, "f": 3}, {"id": 2, "f": 10}]}]}'::jsonb,
'{"(($.a[*] ? (@.id == 2)).b[*] ? (@.id == 1))": null}'::jsonb
);
--> {"a":[{"b":1,"id":1},{"b":[{"f":10,"id":2}],"id":2}]} (delete object at specific jsonpath)
SELECT ub.util_jsonb_update(
'{"a":{"b":{"c": 1}}}'::jsonb,
'{"*":{"d": 5}}'::jsonb
);
--> {"d": 5} (replace with a new object)
SELECT ub.util_jsonb_update(
'{"a":{"b":{"c": 1}}}'::jsonb,
'{"||":{"a": {"b": {"d": 5}}}}'::jsonb
);
--> {"a":{"b":{"c": 1, "d": 5}}} (expand the initial object)
Prepares a list of keys in the "updated object" that differ from the same keys in the "initial object".
Parameters:
ljinitialobject jsonb
: Initial JSONB object.ljupdatedobject jsonb
: Updated JSONB object.lcarrayflag text DEFAULT 'order_no_matter'
: Flag determining how arrays are compared:order_no_matter
(default): Order of elements in arrays does not matter for comparison.order_matter
: Order of elements in arrays matters for comparison.
Returns: jsonb
- An object containing only the keys and values from ljupdatedobject
that are different from ljinitialobject
. Returns NULL
if no differences.
Examples:
SELECT ub.util_jsonb_differ('{"a":{"b":{"c": 1}}}'::jsonb, '{"a.b.c": 1}'::jsonb);
--> null (no new keys)
SELECT ub.util_jsonb_differ('{"a": [2, 3], "b": 10, "d": 20}'::jsonb, '{"a": [3, 4], "b": 10}'::jsonb);
--> {"a": [3, 4]}
SELECT ub.util_jsonb_differ('{"a": [2, 3], "b": 10}'::jsonb, '{"a": [3, 4], "b": 10}'::jsonb, 'order_no_matter');
--> null (no new keys)
SELECT ub.util_jsonb_differ('{"a": [2, 3], "b": 10}'::jsonb, '{"a": [3, 4], "b": 10}'::jsonb, 'order_matter');
--> {"a": [3, 4]}
Processes a JSONB object or array with various specific rules defined by the lcaction
parameter. This is a multi-purpose function combining several complex JSONB transformations.
Parameters:
ljinitialobject jsonb
: Initial object or array.ljprocessdata jsonb
: Object or array with process rules (specific to each action).lcaction text DEFAULT 'OBJECT'
: Action to perform:JSON_TO_PLAIN_ARRAY
: Convert any JSON with nested arrays into a plain array of objects.JSON_DIFFERENCE
: Compare two JSON objects and build an array of objects detailing their differences.CHILDREN_FROM_PLAIN_ARRAY
: Build a nested structure from a plain array of objects.
Returns: jsonb
- Processed object or array.
Converts any JSON (object or array) with nested arrays into a plain array of objects, each with prefix
, path
, child
, order
, and value
keys.
Useful to convert jsonb object into table for further processing
ljinitialobject
: JSON object or array of objects to unnest.
ljprocessdata
: (Internal usage)
* path
(array): Path (text array) to JSON array to unnest.
* prefix
(string): Calculated array prefix, e.g. "a:b".
Result Structure:
prefix
(string): Key prefixes to the array, via colon.path
(array): Path (text array) to JSON array.child
(array): List of keys with "array" JSON type.order
(number): Position of the object in the array (NULL for top-level object).value
(object): Object with non-array keys.
Example:
SELECT ub.util_jsonb_process(
'{ "foo": [ {"a": [{"b": 1}, {"b": 2}]} ], "bar": "info" }'::jsonb,
NULL::jsonb,
'JSON_TO_PLAIN_ARRAY'
);
-->
[
{ "prefix": "", "path": [], "child": ["foo"], "value": { "bar": "info" } },
{ "prefix": "foo", "path": ["foo"], "child": ["a"], "order": 1, "value": {} },
{ "prefix": "foo:a", "path": ["foo", "1", "a"], "child": [], "order": 1, "value": {"b": 1} },
{ "prefix": "foo:a", "path": ["foo", "1", "a"], "child": [], "order": 2, "value": {"b": 2} }
]
Compares two JSON objects (or arrays of objects) and builds an array of objects detailing the differences. Useful for unit-tests to compare expected and actual responses of any function
ljinitialobject
: "Left" JSON object or array of objects (expected values).
ljprocessdata
: "Right" JSON object or array of objects (result values).
Result Structure:
path
(array): Path to an object with differences, e.g.,["foo", "2", "bar"]
.order
(number): Array position of the object with differences.key
(string): Object key with differences.expected
(any): Expected value.result
(any): Result value.expectedType
(string|null): Type of the expected value (if types differ).resultType
(string|null): Type of the result value (if types differ).
Example:
SELECT ub.util_jsonb_process(
'{"a": [2, 3], "b": [{"f": 10}, {"f": 20}], "d": 20}'::jsonb,
'{"a": [3, 4], "b": [{"f": 20}, {"f": 30}], "d": 20}'::jsonb,
'JSON_DIFFERENCE'
);
-->
[
{"key":"a", "path":[], "order":null, "result":[3,4], "expected":[2,3]},
{"key":"f", "path":["b"], "order":1, "result":20, "expected":10},
{"key":"f", "path":["b"], "order":2, "result":30, "expected":20}
]
Builds a nested structure from a plain array of objects like { "key", "value", "parentKey" }
.
Useful to build tree tables
ljinitialobject
: Array of objects to nest. Each object should have:
* key
(number|string|object): Unique key of the object.
* value
(object): List of keys with values to store (this object will be the content of the node).
* parentKey
(number|string|object|null): Parent key of the object (NULL
for root elements).
ljprocessdata
: Settings for the action.
* childKey
(string|null): Key name for the array with children data (defaults to "children"
).
* parentKey
(string|null): Parent key value to build data (used for recursion).
* preparedKeys
(array|null): List of already prepared parent keys to exclude loops (used for recursion).
Returns: jsonb
- JSON with children data, typically an array of objects.
Example:
SELECT ub.util_jsonb_process(
'
[
{ "key": "01", "value": { "info": "foo" }, "parentKey": null },
{ "key": "02", "value": { "info": "bar" }, "parentKey": "01" },
{ "key": "03", "value": { "info": "baz" }, "parentKey": "02" }
]
'::jsonb,
NULL::jsonb,
'CHILDREN_FROM_PLAIN_ARRAY'
);
--> [{"info": "foo", "children": [{"info": "bar", "children": [{"info": "baz"}]}]}]
These functions provide tools for modifying data types and values, and for building dynamic text templates. Useful for input validation and data type / format transformations, e.g. store a date or a datetime as a number for easy comparison and sort
Processes a given value with a set of modifier rules, allowing for type conversion, formatting, validation, and string transformations.
Parameters:
ljinput jsonb
: An object containing:value
: The initial value to be processed (can be any JSON type).modifier
: A JSONB array of modifier rules, each a JSONB object with the following potential keys:type
(string): Type of modification (f_...
for format,v_...
for validate,s_...
for string,a_...
for array).format
(string): Any valid format for the type (e.g., date formats,password
for string,number:<true_val>:<false_val>
for checkbox).delimiter
(string): Delimiter to split/aggregate strings from arrays/objects (e.g.,\n
for newline).timeZone
(string): 3-letter time zone for timestamp calculations (e.g.,GMT
).pretty
(number):1
to applyjsonb_pretty()
(forf_object
,f_array
).strip
(number):1
to applyjsonb_strip_nulls()
(forf_object
,f_array
).regex
(string): Regular expression for string transformations.from
(string): Regex pattern to replace (fors_regex_replace
).to
(string): Replacement string (fors_regex_replace
).flag
(string): Regex flags (e.g.,g
) (fors_regex_replace
).btrim
(string): Characters to trim (fors_btrim
).default
(string): Default value fors_nulls_to_string
.validator
(object|null): Validation rules forv_
types:jsonpath
(string): JSONPath expression (e.g.,"$ > 0 && $ < 100"
).maxLength
(number): Maximal length of the value.
Returns: jsonb
- A JSONB object:
result
(any): The modified value if successful.message
(string): Details on invalid input if validation fails (e.g.,invalid_number
,invalid_jsonpath
,invalid_max_length
,invalid_date
,invalid_datetime
,invalid_object
,invalid_array
).error
(object): Containscode
,message
, anddetails
if an internal error occurs.
Examples:
-- Example: format a number
SELECT ub.util_data_modifier(jsonb_build_object(
'value', '25',
'modifier', '[{"type": "f_number", "format": "FM999,999.00"}]'::jsonb
));
--> { "result": "25.00" }
-- Example: convert and format date from date_2000
SELECT ub.util_data_modifier(jsonb_build_object(
'value', '7300',
'modifier', '[{"type": "f_date", "format": "DD Mon YYYY"}]'::jsonb
));
--> { "result": "27 Dec 2019" }
-- Example: split array into elements
SELECT ub.util_data_modifier(jsonb_build_object(
'value', jsonb_build_array('foo', 'bar'),
'modifier', '[{"type": "f_string", "delimiter": "\n"}]'::jsonb
));
--> { "result": "foo\nbar" }
-- Example: "p1d" period into seconds
SELECT ub.util_data_modifier(jsonb_build_object(
'value', 'p1w',
'modifier', '[{"type": "f_period"}]'::jsonb
));
--> { "result": 604800 }
-- Example: validate text using jsonpath expression
SELECT ub.util_data_modifier(jsonb_build_object(
'value', 'my text',
'modifier', '[{"type": "v_string", "validator": {"jsonpath": "$ like_regex \"^a\""}}]'::jsonb
));
--> { "message": "invalid_jsonpath" }
Supported types and parameters:
| Type | Description | Parameters |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------|
| f_number | convert data to "number" format | `"format":` any format for "number" type |
| f_checkbox | convert true / false to any values | `"format":` "number<:true><:false>" \| "boolean<:true><:false>" |
| f_string | convert data to "string" format | `"format":` "password", `"delimiter"` => build string with delimiters from array \| object |
| f_object | convert data to "object" format | `"pretty":` 1 => jsonb_pretty(), `"strip":` 1 => strip nulls |
| f_array | convert data to "array" format | `"pretty":` 1 => jsonb_pretty(),`"strip":` 1 => strip nulls |
| f_date | convert date_iso \| date_2000 to "date" format | `"format":` any format for "date" type, `"null_to_1970":` null date=>1970-01-01 |
| f_date_iso | convert date from any format to YYYY-MM-DD | `"format":` any format for "date" type, `"null_to_1970":` null date=>1970-01-01 |
| f_timestamp | convert data to "timestamp" format | `"format":` any format for "timestamp" type |
| | | `"timeZone":` "3-letters timezone",`"null_to_1970":` null date=>1970-01-01 |
| f_date_2000 | convert to "date_iso" format, | `"format":` any format for "date" type |
| | then calculate amount of days after 2000-01-01 | `"format":` any format for "date" type |
| f_unix_timestamp | convert data to UNIX timestamp format | `"format":` any format for "timestamp" type |
| | (seconds since 1970-01-01) | |
| f_period | convert "period" format to amount of seconds | `"period":` "100s", "p14d", "p1y", etc |
| s_lower | string transformation | |
| s_upper | string transformation | |
| s_initcap | string transformation | |
| s_btrim | btrim operation | `"btrim":` symbols to trim |
| s_regexp_match | regex transformation | `"regex":` regex expression |
| s_regex_replace | regex transformation | `"from"`, `"to"`, `"flag":` regexp_replace() parameters |
| s_split` | string to array using regex | `"regex":` regex expression |
| s_nulls_to_string| convert all nulls to strings | `"default":` <any value> ("" by default) |
| v_number | convert and validate "number" type | `"validator":` { "jsonpath": "$ > 0" }` |
| v_string | convert and validate "string" type | `"format":` null | "html" (remove <script>, <embed>, <iframe> and similar tags) |
| v_string | | `"validator":` { "jsonpath": "$ like_regex \"^A\"", "maxLength": 256 }` |
| v_date_2000 | validate "date" type and convert to amount of days | `"format":` "<any date format>"` |
| | after 2000-01-01 | |
| v_unix_timestamp | convert "timestamp" type to UNIX timestamp | `"format":` "<any date & time format>"` |
| v_object | convert and validate "object" type | `"validator":` { "jsonpath": "$.a == 1", "maxLength": 1024 }` |
| v_array | convert and validate "object" type | `"validator":` { "jsonpath": "$[*] == 10", "maxLength": 4096 }` |
Converts a template string with placeholders (
{$.<key>}
) and control statements ({$if:}
,{$for:}
) into a final text using parameters from asourceMapping
object. Supports nested statements. Useful to build dynamic HTML templates (e-mails, posts), markdown documents and any other text documents
Parameters:
ljinput jsonb
: An object containing:template
(string|object|array): The template string or object or array with{$<statement>}
and{$.<key>}
insertions.sourceMapping
(object|array): Source data to use for the template processing (key-value pairs for placeholders).data
(array|null): (Internal use for recursive calls) Array of statements and data within them.firstRow
(number|null): (Internal use for recursive calls) Initial row to processdata
(starting with 0).
Template Syntax & Statements:
{$.<key>}
: Inserts the value of<key>
fromsourceMapping
. Supports default values:{$.<key>:<default_value>}
.{$if:<jsonpath condition>}
: Conditional block. Ifjsonpath condition
evaluates to true againstsourceMapping
, the block content is processed.{$elseif:<jsonpath condition>}
: Alternative conditional block after anif
.{$else}
: Default block if no previousif
orelseif
matched.{$for:<array key>}
: Loop through elements of an array specified byarray key
(JSONPath). Inside the loop,sourceMapping
is updated with the current array element, allowing access like{$.array_name.element_key}
.{$end}
: Ends anif
orfor
statement block.
Returns: jsonb
- A JSONB object:
result
(string): The processed template text.lastRow
(number|null): Last processed row (for internal/recursive calls).error
(object): Containscode
,message
, anddetails
if an internal error occurs.
Examples:
-- Enrich jsonb object with data from sourceMapping.
SELECT ub.util_build_template(jsonb_build_object(
'template', '{"title": "{$if:$.role_id == \"premium\"}Special offer{$else}Basic offer{$end} {$.price:200}"}'::jsonb,
'sourceMapping', '{"role_id": "premium", "price": 100}'::jsonb
))
--> {"result": {"title":"Special offer 100"}}
-- Build text template, with if and loop conditions
SELECT ub.util_build_template(jsonb_build_object(
'template',
'
{$if:$.a == 2}
First
{$if:$.a == 1}
Case 1
{$elseif:$.a == 3}
Case 3
{$elseif:$.a == 2}
Case
{$if:$.b > 2}
check
{$end}
2
{$else}
Unknown case
{$end}
{$elseif:$.a == 1}
First 2
{$else}
Unknown case
{$end}
My template
{$.c + $.b}
Template text
{$if:$.c == 2}
{$for:$.v1[*]}
Cycle
{$if:$.a == 2}
{$.v1.n}
{$else}
{$.v1.m}
{$end}
demo
{$end}
{$end}
Template bottom
{$if:$.b > 0 && $.c == 2}
Test
{$if:$.a == 1}
Case 1
{$elseif:$.a == 3}
Case 3
{$elseif:$.a == 2}
Case
{$if:$.b > 2}
check
{$end}
2
{$else}
Unknown case
{$end}
text
{$end}
',
'sourceMapping',
'{
"a":2,
"b":3,
"c":2,
"v1": [
{"m":"text1","n":"next1"},
{"m":"text2","n":"next2"}
]
}'::jsonb
));
-->
First
Case
check
2
My template
5
Template text
Cycle
next1
demo
Cycle
next2
demo
Template bottom
Test
Case
check
2
text
Functions related to JWT (JSON Web Tokens) and cron-like scheduling.
Provides utilities for JWT (JSON Web Token) processing. Requires the pgcrypto
extension.
Easy to sign and verify JWT
Parameters:
ljinput jsonb
: An object containing:mode
(string): Operation mode:jwt_sign
: Signs a JWT based on JSON payload, secret key, and algorithm.jwt_verify
: Verifies a JWT string and returns its header, payload, and validity status.jwt_encode
: Encodes a bytea value into base64url format (used internally).jwt_decode
: Decodes a base64url string into bytea (used internally).jwt_generate
: Generates a JWT signature for a given value using a secret and algorithm (used internally).
jwtValue
(string): The JWT string or base64 string, depending on the mode.jwtPayload
(object): The JSON object to be used as the JWT payload (forjwt_sign
).jwtSecret
(string): The secret key for signing/verification.jwtAlgorithm
(string): The encryption algorithm (sha256
(default),sha384
,sha512
).sessionData
(object): (Optional) Any session-related data.
Returns: jsonb
- An object containing:
jwtValue
(string): The resulting JWT string or base64 encoded value.jwtPayload
(object): The decoded JWT payload (forjwt_verify
).jwtHeader
(string): The decoded JWT header (forjwt_verify
).jwtValid
(number):1
if the JWT is valid,0
otherwise (forjwt_verify
).
Examples:
SELECT ub.util_jwt('{"mode": "jwt_sign", "jwtPayload": {"a": 1}, "jwtSecret": "1234"}');
--> { "jwtValue": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhIjogMX0.3aKAFdFca4DozVrKxqgcGPZik8erGRtdbTipg8Hk9Ao" }
SELECT ub.util_jwt('{"mode": "jwt_verify", "jwtValue": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhIjogMX0.3aKAFdFca4DozVrKxqgcGPZik8erGRtdbTipg8Hk9Ao", "jwtSecret": "1234"}');
-->
{
"jwtValid": 1,
"jwtHeader": {"alg": "HS256", "typ": "JWT" },
"jwtPayload": { "a": 1}
}
Calculates the next UNIX timestamp based on a crontab expression. Useful for CRON and any other scheduled tasks
Parameters:
crontab_expr text
: The crontab expression string. Positions are:- Seconds
- Minutes
- Hours
- Day of month
- Month
- Day of week
Allowed special characters:
,
,-
,*
,/
.
Returns: double precision
- UNIX timestamp (at UTC) of the next event, or NULL
if the expression is invalid.
Examples:
SELECT ub.util_process_crontab('5 * * * * * '); -- every minute at 5th second
--> 1762090925 (value depends on the current timestamp)
SELECT ub.util_process_crontab('*/5 * * * * * '); -- every 5 seconds
--> 1762092675 (value depends on the current timestamp)
SELECT ub.util_process_crontab('* * 5,10,15 * * *'); -- every day at 5 a.m., 10 a.m. and 3 p.m. UTC
--> 1762092600 (value depends on the current timestamp)
SELECT ub.util_process_crontab('* * 3 * * MON,WED,FRI'); -- at 3 a.m. on Monday, Wednesday and Friday
--> 1762092600 (value depends on the current timestamp)
A universal function for validating various data types and formats.
A universal verificator to check if an input text matches a specified type or format. Useful to check format of a text variable without processing an SQL error
Parameters:
lcinput text
: The input text to verify.lcformat text
: The type or format to validate against:JSON
: General JSON format.JSONOBJECT
: JSON object format.JSONARRAY
: JSON array format.JSONPATH
: JSONPath expression format.TSQUERY
: Text search query format.DATE_<format>
: Date in a specified format (e.g.,DATE_YYYY-MM-DD
).DATETIME_<format>
: Datetime in a specified format (e.g.,DATETIME_YYYY-MM-DD HH24:MI:SS
).TIME
: Time format.BASE64
: Base64 encoded string format.EMAIL
: Email address format.URL
: URL format.EXT
: Checks if a PostgreSQL extension (namedlcinput
) is installed.
Returns: text
- "TRUE"
if the input is valid for the given format, "FALSE"
otherwise.
Examples:
SELECT ub.util_verificator('[{2,3]', 'JSON');
--> "FALSE"
SELECT ub.util_verificator('[2,3]', 'JSONARRAY');
--> "TRUE"
SELECT ub.util_verificator('12.10.2020', 'DATE_YYYY-MM-DD');
--> "FALSE"
SELECT ub.util_verificator('https://google.com', 'URL');
--> "TRUE"
SELECT ub.util_verificator('$.a = "check', 'JSONPATH');
--> "FALSE"