extracted objects
This commit is contained in:
727
docs/packages/PLJSON_PRINTER.md
Normal file
727
docs/packages/PLJSON_PRINTER.md
Normal file
@@ -0,0 +1,727 @@
|
||||
# PLJSON_PRINTER
|
||||
|
||||
## Package Specification
|
||||
|
||||
```sql
|
||||
package pljson_printer as
|
||||
/*
|
||||
Copyright (c) 2010 Jonas Krogsboell
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
indent_string varchar2(10 char) := ' '; --chr(9); for tab
|
||||
newline_char varchar2(2 char) := chr(13)||chr(10); -- Windows style
|
||||
--newline_char varchar2(2) := chr(10); -- Mac style
|
||||
--newline_char varchar2(2) := chr(13); -- Linux style
|
||||
ascii_output boolean not null := true;
|
||||
empty_string_as_null boolean not null := false;
|
||||
escape_solidus boolean not null := false;
|
||||
|
||||
function pretty_print(obj pljson, spaces boolean default true, line_length number default 0) return varchar2;
|
||||
function pretty_print_list(obj pljson_list, spaces boolean default true, line_length number default 0) return varchar2;
|
||||
function pretty_print_any(json_part pljson_element, spaces boolean default true, line_length number default 0) return varchar2;
|
||||
procedure pretty_print(obj pljson, spaces boolean default true, buf in out nocopy clob, line_length number default 0, erase_clob boolean default true);
|
||||
procedure pretty_print_list(obj pljson_list, spaces boolean default true, buf in out nocopy clob, line_length number default 0, erase_clob boolean default true);
|
||||
procedure pretty_print_any(json_part pljson_element, spaces boolean default true, buf in out nocopy clob, line_length number default 0, erase_clob boolean default true);
|
||||
|
||||
procedure dbms_output_clob(my_clob clob, delim varchar2, jsonp varchar2 default null);
|
||||
procedure htp_output_clob(my_clob clob, jsonp varchar2 default null);
|
||||
-- made public just for testing/profiling...
|
||||
function escapeString(str varchar2) return varchar2;
|
||||
|
||||
end pljson_printer;```
|
||||
|
||||
## Package Body
|
||||
|
||||
```sql
|
||||
package body pljson_printer as
|
||||
max_line_len number := 0;
|
||||
cur_line_len number := 0;
|
||||
|
||||
-- associative array used inside escapeString to cache the escaped version of every character
|
||||
-- escaped so far (example: char_map('"') contains the '\"' string)
|
||||
-- (if the character does not need to be escaped, the character is stored unchanged in the array itself)
|
||||
-- type Rmap_char is record(buf varchar2(40), len integer);
|
||||
type Tmap_char_string is table of varchar2(40) index by varchar2(1 char); /* index by unicode char */
|
||||
char_map Tmap_char_string;
|
||||
-- since char_map the associative array is a global variable reused across multiple calls to escapeString,
|
||||
-- i need to be able to detect that the escape_solidus or ascii_output global parameters have been changed,
|
||||
-- in order to clear it and avoid using escape sequences that have been cached using the previous values
|
||||
char_map_escape_solidus boolean := escape_solidus;
|
||||
char_map_ascii_output boolean := ascii_output;
|
||||
|
||||
function llcheck(str in varchar2) return varchar2 as
|
||||
begin
|
||||
--dbms_output.put_line(cur_line_len || ' : ' || str);
|
||||
if (max_line_len > 0 and length(str)+cur_line_len > max_line_len) then
|
||||
cur_line_len := length(str);
|
||||
return newline_char || str;
|
||||
else
|
||||
cur_line_len := cur_line_len + length(str);
|
||||
return str;
|
||||
end if;
|
||||
end llcheck;
|
||||
|
||||
-- escapes a single character.
|
||||
function escapeChar(ch char) return varchar2 deterministic is
|
||||
result varchar2(20);
|
||||
begin
|
||||
--backspace b = U+0008
|
||||
--formfeed f = U+000C
|
||||
--newline n = U+000A
|
||||
--carret r = U+000D
|
||||
--tabulator t = U+0009
|
||||
result := ch;
|
||||
|
||||
case ch
|
||||
when chr( 8) then result := '\b';
|
||||
when chr( 9) then result := '\t';
|
||||
when chr(10) then result := '\n';
|
||||
when chr(12) then result := '\f';
|
||||
when chr(13) then result := '\r';
|
||||
when chr(34) then result := '\"';
|
||||
when chr(47) then if (escape_solidus) then result := '\/'; end if;
|
||||
when chr(92) then result := '\\';
|
||||
/* WARNING: ascii() returns PLS_INTEGER and large unicode code points can be negative */
|
||||
else if (ascii(ch) >= 0 and ascii(ch) < 32) then
|
||||
result := '\u' || replace(substr(to_char(ascii(ch), 'XXXX'), 2, 4), ' ', '0');
|
||||
elsif (ascii_output) then
|
||||
result := replace(asciistr(ch), '\', '\u');
|
||||
end if;
|
||||
end case;
|
||||
return result;
|
||||
end;
|
||||
|
||||
function escapeString(str varchar2) return varchar2 as
|
||||
sb varchar2(32767 byte) := '';
|
||||
buf varchar2(40);
|
||||
ch varchar2(1 char); /* unicode char */
|
||||
begin
|
||||
if (str is null) then return ''; end if;
|
||||
|
||||
-- clear the cache if global parameters have been changed
|
||||
if char_map_escape_solidus <> escape_solidus or
|
||||
char_map_ascii_output <> ascii_output
|
||||
then
|
||||
char_map.delete;
|
||||
char_map_escape_solidus := escape_solidus;
|
||||
char_map_ascii_output := ascii_output;
|
||||
end if;
|
||||
|
||||
for i in 1 .. length(str) loop
|
||||
ch := substr(str, i, 1 ) ;
|
||||
|
||||
begin
|
||||
-- it this char has already been processed, I have cached its escaped value
|
||||
buf:=char_map(ch);
|
||||
exception when no_Data_found then
|
||||
-- otherwise, i convert the value and add it to the cache
|
||||
buf := escapeChar(ch);
|
||||
char_map(ch) := buf;
|
||||
end;
|
||||
|
||||
sb := sb || buf;
|
||||
end loop;
|
||||
return sb;
|
||||
end escapeString;
|
||||
|
||||
function newline(spaces boolean) return varchar2 as
|
||||
begin
|
||||
cur_line_len := 0;
|
||||
if (spaces) then return newline_char; else return ''; end if;
|
||||
end;
|
||||
|
||||
/* function get_schema return varchar2 as
|
||||
begin
|
||||
return sys_context('userenv', 'current_schema');
|
||||
end;
|
||||
*/
|
||||
function tab(indent number, spaces boolean) return varchar2 as
|
||||
i varchar(200) := '';
|
||||
begin
|
||||
if (not spaces) then return ''; end if;
|
||||
for x in 1 .. indent loop i := i || indent_string; end loop;
|
||||
return i;
|
||||
end;
|
||||
|
||||
function getCommaSep(spaces boolean) return varchar2 as
|
||||
begin
|
||||
if (spaces) then return ', '; else return ','; end if;
|
||||
end;
|
||||
|
||||
function getMemName(mem pljson_element, spaces boolean) return varchar2 as
|
||||
begin
|
||||
if (spaces) then
|
||||
return llcheck('"'||escapeString(mem.mapname)||'"') || llcheck(' : ');
|
||||
else
|
||||
return llcheck('"'||escapeString(mem.mapname)||'"') || llcheck(':');
|
||||
end if;
|
||||
end;
|
||||
|
||||
/* Clob method start here */
|
||||
procedure add_to_clob(buf_lob in out nocopy clob, buf_str in out nocopy varchar2, str varchar2) as
|
||||
begin
|
||||
-- if (length(str) > 5000 - length(buf_str)) then
|
||||
if (lengthb(str) > 32767 - lengthb(buf_str)) then
|
||||
-- dbms_lob.writeappend(buf_lob, length2(buf_str), buf_str);
|
||||
dbms_lob.append(buf_lob, buf_str);
|
||||
buf_str := str;
|
||||
else
|
||||
buf_str := buf_str || str;
|
||||
end if;
|
||||
end add_to_clob;
|
||||
|
||||
procedure flush_clob(buf_lob in out nocopy clob, buf_str in out nocopy varchar2) as
|
||||
begin
|
||||
-- dbms_lob.writeappend(buf_lob, length2(buf_str), buf_str);
|
||||
dbms_lob.append(buf_lob, buf_str);
|
||||
end flush_clob;
|
||||
|
||||
procedure ppObj(obj pljson, indent number, buf in out nocopy clob, spaces boolean, buf_str in out nocopy varchar2);
|
||||
|
||||
procedure ppString(elem pljson_string, buf in out nocopy clob, buf_str in out nocopy varchar2) is
|
||||
offset number := 1;
|
||||
/* E.I.Sarmas (github.com/dsnz) 2016-01-21 limit to 5000 chars */
|
||||
v_str varchar(5000 char);
|
||||
amount number := 5000; /* chunk size for use in escapeString, less than this number may be copied */
|
||||
begin
|
||||
if empty_string_as_null and elem.extended_str is null and elem.str is null then
|
||||
add_to_clob(buf, buf_str, 'null');
|
||||
else
|
||||
add_to_clob(buf, buf_str, case when elem.num = 1 then '"' else '/**/' end);
|
||||
if (elem.extended_str is not null) then --clob implementation
|
||||
while (offset <= dbms_lob.getlength(elem.extended_str)) loop
|
||||
dbms_lob.read(elem.extended_str, amount, offset, v_str);
|
||||
if (elem.num = 1) then
|
||||
add_to_clob(buf, buf_str, escapeString(v_str));
|
||||
else
|
||||
add_to_clob(buf, buf_str, v_str);
|
||||
end if;
|
||||
offset := offset + amount;
|
||||
end loop;
|
||||
else
|
||||
if (elem.num = 1) then
|
||||
while (offset <= length(elem.str)) loop
|
||||
v_str:=substr(elem.str, offset, amount);
|
||||
add_to_clob(buf, buf_str, escapeString(v_str));
|
||||
offset := offset + amount;
|
||||
end loop;
|
||||
else
|
||||
add_to_clob(buf, buf_str, elem.str);
|
||||
end if;
|
||||
end if;
|
||||
add_to_clob(buf, buf_str, case when elem.num = 1 then '"' else '/**/' end);
|
||||
end if;
|
||||
end;
|
||||
|
||||
procedure ppEA(input pljson_list, indent number, buf in out nocopy clob, spaces boolean, buf_str in out nocopy varchar2) as
|
||||
elem pljson_element;
|
||||
arr pljson_element_array := input.list_data;
|
||||
numbuf varchar2(4000);
|
||||
begin
|
||||
for y in 1 .. arr.count loop
|
||||
elem := arr(y);
|
||||
if (elem is not null) then
|
||||
case elem.typeval
|
||||
/* number */
|
||||
when 4 then
|
||||
numbuf := treat(elem as pljson_number).number_toString();
|
||||
add_to_clob(buf, buf_str, llcheck(numbuf));
|
||||
/* string */
|
||||
when 3 then
|
||||
ppString(treat(elem as pljson_string), buf, buf_str);
|
||||
/* bool */
|
||||
when 5 then
|
||||
if (elem.get_bool()) then
|
||||
add_to_clob(buf, buf_str, llcheck('true'));
|
||||
else
|
||||
add_to_clob(buf, buf_str, llcheck('false'));
|
||||
end if;
|
||||
/* null */
|
||||
when 6 then
|
||||
add_to_clob(buf, buf_str, llcheck('null'));
|
||||
/* array */
|
||||
when 2 then
|
||||
add_to_clob(buf, buf_str, llcheck('['));
|
||||
ppEA(treat(elem as pljson_list), indent, buf, spaces, buf_str);
|
||||
add_to_clob(buf, buf_str, llcheck(']'));
|
||||
/* object */
|
||||
when 1 then
|
||||
ppObj(treat(elem as pljson), indent, buf, spaces, buf_str);
|
||||
else
|
||||
add_to_clob(buf, buf_str, llcheck(elem.get_type));
|
||||
end case;
|
||||
end if;
|
||||
if (y != arr.count) then add_to_clob(buf, buf_str, llcheck(getCommaSep(spaces))); end if;
|
||||
end loop;
|
||||
end ppEA;
|
||||
|
||||
procedure ppMem(mem pljson_element, indent number, buf in out nocopy clob, spaces boolean, buf_str in out nocopy varchar2) as
|
||||
numbuf varchar2(4000);
|
||||
begin
|
||||
add_to_clob(buf, buf_str, llcheck(tab(indent, spaces)) || llcheck(getMemName(mem, spaces)));
|
||||
case mem.typeval
|
||||
/* number */
|
||||
when 4 then
|
||||
numbuf := treat(mem as pljson_number).number_toString();
|
||||
add_to_clob(buf, buf_str, llcheck(numbuf));
|
||||
/* string */
|
||||
when 3 then
|
||||
ppString(treat(mem as pljson_string), buf, buf_str);
|
||||
/* bool */
|
||||
when 5 then
|
||||
if (mem.get_bool()) then
|
||||
add_to_clob(buf, buf_str, llcheck('true'));
|
||||
else
|
||||
add_to_clob(buf, buf_str, llcheck('false'));
|
||||
end if;
|
||||
/* null */
|
||||
when 6 then
|
||||
add_to_clob(buf, buf_str, llcheck('null'));
|
||||
/* array */
|
||||
when 2 then
|
||||
add_to_clob(buf, buf_str, llcheck('['));
|
||||
ppEA(treat(mem as pljson_list), indent, buf, spaces, buf_str);
|
||||
add_to_clob(buf, buf_str, llcheck(']'));
|
||||
/* object */
|
||||
when 1 then
|
||||
ppObj(treat(mem as pljson), indent, buf, spaces, buf_str);
|
||||
else
|
||||
add_to_clob(buf, buf_str, llcheck(mem.get_type));
|
||||
end case;
|
||||
end ppMem;
|
||||
|
||||
procedure ppObj(obj pljson, indent number, buf in out nocopy clob, spaces boolean, buf_str in out nocopy varchar2) as
|
||||
begin
|
||||
add_to_clob(buf, buf_str, llcheck('{') || newline(spaces));
|
||||
for m in 1 .. obj.json_data.count loop
|
||||
ppMem(obj.json_data(m), indent+1, buf, spaces, buf_str);
|
||||
if (m != obj.json_data.count) then
|
||||
add_to_clob(buf, buf_str, llcheck(',') || newline(spaces));
|
||||
else
|
||||
add_to_clob(buf, buf_str, newline(spaces));
|
||||
end if;
|
||||
end loop;
|
||||
add_to_clob(buf, buf_str, llcheck(tab(indent, spaces)) || llcheck('}')); -- || chr(13);
|
||||
end ppObj;
|
||||
|
||||
procedure pretty_print(obj pljson, spaces boolean default true, buf in out nocopy clob, line_length number default 0, erase_clob boolean default true) as
|
||||
buf_str varchar2(32767);
|
||||
amount number := dbms_lob.getlength(buf);
|
||||
begin
|
||||
if (erase_clob and amount > 0) then
|
||||
dbms_lob.trim(buf, 0);
|
||||
-- dbms_lob.erase(buf, amount);
|
||||
end if;
|
||||
|
||||
max_line_len := line_length;
|
||||
cur_line_len := 0;
|
||||
ppObj(obj, 0, buf, spaces, buf_str);
|
||||
flush_clob(buf, buf_str);
|
||||
end;
|
||||
|
||||
procedure pretty_print_list(obj pljson_list, spaces boolean default true, buf in out nocopy clob, line_length number default 0, erase_clob boolean default true) as
|
||||
buf_str varchar2(32767);
|
||||
amount number := dbms_lob.getlength(buf);
|
||||
begin
|
||||
if (erase_clob and amount > 0) then
|
||||
dbms_lob.trim(buf, 0);
|
||||
-- dbms_lob.erase(buf, amount);
|
||||
end if;
|
||||
|
||||
max_line_len := line_length;
|
||||
cur_line_len := 0;
|
||||
add_to_clob(buf, buf_str, llcheck('['));
|
||||
ppEA(obj, 0, buf, spaces, buf_str);
|
||||
add_to_clob(buf, buf_str, llcheck(']'));
|
||||
flush_clob(buf, buf_str);
|
||||
end;
|
||||
|
||||
procedure pretty_print_any(json_part pljson_element, spaces boolean default true, buf in out nocopy clob, line_length number default 0, erase_clob boolean default true) as
|
||||
buf_str varchar2(32767) := '';
|
||||
numbuf varchar2(4000);
|
||||
amount number := dbms_lob.getlength(buf);
|
||||
begin
|
||||
if (erase_clob and amount > 0) then
|
||||
dbms_lob.trim(buf, 0);
|
||||
-- dbms_lob.erase(buf, amount);
|
||||
end if;
|
||||
|
||||
case json_part.typeval
|
||||
/* number */
|
||||
when 4 then
|
||||
numbuf := treat(json_part as pljson_number).number_toString();
|
||||
add_to_clob(buf, buf_str, numbuf);
|
||||
/* string */
|
||||
when 3 then
|
||||
ppString(treat(json_part as pljson_string), buf, buf_str);
|
||||
/* bool */
|
||||
when 5 then
|
||||
if (json_part.get_bool()) then
|
||||
add_to_clob(buf, buf_str, 'true');
|
||||
else
|
||||
add_to_clob(buf, buf_str, 'false');
|
||||
end if;
|
||||
/* null */
|
||||
when 6 then
|
||||
add_to_clob(buf, buf_str, 'null');
|
||||
/* array */
|
||||
when 2 then
|
||||
pretty_print_list(pljson_list(json_part), spaces, buf, line_length);
|
||||
return;
|
||||
/* object */
|
||||
when 1 then
|
||||
pretty_print(pljson(json_part), spaces, buf, line_length);
|
||||
return;
|
||||
else
|
||||
add_to_clob(buf, buf_str, 'unknown type:' || json_part.get_type);
|
||||
end case;
|
||||
flush_clob(buf, buf_str);
|
||||
end;
|
||||
|
||||
/* Clob method end here */
|
||||
|
||||
/* Varchar2 method start here */
|
||||
procedure add_buf (buf in out nocopy varchar2, str in varchar2) as
|
||||
begin
|
||||
if (lengthb(str)>32767-lengthb(buf)) then
|
||||
raise_application_error(-20001,'Length of result JSON more than 32767 bytes. Use to_clob() procedures');
|
||||
end if;
|
||||
buf := buf || str;
|
||||
end;
|
||||
|
||||
procedure ppString(elem pljson_string, buf in out nocopy varchar2) is
|
||||
offset number := 1;
|
||||
/* E.I.Sarmas (github.com/dsnz) 2016-01-21 limit to 5000 chars */
|
||||
v_str varchar(5000 char);
|
||||
amount number := 5000; /* chunk size for use in escapeString, less than this number may be copied */
|
||||
begin
|
||||
if empty_string_as_null and elem.extended_str is null and elem.str is null then
|
||||
add_buf(buf, 'null');
|
||||
else
|
||||
add_buf(buf, case when elem.num = 1 then '"' else '/**/' end);
|
||||
if (elem.extended_str is not null) then --clob implementation
|
||||
while (offset <= dbms_lob.getlength(elem.extended_str)) loop
|
||||
dbms_lob.read(elem.extended_str, amount, offset, v_str);
|
||||
if (elem.num = 1) then
|
||||
add_buf(buf, escapeString(v_str));
|
||||
else
|
||||
add_buf(buf, v_str);
|
||||
end if;
|
||||
offset := offset + amount;
|
||||
end loop;
|
||||
else
|
||||
if (elem.num = 1) then
|
||||
while (offset <= length(elem.str)) loop
|
||||
v_str:=substr(elem.str, offset, amount);
|
||||
add_buf(buf, escapeString(v_str));
|
||||
offset := offset + amount;
|
||||
end loop;
|
||||
else
|
||||
add_buf(buf, elem.str);
|
||||
end if;
|
||||
end if;
|
||||
add_buf(buf, case when elem.num = 1 then '"' else '/**/' end);
|
||||
end if;
|
||||
end;
|
||||
|
||||
procedure ppObj(obj pljson, indent number, buf in out nocopy varchar2, spaces boolean);
|
||||
|
||||
procedure ppEA(input pljson_list, indent number, buf in out varchar2, spaces boolean) as
|
||||
elem pljson_element;
|
||||
arr pljson_element_array := input.list_data;
|
||||
str varchar2(400);
|
||||
begin
|
||||
for y in 1 .. arr.count loop
|
||||
elem := arr(y);
|
||||
if (elem is not null) then
|
||||
case elem.typeval
|
||||
/* number */
|
||||
when 4 then
|
||||
str := treat(elem as pljson_number).number_toString();
|
||||
add_buf(buf, llcheck(str));
|
||||
/* string */
|
||||
when 3 then
|
||||
ppString(treat(elem as pljson_string), buf);
|
||||
/* bool */
|
||||
when 5 then
|
||||
if (elem.get_bool()) then
|
||||
add_buf (buf, llcheck('true'));
|
||||
else
|
||||
add_buf (buf, llcheck('false'));
|
||||
end if;
|
||||
/* null */
|
||||
when 6 then
|
||||
add_buf (buf, llcheck('null'));
|
||||
/* array */
|
||||
when 2 then
|
||||
add_buf( buf, llcheck('['));
|
||||
ppEA(treat(elem as pljson_list), indent, buf, spaces);
|
||||
add_buf( buf, llcheck(']'));
|
||||
/* object */
|
||||
when 1 then
|
||||
ppObj(treat(elem as pljson), indent, buf, spaces);
|
||||
else
|
||||
add_buf (buf, llcheck(elem.get_type)); /* should never happen */
|
||||
end case;
|
||||
end if;
|
||||
if (y != arr.count) then add_buf(buf, llcheck(getCommaSep(spaces))); end if;
|
||||
end loop;
|
||||
end ppEA;
|
||||
|
||||
procedure ppMem(mem pljson_element, indent number, buf in out nocopy varchar2, spaces boolean) as
|
||||
str varchar2(400) := '';
|
||||
begin
|
||||
add_buf(buf, llcheck(tab(indent, spaces)) || getMemName(mem, spaces));
|
||||
case mem.typeval
|
||||
/* number */
|
||||
when 4 then
|
||||
str := treat(mem as pljson_number).number_toString();
|
||||
add_buf(buf, llcheck(str));
|
||||
/* string */
|
||||
when 3 then
|
||||
ppString(treat(mem as pljson_string), buf);
|
||||
/* bool */
|
||||
when 5 then
|
||||
if (mem.get_bool()) then
|
||||
add_buf(buf, llcheck('true'));
|
||||
else
|
||||
add_buf(buf, llcheck('false'));
|
||||
end if;
|
||||
/* null */
|
||||
when 6 then
|
||||
add_buf(buf, llcheck('null'));
|
||||
/* array */
|
||||
when 2 then
|
||||
add_buf(buf, llcheck('['));
|
||||
ppEA(treat(mem as pljson_list), indent, buf, spaces);
|
||||
add_buf(buf, llcheck(']'));
|
||||
/* object */
|
||||
when 1 then
|
||||
ppObj(treat(mem as pljson), indent, buf, spaces);
|
||||
else
|
||||
add_buf(buf, llcheck(mem.get_type)); /* should never happen */
|
||||
end case;
|
||||
end ppMem;
|
||||
|
||||
procedure ppObj(obj pljson, indent number, buf in out nocopy varchar2, spaces boolean) as
|
||||
begin
|
||||
add_buf (buf, llcheck('{') || newline(spaces));
|
||||
for m in 1 .. obj.json_data.count loop
|
||||
ppMem(obj.json_data(m), indent+1, buf, spaces);
|
||||
if (m != obj.json_data.count) then
|
||||
add_buf(buf, llcheck(',') || newline(spaces));
|
||||
else
|
||||
add_buf(buf, newline(spaces));
|
||||
end if;
|
||||
end loop;
|
||||
add_buf(buf, llcheck(tab(indent, spaces)) || llcheck('}')); -- || chr(13);
|
||||
end ppObj;
|
||||
|
||||
function pretty_print(obj pljson, spaces boolean default true, line_length number default 0) return varchar2 as
|
||||
buf varchar2(32767 byte) := '';
|
||||
begin
|
||||
max_line_len := line_length;
|
||||
cur_line_len := 0;
|
||||
ppObj(obj, 0, buf, spaces);
|
||||
return buf;
|
||||
end pretty_print;
|
||||
|
||||
function pretty_print_list(obj pljson_list, spaces boolean default true, line_length number default 0) return varchar2 as
|
||||
buf varchar2(32767 byte) :='';
|
||||
begin
|
||||
max_line_len := line_length;
|
||||
cur_line_len := 0;
|
||||
add_buf(buf, llcheck('['));
|
||||
ppEA(obj, 0, buf, spaces);
|
||||
add_buf(buf, llcheck(']'));
|
||||
return buf;
|
||||
end;
|
||||
|
||||
function pretty_print_any(json_part pljson_element, spaces boolean default true, line_length number default 0) return varchar2 as
|
||||
buf varchar2(32767) := '';
|
||||
begin
|
||||
case json_part.typeval
|
||||
/* number */
|
||||
when 4 then
|
||||
buf := treat(json_part as pljson_number).number_toString();
|
||||
/* string */
|
||||
when 3 then
|
||||
ppString(treat(json_part as pljson_string), buf);
|
||||
/* bool */
|
||||
when 5 then
|
||||
if (json_part.get_bool()) then buf := 'true'; else buf := 'false'; end if;
|
||||
/* null */
|
||||
when 6 then
|
||||
buf := 'null';
|
||||
/* array */
|
||||
when 2 then
|
||||
buf := pretty_print_list(pljson_list(json_part), spaces, line_length);
|
||||
/* object */
|
||||
when 1 then
|
||||
buf := pretty_print(pljson(json_part), spaces, line_length);
|
||||
else
|
||||
buf := 'weird error: ' || json_part.get_type;
|
||||
end case;
|
||||
return buf;
|
||||
end;
|
||||
|
||||
procedure dbms_output_clob(my_clob clob, delim varchar2, jsonp varchar2 default null) as
|
||||
prev number := 1;
|
||||
indx number := 1;
|
||||
size_of_nl number := length2(delim);
|
||||
v_str varchar2(32767);
|
||||
amount number;
|
||||
max_string_chars number := 5000; /* chunk size, less than this number may be copied */
|
||||
begin
|
||||
if (jsonp is not null) then dbms_output.put_line(jsonp||'('); end if;
|
||||
while (indx != 0) loop
|
||||
--read every line
|
||||
indx := dbms_lob.instr(my_clob, delim, prev+1);
|
||||
--dbms_output.put_line(prev || ' to ' || indx);
|
||||
|
||||
if (indx = 0) then
|
||||
--emit from prev to end;
|
||||
amount := max_string_chars;
|
||||
--dbms_output.put_line(' mycloblen ' || dbms_lob.getlength(my_clob));
|
||||
loop
|
||||
dbms_lob.read(my_clob, amount, prev, v_str);
|
||||
dbms_output.put_line(v_str);
|
||||
prev := prev+amount;
|
||||
exit when prev >= dbms_lob.getlength(my_clob);
|
||||
end loop;
|
||||
else
|
||||
amount := indx - prev;
|
||||
if (amount > max_string_chars) then
|
||||
amount := max_string_chars;
|
||||
--dbms_output.put_line(' mycloblen ' || dbms_lob.getlength(my_clob));
|
||||
loop
|
||||
dbms_lob.read(my_clob, amount, prev, v_str);
|
||||
dbms_output.put_line(v_str);
|
||||
prev := prev+amount;
|
||||
amount := indx - prev;
|
||||
exit when prev >= indx - 1;
|
||||
if (amount > max_string_chars) then
|
||||
amount := max_string_chars;
|
||||
end if;
|
||||
end loop;
|
||||
prev := indx + size_of_nl;
|
||||
else
|
||||
dbms_lob.read(my_clob, amount, prev, v_str);
|
||||
dbms_output.put_line(v_str);
|
||||
prev := indx + size_of_nl;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end loop;
|
||||
if (jsonp is not null) then dbms_output.put_line(')'); end if;
|
||||
|
||||
/* while (amount != 0) loop
|
||||
indx := dbms_lob.instr(my_clob, delim, prev+1);
|
||||
|
||||
-- dbms_output.put_line(prev || ' to ' || indx);
|
||||
if (indx = 0) then
|
||||
indx := dbms_lob.getlength(my_clob)+1;
|
||||
end if;
|
||||
if (indx-prev > 32767) then
|
||||
indx := prev+32767;
|
||||
end if;
|
||||
-- dbms_output.put_line(prev || ' to ' || indx);
|
||||
--substr doesnt work properly on all platforms! (come on oracle - error on Oracle VM for virtualbox)
|
||||
-- dbms_output.put_line(dbms_lob.substr(my_clob, indx-prev, prev));
|
||||
amount := indx-prev;
|
||||
-- dbms_output.put_line('amount'||amount);
|
||||
dbms_lob.read(my_clob, amount, prev, v_str);
|
||||
dbms_output.put_line(v_str);
|
||||
prev := indx+size_of_nl;
|
||||
if (amount = 32767) then prev := prev-size_of_nl-1; end if;
|
||||
end loop;
|
||||
if (jsonp is not null) then dbms_output.put_line(')'); end if;*/
|
||||
end;
|
||||
|
||||
/* procedure dbms_output_clob(my_clob clob, delim varchar2, jsonp varchar2 default null) as
|
||||
prev number := 1;
|
||||
indx number := 1;
|
||||
size_of_nl number := length2(delim);
|
||||
v_str varchar2(32767);
|
||||
amount number;
|
||||
begin
|
||||
if (jsonp is not null) then dbms_output.put_line(jsonp||'('); end if;
|
||||
while (indx != 0) loop
|
||||
indx := dbms_lob.instr(my_clob, delim, prev+1);
|
||||
|
||||
--dbms_output.put_line(prev || ' to ' || indx);
|
||||
if (indx-prev > 32767) then
|
||||
indx := prev+32767;
|
||||
end if;
|
||||
--dbms_output.put_line(prev || ' to ' || indx);
|
||||
--substr doesnt work properly on all platforms! (come on oracle - error on Oracle VM for virtualbox)
|
||||
if (indx = 0) then
|
||||
--dbms_output.put_line(dbms_lob.substr(my_clob, dbms_lob.getlength(my_clob)-prev+size_of_nl, prev));
|
||||
amount := dbms_lob.getlength(my_clob)-prev+size_of_nl;
|
||||
dbms_lob.read(my_clob, amount, prev, v_str);
|
||||
else
|
||||
--dbms_output.put_line(dbms_lob.substr(my_clob, indx-prev, prev));
|
||||
amount := indx-prev;
|
||||
--dbms_output.put_line('amount'||amount);
|
||||
dbms_lob.read(my_clob, amount, prev, v_str);
|
||||
end if;
|
||||
dbms_output.put_line(v_str);
|
||||
prev := indx+size_of_nl;
|
||||
if (amount = 32767) then prev := prev-size_of_nl-1; end if;
|
||||
end loop;
|
||||
if (jsonp is not null) then dbms_output.put_line(')'); end if;
|
||||
end;
|
||||
*/
|
||||
|
||||
procedure htp_output_clob(my_clob clob, jsonp varchar2 default null) as
|
||||
/*amount number := 4096;
|
||||
pos number := 1;
|
||||
len number;
|
||||
*/
|
||||
l_amt number default 4096;
|
||||
l_off number default 1;
|
||||
l_str varchar2(32000);
|
||||
begin
|
||||
if (jsonp is not null) then htp.prn(jsonp||'('); end if;
|
||||
|
||||
begin
|
||||
loop
|
||||
dbms_lob.read( my_clob, l_amt, l_off, l_str );
|
||||
|
||||
-- it is vital to use htp.PRN to avoid
|
||||
-- spurious line feeds getting added to your
|
||||
-- document
|
||||
htp.prn( l_str );
|
||||
l_off := l_off+l_amt;
|
||||
end loop;
|
||||
exception
|
||||
when no_data_found then NULL;
|
||||
end;
|
||||
|
||||
/*
|
||||
len := dbms_lob.getlength(my_clob);
|
||||
|
||||
while (pos < len) loop
|
||||
htp.prn(dbms_lob.substr(my_clob, amount, pos)); -- should I replace substr with dbms_lob.read?
|
||||
--dbms_output.put_line(dbms_lob.substr(my_clob, amount, pos));
|
||||
pos := pos + amount;
|
||||
end loop;
|
||||
*/
|
||||
if (jsonp is not null) then htp.prn(')'); end if;
|
||||
end;
|
||||
|
||||
end pljson_printer;```
|
||||
Reference in New Issue
Block a user