Skip to content

Commit 9992bcf

Browse files
author
Sergejs Vinniks
committed
Implemented the COMPARE_TO method
1 parent 4272b64 commit 9992bcf

16 files changed

+1492
-42
lines changed

src/packages/json_core.pkb

+1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ CREATE OR REPLACE PACKAGE BODY json_core IS
8787
default_message_resolver.register_message('JDC-00048', 'Builder not specified!');
8888
default_message_resolver.register_message('JDC-00049', 'Property value not specified!');
8989
default_message_resolver.register_message('JDC-00050', 'Unimplemented feature!');
90+
default_message_resolver.register_message('JDC-00051', 'Right value not specified!');
9091
END;
9192

9293
-- Do-nothing procedure to initialize error messages from another packages

src/packages/json_parser.pkb

-2
Original file line numberDiff line numberDiff line change
@@ -715,8 +715,6 @@ CREATE OR REPLACE PACKAGE BODY json_parser IS
715715
add_event('N', v_value);
716716
WHEN 'lfEnd' THEN
717717
NULL;
718-
WHEN 'lfContent' THEN
719-
NULL;
720718
ELSE
721719
-- Unexpected end of the input!
722720
error$.raise('JSN-00002');

src/packages/persistent_json_store.pkb

+23-7
Original file line numberDiff line numberDiff line change
@@ -1119,16 +1119,28 @@ CREATE OR REPLACE PACKAGE BODY persistent_json_store IS
11191119

11201120
v_value := get_value(p_object_id);
11211121

1122-
IF v_value.type NOT IN ('O', 'R') THEN
1122+
IF v_value.type NOT IN ('O', 'R', 'A') THEN
11231123
-- Value is not an object!
11241124
error$.raise('JDC-00021');
11251125
END IF;
11261126

1127-
SELECT name
1128-
BULK COLLECT INTO v_keys
1129-
FROM json_values
1130-
WHERE parent_id = p_object_id
1131-
ORDER BY name;
1127+
IF v_value.type = 'A' THEN
1128+
1129+
SELECT name
1130+
BULK COLLECT INTO v_keys
1131+
FROM json_values
1132+
WHERE parent_id = p_object_id
1133+
ORDER BY TO_INDEX(name);
1134+
1135+
ELSE
1136+
1137+
SELECT name
1138+
BULK COLLECT INTO v_keys
1139+
FROM json_values
1140+
WHERE parent_id = p_object_id
1141+
ORDER BY name;
1142+
1143+
END IF;
11321144

11331145
RETURN v_keys;
11341146

@@ -1383,14 +1395,18 @@ CREATE OR REPLACE PACKAGE BODY persistent_json_store IS
13831395
error$.raise('JDC-00034');
13841396
END IF;
13851397

1398+
IF v_value.locked IS NULL THEN
1399+
RETURN;
1400+
END IF;
1401+
13861402
IF p_unpin_tree THEN
13871403

13881404
SELECT id
13891405
BULK COLLECT INTO v_ids_to_unpin
13901406
FROM json_values
1391-
WHERE locked = 'T'
13921407
START WITH id = p_id
13931408
CONNECT BY PRIOR id = parent_id
1409+
AND locked = 'T'
13941410
FOR UPDATE;
13951411

13961412
ELSE

src/packages/transient_json_store.pkb

+11-4
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ CREATE OR REPLACE PACKAGE BODY transient_json_store IS
482482

483483
v_value := get_value(p_object_id);
484484

485-
IF v_value.type NOT IN ('O', 'R') THEN
485+
IF v_value.type NOT IN ('O', 'R', 'A') THEN
486486
-- Value is not an object!
487487
error$.raise('JDC-00021');
488488
END IF;
@@ -495,7 +495,12 @@ CREATE OR REPLACE PACKAGE BODY transient_json_store IS
495495
WHILE v_name LIKE v_pattern LOOP
496496

497497
v_keys.EXTEND(1);
498-
v_keys(v_keys.COUNT) := v_values(v_value_child_ids(v_name)).name;
498+
499+
IF v_value.type = 'A' THEN
500+
v_keys(v_keys.COUNT) := v_values(v_value_child_ids(v_name)).name;
501+
ELSE
502+
v_keys(v_keys.COUNT) := NVL(LTRIM(v_values(v_value_child_ids(v_name)).name, '0'), '0');
503+
END IF;
499504

500505
v_name := v_value_child_ids.NEXT(v_name);
501506

@@ -1052,8 +1057,6 @@ CREATE OR REPLACE PACKAGE BODY transient_json_store IS
10521057

10531058
PROCEDURE visit_next IS
10541059

