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_arrayub.agg_jsonb_arrayub.util_jsonb_concatub.agg_jsonb_concatub.util_jsonb_mergeub.agg_jsonb_mergeub.util_jsonb_merge_nullub.util_jsonb_multi_arrayub.util_jsonb_multi_concatub.util_jsonb_multi_mergeub.util_jsonb_nestub.util_jsonb_unnestub.util_jsonb_updateub.util_jsonb_differub.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 theinitialarray with themergedarray.expand: Adds all new elements from themergedarray to theinitialarray, excluding duplicates (fornumber,string,booleantypes).add: Concatenates all elements from themergedarray to theinitialarray (duplicates are possible). (Default)sub: Subtracts elements of themergedarray from theinitialarray.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-
NULLvalue. - If an updated key ends with ".", the appropriate key in the initial object is replaced with the updated value.
- Arrays are merged using the
lcArrayFlagparameter. string,number,booleantypes 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,passwordfor string,number:<true_val>:<false_val>for checkbox).delimiter(string): Delimiter to split/aggregate strings from arrays/objects (e.g.,\nfor newline).timeZone(string): 3-letter time zone for timestamp calculations (e.g.,GMT).pretty(number):1to applyjsonb_pretty()(forf_object,f_array).strip(number):1to 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, anddetailsif 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 asourceMappingobject. 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 conditionevaluates to true againstsourceMapping, the block content is processed.{$elseif:<jsonpath condition>}: Alternative conditional block after anif.{$else}: Default block if no previousiforelseifmatched.{$for:<array key>}: Loop through elements of an array specified byarray key(JSONPath). Inside the loop,sourceMappingis updated with the current array element, allowing access like{$.array_name.element_key}.{$end}: Ends aniforforstatement 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, anddetailsif 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
textFunctions 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):1if the JWT is valid,0otherwise (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"