Update Function JSON_TYPE

This commit is contained in:
2026-02-25 23:01:22 +00:00
parent 785a96e392
commit 55a4a05960

View File

@@ -1 +1,103 @@
@\@^@
SET PATH *LIBL ;
CREATE OR REPLACE FUNCTION CISTOOLS.JSON_TYPE (
INJSON CLOB(2097152) )
RETURNS VARCHAR(20)
LANGUAGE SQL
SPECIFIC CISTOOLS.JSON_TYPE
DETERMINISTIC
READS SQL DATA
CALLED ON NULL INPUT
NO EXTERNAL ACTION
SET OPTION ALWBLK = *ALLREAD ,
ALWCPYDTA = *OPTIMIZE ,
COMMIT = *NONE ,
DECRESULT = (31, 31, 00) ,
DYNDFTCOL = *NO ,
DYNUSRPRF = *USER ,
SRTSEQ = *HEX
BEGIN
DECLARE V CLOB ( 2 M ) ;
DECLARE T VARCHAR ( 20 ) ;
DECLARE DUMMYC CLOB ( 2 M ) ;
DECLARE DUMMYV VARCHAR ( 1 ) ;
DECLARE BAD SMALLINT DEFAULT 0 ;
-- Ultra-safe: never throw, always return a type (or 'invalid')
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET BAD = 1 ;
SET V = TRIM ( INJSON ) ;
IF V IS NULL
OR V = '' THEN
RETURN 'null' ;
END IF ;
-- Strict JSON null keyword
IF REGEXP_LIKE ( V , '^(?i)null$' ) THEN
RETURN 'null' ;
END IF ;
/* ============================================================
Phase 1: Fast REGEXP classification (shape + scalar patterns)
Phase 2: Validate with JSON parser (JSON_QUERY / JSON_VALUE)
If parser fails => return 'invalid'
============================================================ */
-- OBJECT
IF REGEXP_LIKE ( V , '^\{.*\}$' , 'n' ) THEN
SET T = 'object' ;
-- JSON_QUERY returns JSON text for objects/arrays; will throw if invalid JSON
SET DUMMYC = JSON_QUERY ( V , '$' ) ;
IF BAD = 1
OR DUMMYC IS NULL THEN
RETURN 'invalid' ;
END IF ;
RETURN T ;
END IF ;
-- ARRAY
IF REGEXP_LIKE ( V , '^\[.*\]$' , 'n' ) THEN
SET T = 'array' ;
SET DUMMYC = JSON_QUERY ( V , '$' ) ;
IF BAD = 1
OR DUMMYC IS NULL THEN
RETURN 'invalid' ;
END IF ;
RETURN T ;
END IF ;
-- STRING (JSON-escaped)
IF REGEXP_LIKE ( V , '^"(\\.|[^"\\])*"$' ) THEN
SET T = 'string' ;
-- JSON_VALUE parses scalar and returns SQL scalar; throws on invalid JSON
SET DUMMYV = SUBSTR ( COALESCE ( JSON_VALUE ( V , '$' ) , '' ) , 1 , 1 ) ;
IF BAD = 1 THEN
RETURN 'invalid' ;
END IF ;
RETURN T ;
END IF ;
-- BOOLEAN
IF REGEXP_LIKE ( V , '^(?i:true|false)$' ) THEN
SET T = 'boolean' ;
SET DUMMYV = SUBSTR ( COALESCE ( JSON_VALUE ( V , '$' ) , '' ) , 1 , 1 ) ;
IF BAD = 1 THEN
RETURN 'invalid' ;
END IF ;
RETURN T ;
END IF ;
-- NUMBER (RFC-like)
IF REGEXP_LIKE ( V , '^-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?$' )
THEN
SET T = 'number' ;
-- Validate as JSON scalar
SET DUMMYV = SUBSTR ( COALESCE ( JSON_VALUE ( V , '$' ) , '' ) , 1 , 1 ) ;
IF BAD = 1 THEN
RETURN 'invalid' ;
END IF ;
RETURN T ;
END IF ;
-- Anything else is not valid JSON text
RETURN 'invalid' ;
END ;
GRANT ALTER , EXECUTE
ON SPECIFIC FUNCTION CISTOOLS.JSON_TYPE
TO AMAPICS WITH GRANT OPTION ;
GRANT EXECUTE
ON SPECIFIC FUNCTION CISTOOLS.JSON_TYPE
TO PUBLIC ;