1055-
v_parent_value_id NUMBER;
1056-
10571060
v_next_sibling_element_i PLS_INTEGER;
10581061
v_next_sibling_element json_core.t_query_element;
10591062

@@ -1196,6 +1199,10 @@ CREATE OR REPLACE PACKAGE BODY transient_json_store IS
11961199
v_name := get_bind_value(v_element.bind_number);
11971200
END IF;
11981201

1202+
IF v_parent_value_id > 0 AND v_values(v_parent_value_id).type = 'A' THEN
1203+
v_name := LPAD(v_name, 12, '0');
1204+
END IF;
1205+
11991206
v_name := v_parent_value_id || '-' || v_name;
12001207

12011208
IF v_value_child_ids.EXISTS(v_name) THEN

src/types/t_json.tpb

+189
Original file line numberDiff line numberDiff line change
@@ -1670,4 +1670,193 @@ CREATE OR REPLACE TYPE BODY t_json IS
16701670
unpin(':i', p_unpin_tree, bind(p_index));
16711671
END;
16721672

1673+
-- Value comparison
1674+
1675+
MEMBER FUNCTION compare_to (
1676+
p_value IN t_json
1677+
)
1678+
RETURN t_json_mismatches IS
1679+
1680+
v_path t_varchars;
1681+
v_mismatches t_json_mismatches;
1682+
1683+
PROCEDURE add_mismatch (
1684+
p_code IN VARCHAR2
1685+
) IS
1686+
BEGIN
1687+
v_mismatches.EXTEND(1);
1688+
v_mismatches(v_mismatches.COUNT) := t_json_mismatch(v_path, p_code);
1689+
END;
1690+
1691+
PROCEDURE push_name (
1692+
p_name IN VARCHAR2
1693+
) IS
1694+
BEGIN
1695+
v_path.EXTEND(1);
1696+
v_path(v_path.COUNT) := p_name;
1697+
END;
1698+
1699+
PROCEDURE pop_name IS
1700+
BEGIN
1701+
v_path.TRIM(1);
1702+
END;
1703+
1704+
PROCEDURE visit_value (
1705+
p_left IN t_json,
1706+
p_right IN t_json
1707+
) IS
1708+
1709+
v_left_type CHAR;
1710+
v_left_value VARCHAR2(4000);
1711+
1712+
v_right_type CHAR;
1713+
v_right_value VARCHAR2(4000);
1714+
1715+
v_parent_id NUMBER;
1716+
1717+
v_left_keys t_varchars;
1718+
v_right_keys t_varchars;
1719+
1720+
v_left_i PLS_INTEGER;
1721+
v_right_i PLS_INTEGER;
1722+
1723+
v_left_key VARCHAR2(4000);
1724+
v_right_key VARCHAR2(4000);
1725+
1726+
v_compare PLS_INTEGER;
1727+
1728+
PROCEDURE missing_left IS
1729+
BEGIN
1730+
1731+
push_name(v_right_key);
1732+
add_mismatch('ML');
1733+
pop_name;
1734+
1735+
v_right_i := v_right_i + 1;
1736+
1737+
END;
1738+
1739+
PROCEDURE missing_right IS
1740+
BEGIN
1741+
1742+
push_name(v_left_key);
1743+
add_mismatch('MR');
1744+
pop_name;
1745+
1746+
v_left_i := v_left_i + 1;
1747+
1748+
END;
1749+
1750+
PROCEDURE compare_keys IS
1751+
BEGIN
1752+
1753+
IF v_left_key = v_right_key THEN
1754+
v_compare := 0;
1755+
ELSIF v_left_type = 'A' THEN
1756+
IF LPAD(v_left_key, 12, '0') > LPAD(v_right_key, 12, '0') THEN
1757+
v_compare := 1;
1758+
ELSE
1759+
v_compare := -1;
1760+
END IF;
1761+
ELSE
1762+
IF v_left_key > v_right_key THEN
1763+
v_compare := 1;
1764+
ELSE
1765+
v_compare := -1;
1766+
END IF;
1767+
END IF;
1768+
1769+
END;
1770+
1771+
BEGIN
1772+
1773+
p_left.dump(v_parent_id, v_left_type, v_left_value);
1774+
p_right.dump(v_parent_id, v_right_type, v_right_value);
1775+
1776+
IF v_left_type != v_right_type THEN
1777+
1778+
add_mismatch('TM');
1779+
1780+
ELSIF v_left_type IN ('S', 'N', 'B') THEN
1781+
1782+
IF v_left_value != v_right_value THEN
1783+
add_mismatch('VM');
1784+
END IF;
1785+
1786+
ELSIF v_left_type != 'E' THEN
1787+
1788+
v_left_keys := p_left.get_keys;
1789+
v_right_keys := p_right.get_keys;
1790+
1791+
v_left_i := 1;
1792+
v_right_i := 1;
1793+
1794+
WHILE v_left_i <= v_left_keys.COUNT
1795+
OR v_right_i <= v_right_keys.COUNT
1796+
LOOP
1797+
1798+
IF v_left_i > v_left_keys.COUNT THEN
1799+
1800+
v_right_key := v_right_keys(v_right_i);
1801+
missing_left;
1802+
1803+
ELSIF v_right_i > v_right_keys.COUNT THEN
1804+
1805+
v_left_key := v_left_keys(v_left_i);
1806+
missing_right;
1807+
1808+
ELSE
1809+
1810+
v_left_key := v_left_keys(v_left_i);
1811+
v_right_key := v_right_keys(v_right_i);
1812+
compare_keys;
1813+
1814+
IF v_compare = -1 THEN
1815+
1816+
missing_right;
1817+
1818+
ELSIF v_compare = 1 THEN
1819+
1820+
missing_left;
1821+
1822+
ELSE
1823+
1824+
push_name(v_left_key);
1825+
1826+
visit_value(
1827+
p_left.get(':name', bind(v_left_key)),
1828+
p_right.get(':name', bind(v_right_key))
1829+
);
1830+
1831+
pop_name;
1832+
1833+
v_left_i := v_left_i + 1;
1834+
v_right_i := v_right_i + 1;
1835+
1836+
END IF;
1837+
1838+
END IF;
1839+
1840+
END LOOP;
1841+
1842+
END IF;
1843+
1844+
END;
1845+
1846+
BEGIN
1847+
1848+
IF p_value IS NULL THEN
1849+
-- Right value not specified!
1850+
error$.raise('JDC-00051');
1851+
END IF;
1852+
1853+
v_path := t_varchars();
1854+
v_mismatches := t_json_mismatches();
1855+
1856+
visit_value(self, p_value);
1857+
1858+
RETURN v_mismatches;
1859+
1860+
END;
1861+
16731862
END;

