LuaORM icon indicating copy to clipboard operation
LuaORM copied to clipboard

Custom Field Type Options `convert` and `to` don't seem to be working

Open erichowey opened this issue 5 years ago • 3 comments

I'm setting up a field to transform lua true/false to 0/1 in a tinyint(1) for mysql and vice versa. I have the following custom field type set up for boolean values in mysql:

local sqlBooleanType = API.FieldType({
    luaDataType = "boolean",
    SQLDataType = "tinyint(1)",

    convert = function (_value)
        if _value then
            return "1"
        else
            return "0"
        end
    end,

    to = function (_value)
        if _value == "1" then
            return true
        else
            return false
        end
    end
})

When I save, the fields are null. When I retrieve with fields set to 0/1, the result is always false. I've tried using the other functions validate and as. I can't seem to get it to work.

erichowey avatar Jan 20 '21 23:01 erichowey

I think the problem is that you convert the input values to strings and compare the values from the database to strings. For example if you compare 1 to "1" it will return false:

> print(1 == "1")
false

So it should instead be:

        if _value then
            return 1
        else
            return 0
        end
        if _value == 1 then
            return true
        else
            return false
        end

wesen1 avatar Jan 21 '21 06:01 wesen1

Unfortunately, that doesn't seem to be the issue. When updating the functions as stated, on save, the values are always saved as NULL. When setting the values manually and then retrieving, the result is always false.

Full code to my test app is here: https://gist.github.com/erichowey/bd7f1ca0598e658ef39a9a9ea7b4fa9f

Thank You!

erichowey avatar Jan 21 '21 20:01 erichowey

I checked the LuaORM code, the relevant code is in Table.FieldType.

There are two problems:

  1. The "convert" function is called in multiple cases The method FieldType:convertValueBeforeProcessing() calls the "convert" function that is defined for the FieldType. It is called in these cases:
  • FieldType:validate(): The usage here causes every input value to be invalid, because first the false/true value is converted to 1/0, then this method checks if 1/0 matches the lua data type (boolean)
  • FieldType:convertValueToSQLString(): This is the case where you want to convert the input value to 1 or 0
  • FieldType:convertValueToFieldType(): This causes values that come from the database to always become 1, then when converted to the lua data type all values will become true, finally the "to" function is called with true and returns false

The "convert" function is currently only used in the dateTimeField FieldType, and it is required to be called because input values may be either timestamps as integers or the result of os.date("*t"). The call in FieldType:convertValueToFieldType() could maybe be removed, but the other two are absolutely required for the dateTimeField.

  1. Values from the database are always converted to the lua data type before being given to the "to" function So in this case, if you get "1" or "0" from the database and the lua data type is boolean, all values will become true

I think the behavior that you need requires new config options, one to convert values after validating that they are of the correct lua data type and before generating the SQL insert string for the value, and another to disable/overwrite the conversion of raw query result values to the configured lua data type.

wesen1 avatar Jan 24 '21 23:01 wesen1