Skip to content

Commit 05adc40

Browse files
committed
feat(schema) allow partial update of record fields
1 parent 7864171 commit 05adc40

File tree

2 files changed

+47
-3
lines changed

2 files changed

+47
-3
lines changed

kong/db/schema/init.lua

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,24 @@ Schema.entity_checkers = {
468468
}
469469

470470

471+
local function memoize(fn)
472+
local cache = setmetatable({}, { __mode = "k" })
473+
return function(k)
474+
if cache[k] then
475+
return cache[k]
476+
end
477+
local v = fn(k)
478+
cache[k] = v
479+
return v
480+
end
481+
end
482+
483+
484+
local get_field_schema = memoize(function(field)
485+
return Schema.new(field)
486+
end)
487+
488+
471489
-- Forward declaration
472490
local validate_fields
473491

@@ -568,7 +586,7 @@ function Schema:validate_field(field, value)
568586
return nil, validation_errors.SCHEMA_MISSING_ATTRIBUTE:format("fields")
569587
end
570588

571-
local field_schema = Schema.new(field)
589+
local field_schema = get_field_schema(field)
572590
-- TODO return nested table or string?
573591
local copy = field_schema:process_auto_fields(value, "insert")
574592
local ok, err = field_schema:validate(copy)
@@ -686,7 +704,7 @@ end
686704
-- @param entity The entity object where key `k` is missing.
687705
local function handle_missing_field(k, field, entity)
688706
if field.default ~= nil then
689-
entity[k] = field.default
707+
entity[k] = tablex.deepcopy(field.default)
690708
return
691709
end
692710

@@ -1028,7 +1046,9 @@ end
10281046

10291047
--- Given a table, update its fields whose schema
10301048
-- definition declares them as `auto = true`,
1031-
-- based on its CRUD operation context.
1049+
-- based on its CRUD operation context, and set
1050+
-- defaults for missing values when the CRUD context
1051+
-- is "insert".
10321052
-- This function encapsulates various "smart behaviors"
10331053
-- for value creation and update.
10341054
-- @param input The table containing data to be processed.
@@ -1064,6 +1084,11 @@ function Schema:process_auto_fields(input, context)
10641084
output[key] = make_array(field_value)
10651085
elseif field_type == "set" then
10661086
output[key] = make_set(field_value)
1087+
elseif field_type == "record" then
1088+
if field_value ~= null then
1089+
local field_schema = get_field_schema(field)
1090+
output[key] = field_schema:process_auto_fields(field_value, context)
1091+
end
10671092
end
10681093

10691094
elseif context ~= "update" then

spec/01-unit/000-new-dao/01-schema/01-schema_spec.lua

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1525,6 +1525,24 @@ describe("schema", function()
15251525
{ f = { type = "number" }, },
15261526
},
15271527
default = { f = 123 } }, },
1528+
{ nested_record = {
1529+
type = "record",
1530+
default = {
1531+
r = {
1532+
a = "nr",
1533+
b = 123,
1534+
}
1535+
},
1536+
fields = {
1537+
{ r = {
1538+
type = "record",
1539+
fields = {
1540+
{ a = { type = "string" } },
1541+
{ b = { type = "number" } }
1542+
}
1543+
} }
1544+
}
1545+
} }
15281546
}
15291547
})
15301548
check_all_types_covered(Test.fields)
@@ -1537,6 +1555,7 @@ describe("schema", function()
15371555
assert.same("foo", data.f)
15381556
assert.same({ foo = 1, bar = 2 }, data.g)
15391557
assert.same({ f = 123 }, data.h)
1558+
assert.same({ r = { a = "nr", b = 123, }}, data.nested_record)
15401559
end)
15411560

15421561
it("honors 'false' as a default", function()

0 commit comments

Comments
 (0)