src/types/t_json.tps

+7
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,14 @@ CREATE OR REPLACE TYPE t_json IS OBJECT (
709709
self IN t_json,
710710
p_index IN NUMBER,
711711
p_unpin_tree IN BOOLEAN := FALSE
712+
),
713+
714+
-- Value comparison
715+
716+
MEMBER FUNCTION compare_to (
717+
p_value IN t_json
712718
)
719+
RETURN t_json_mismatches
713720

714721
)
715722
NOT FINAL

src/types/t_json_mismatch.tps

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
CREATE OR REPLACE TYPE t_json_mismatch IS OBJECT (
2+
path t_varchars,
3+
mismatch VARCHAR2(2)
4+
)

src/types/t_json_mismatches.tps

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CREATE OR REPLACE TYPE t_json_mismatches IS TABLE OF t_json_mismatch

test/json_parser.js

+12-10
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@
1616

1717
suite("Invalid JSON handling", function() {
1818

19+
test("Empty JSON", function() {
20+
21+
expect(function() {
22+
23+
database.call("json_parser.parse", {
24+
p_content: null
25+
});
26+
27+
}).to.throw(/JSN-00002/);
28+
29+
});
30+
1931
test("Invalid start of JSON", function() {
2032

2133
expect(function() {
@@ -321,16 +333,6 @@ suite("Invalid JSON handling", function() {
321333

322334
suite("Scalar value tests", function() {
323335

324-
test("Empty document", function() {
325-
326-
var events = database.call("json_parser.parse", {
327-
p_content: null
328-
});
329-
330-
expect(events).to.eql([]);
331-
332-
});
333-
334336
test("String value", function() {
335337

336338
var events = database.call("json_parser.parse", {

test/t_persistent_json/compare_to.js

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
let implementationPackage = "persistent_json_store";
2+
let implementationType = "t_persistent_json";
3+
4+
load("test/templates/implementation_type/compare_to.js.tpl");

test/t_persistent_json/get_table.js

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
let implementationPackage = "persistent_json_store";
2+
let implementationType = "t_persistent_json";
3+
4+
load("test/templates/implementation_type/get_table.js.tpl");

test/t_transient_json/compare_to.js

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
let implementationPackage = "transient_json_store";
2+
let implementationType = "t_transient_json";
3+
4+
load("test/templates/implementation_type/compare_to.js.tpl");

test/t_transient_json/get_table.js

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
let implementationPackage = "transient_json_store";
2+
let implementationType = "t_transient_json";
3+
4+
load("test/templates/implementation_type/get_table.js.tpl");

0 commit comments

Comments
 (0)