Skip to content

Commit

Permalink
feat(db) add support for read transformations (#5100)
Browse files Browse the repository at this point in the history
  • Loading branch information
bungle authored and dndx committed Nov 1, 2019
1 parent cba6282 commit 0b33972
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 21 deletions.
14 changes: 10 additions & 4 deletions kong/db/dao/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ local function check_insert(self, entity, options)
return nil, tostring(err_t), err_t
end

entity_to_insert, err = self.schema:transform(entity_to_insert, entity)
entity_to_insert, err = self.schema:transform(entity_to_insert, entity, "insert")
if not entity_to_insert then
err_t = self.errors:transformation_error(err)
return nil, tostring(err_t), err_t
Expand Down Expand Up @@ -331,7 +331,7 @@ local function check_update(self, key, entity, options, name)
return nil, nil, tostring(err_t), err_t
end

entity_to_update, err = self.schema:transform(entity_to_update, entity)
entity_to_update, err = self.schema:transform(entity_to_update, entity, "update")
if not entity_to_update then
err_t = self.errors:transformation_error(err)
return nil, nil, tostring(err_t), err_t
Expand Down Expand Up @@ -379,7 +379,7 @@ local function check_upsert(self, entity, options, name, value)
entity_to_upsert[name] = nil
end

entity_to_upsert, err = self.schema:transform(entity_to_upsert, entity)
entity_to_upsert, err = self.schema:transform(entity_to_upsert, entity, "upsert")
if not entity_to_upsert then
err_t = self.errors:transformation_error(err)
return nil, tostring(err_t), err_t
Expand Down Expand Up @@ -1080,7 +1080,13 @@ function DAO:row_to_entity(row, options)
return nil, tostring(err_t), err_t
end

return entity
local transformed_entity, err = self.schema:transform(entity, row, "select")
if not transformed_entity then
local err_t = self.errors:transformation_error(err)
return nil, tostring(err_t), err_t
end

return transformed_entity
end


Expand Down
45 changes: 31 additions & 14 deletions kong/db/schema/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2058,18 +2058,30 @@ end
--- Run transformations on fields.
-- @param input The input table.
-- @param original_input The original input for transformation detection.
-- @param context a string describing the CRUD context:
-- valid values are: "insert", "update", "upsert", "select"
-- @return the transformed entity
function Schema:transform(input, original_input)
function Schema:transform(input, original_input, context)
if not self.transformations then
return input
end

local output = input
for _, transformation in ipairs(self.transformations) do
local on_write = transformation.on_write
local transform
if context == "select" then
transform = transformation.on_read

else
transform = transformation.on_write
end

if not transform then
goto next
end

local args = {}
local argc = 0
local all_set = true
for _, input_field_name in ipairs(transformation.input) do
local value = get_field(original_input or input, input_field_name)
if is_nonempty(value) then
Expand All @@ -2081,26 +2093,31 @@ function Schema:transform(input, original_input)
end

else
all_set = false
break
goto next
end
end

if all_set then
if transformation.needs then
for _, need in ipairs(transformation.needs) do
if transformation.needs then
for _, need in ipairs(transformation.needs) do
local value = get_field(input, need)
if is_nonempty(value) then
argc = argc + 1
args[argc] = get_field(input, need)
end
end

local data, err = on_write(unpack(args))
if err then
return nil, validation_errors.TRANSFORMATION_ERROR:format(err)
else
goto next
end
end
end

output = self:merge_values(data, output)
local data, err = transform(unpack(args))
if err then
return nil, validation_errors.TRANSFORMATION_ERROR:format(err)
end

output = self:merge_values(data, output)

::next::
end

return output
Expand Down
16 changes: 15 additions & 1 deletion kong/db/schema/metaschema.lua
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,21 @@ local transformations_array = {
{
on_write = {
type = "function",
required = true,
required = false,
},
},
{
on_read = {
type = "function",
required = false,
},
},
},
entity_checks = {
{
at_least_one_of = {
"on_write",
"on_read",
},
},
},
Expand Down
40 changes: 38 additions & 2 deletions spec/01-unit/01-db/01-schema/01-schema_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3598,6 +3598,42 @@ describe("schema", function()
assert.equal("TEST1", transformed_entity.name)
end)

it("transforms fields on write and read", function()
local test_schema = {
name = "test",
fields = {
{
name = {
type = "string"
},
},
},
transformations = {
{
input = { "name" },
on_write = function(name)
return { name = name:upper() }
end,
on_read = function(name)
return { name = name:lower() }
end,
},
},
}
local entity = { name = "TeSt1" }

local TestEntities = Schema.new(test_schema)
local transformed_entity, _ = TestEntities:transform(entity)

assert.truthy(transformed_entity)
assert.equal("TEST1", transformed_entity.name)

transformed_entity, _ = TestEntities:transform(transformed_entity, nil, "select")

assert.truthy(transformed_entity)
assert.equal("test1", transformed_entity.name)
end)

it("transforms fields with input table", function()
local test_schema = {
name = "test",
Expand Down Expand Up @@ -3781,7 +3817,7 @@ describe("schema", function()
assert.equal("transformation failed: unable to transform name", err)
end)

it("does not skip transformation if needs are not fulfilled (this is handled by validation)", function()
it("skips transformation if needs are not fulfilled", function()
local test_schema = {
name = "test",
fields = {
Expand Down Expand Up @@ -3810,7 +3846,7 @@ describe("schema", function()
local transformed_entity, _ = TestEntities:transform(entity)

assert.truthy(transformed_entity)
assert.equal("TEST1", transformed_entity.name)
assert.equal("test1", transformed_entity.name)
end)


Expand Down
60 changes: 60 additions & 0 deletions spec/01-unit/01-db/01-schema/02-metaschema_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,66 @@ describe("metaschema", function()
assert.truthy(MetaSchema:validate(MetaSchema))
end)

it("validates transformation has transformation function specified (positive)", function()
assert.truthy(MetaSchema:validate({
name = "test",
primary_key = { "test" },
fields = {
{ test = { type = "string" } },
},
transformations = {
{
input = { "test" },
on_write = function() return true end,
},
},
}))

assert.truthy(MetaSchema:validate({
name = "test",
primary_key = { "test" },
fields = {
{ test = { type = "string" } },
},
transformations = {
{
input = { "test" },
on_read = function() return true end,
},
},
}))

assert.truthy(MetaSchema:validate({
name = "test",
primary_key = { "test" },
fields = {
{ test = { type = "string" } },
},
transformations = {
{
input = { "test" },
on_read = function() return true end,
on_write = function() return true end,
},
},
}))
end)

it("validates transformation has transformation function specified (negative)", function()
assert.falsy(MetaSchema:validate({
name = "test",
primary_key = { "test" },
fields = {
{ test = { type = "string" } },
},
transformations = {
{
input = { "test" },
},
},
}))
end)

it("validates transformation input fields exists (positive)", function()
assert.truthy(MetaSchema:validate({
name = "test",
Expand Down

0 comments on commit 0b33972

Please sign in to comment.