Skip to content

Commit 335a7fa

Browse files
authored
perf: used hash object confirm if there was a duplicated value in array. (#21)
1 parent 2992f43 commit 335a7fa

File tree

2 files changed

+50
-9
lines changed

2 files changed

+50
-9
lines changed

lib/jsonschema.lua

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ function codectx_mt:_get_loader()
182182
end
183183

184184
function codectx_mt:as_string()
185+
self:_get_loader()
185186
return tab_concat(self._code_table)
186187
end
187188

@@ -329,6 +330,21 @@ end
329330
validatorlib.deepeq = deepeq
330331

331332

333+
local function unique_item_in_array(arr)
334+
local existed_items = {}
335+
for i, val in ipairs(arr) do
336+
if existed_items[val] then
337+
return false, existed_items[val], i
338+
end
339+
340+
existed_items[val] = i
341+
end
342+
343+
return true
344+
end
345+
validatorlib.unique_item_in_array = unique_item_in_array
346+
347+
332348
--
333349
-- Validation generator
334350
--
@@ -746,15 +762,10 @@ generate_validator = function(ctx, schema)
746762
ctx:stmt( ' end')
747763
end
748764

749-
-- TODO: this is slow as hell, could be optimized by storing value items
750-
-- in a spearate set, and calling deepeq only for references.
751765
if schema.uniqueItems then
752-
ctx:stmt(sformat(' for i=2, #%s do', ctx:param(1)))
753-
ctx:stmt( ' for j=1, i-1 do')
754-
ctx:stmt(sformat(' if %s(%s[i], %s[j]) then', ctx:libfunc('lib.deepeq'), ctx:param(1), ctx:param(1)))
755-
ctx:stmt(sformat(' return false, %s("expected unique items but items %%d and %%d are equal", i, j)', ctx:libfunc('string.format')))
756-
ctx:stmt( ' end')
757-
ctx:stmt( ' end')
766+
ctx:stmt(sformat(' local ok, item1, item2 = %s(%s)', ctx:libfunc('lib.unique_item_in_array'), ctx:param(1)))
767+
ctx:stmt(sformat(' if not ok then', ctx:libfunc('lib.unique_item_in_array'), ctx:param(1)))
768+
ctx:stmt(sformat(' return false, %s("expected unique items but items %%d and %%d are equal", item1, item2)', ctx:libfunc('string.format')))
758769
ctx:stmt( ' end')
759770
end
760771
ctx:stmt('end') -- if array

t/default.lua

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
local jsonschema = require 'jsonschema'
2-
2+
----------------------------------------------------- test case 1
33
local rule = {
44
type = "object",
55
properties = {
@@ -29,6 +29,7 @@ if not conf.rule then
2929
return
3030
end
3131

32+
----------------------------------------------------- test case 2
3233
rule = {
3334
type = "object",
3435
properties = {
@@ -59,3 +60,32 @@ if ok then
5960
end
6061

6162
ngx.say("passed: table value as default value")
63+
64+
----------------------------------------------------- test case 3
65+
local rule = {
66+
type = "array",
67+
uniqueItems = true
68+
}
69+
70+
validator = jsonschema.generate_validator(rule)
71+
72+
local data = {}
73+
for i = 1, 1000 * 500 do
74+
data[i] = i
75+
end
76+
77+
ngx.update_time()
78+
local start_time = ngx.now()
79+
80+
local ok, err = validator(data)
81+
if not ok then
82+
ngx.say("fail: check uniqueItems array: ", err)
83+
end
84+
85+
ngx.update_time()
86+
if ngx.now() - start_time > 0.1 then
87+
ngx.say("fail: check uniqueItems array take more than 0.1s")
88+
ngx.exit(-1)
89+
end
90+
91+
ngx.say("passed: check uniqueItems array")

0 commit comments

Comments
 (0)