function Schema:process_auto_fields()

in kong/kong/db/schema/init.lua [1606:1823]


function Schema:process_auto_fields(data, context, nulls, opts)
  yield(true)

  local check_immutable_fields = false

  local is_select = context == "select"
  if not is_select then
    data = tablex.deepcopy(data)
  end

  local shorthand_fields = self.shorthand_fields
  if shorthand_fields then
    local errs = {}
    local has_errs
    for i = 1, #shorthand_fields do
      local sname, sdata = next(shorthand_fields[i])
      local value = data[sname]
      if value ~= nil then
        local _, err = self:validate_field(sdata, value)
        if err then
          errs[sname] = err
          has_errs = true
        else
          data[sname] = nil
          local new_values = sdata.func(value)
          if new_values then
            for k, v in pairs(new_values) do
              data[k] = v
            end
          end
        end
      end
    end
    if has_errs then
      return nil, errs
    end
  end

  local now_s
  local now_ms

  
  
  
  
  local kong = kong
  local resolve_references
  if is_select and not nulls then
    if kong and kong.configuration then
      resolve_references = kong.configuration.role ~= "control_plane"
    else
      resolve_references = true
    end
  end

  local refs
  local prev_refs = resolve_references and data["$refs"]

  for key, field in self:each_field(data) do
    local ftype = field.type
    local value = data[key]
    if not is_select and field.auto then
      local is_insert_or_upsert = context == "insert" or context == "upsert"
      if field.uuid then
        if is_insert_or_upsert and value == nil then
          value = uuid()
        end

      elseif ftype == "string" then
        if is_insert_or_upsert and value == nil then
          value = random_string()
        end

      elseif (key == "created_at" and is_insert_or_upsert and (value == null or
                                                               value == nil))
      or
             (key == "updated_at" and (is_insert_or_upsert or context == "update"))
      then
        if ftype == "number" then
          if not now_ms then
            update_time()
            now_ms = ngx_now()
          end
          value = now_ms

        elseif ftype == "integer" then
          if not now_s then
            update_time()
            now_s = ngx_time()
          end
          value = now_s
        end
      end
    end

    value = adjust_field_for_context(field, value, context, nulls, opts)

    if is_select then
      local vtype = type(value)
      if value == null and not nulls then
        value = nil
      elseif ftype == "integer" and vtype == "number" then
        value = floor(value)
      end

      if resolve_references then
        if ftype == "string" and field.referenceable then
          if is_reference(value) then
            if refs then
              refs[key] = value
            else
              refs = { [key] = value }
            end

            local deref, err = kong.vault.get(value)
            if deref then
              value = deref

            else
              if err then
                kong.log.warn("unable to resolve reference ", value, " (", err, ")")
              else
                kong.log.warn("unable to resolve reference ", value)
              end

              value = nil
            end

          elseif prev_refs and prev_refs[key] then
            if refs then
              refs[key] = prev_refs[key]
            else
              refs = { [key] = prev_refs[key] }
            end
          end

        elseif vtype == "table" and (ftype == "array" or ftype == "set") then
          local subfield = field.elements
          if subfield.type == "string" and subfield.referenceable then
            local count = #value
            if count > 0 then
              for i = 1, count do
                if is_reference(value[i]) then
                  if not refs then
                    refs = {}
                  end

                  if not refs[key] then
                    refs[key] = new_tab(count, 0)
                  end

                  refs[key][i] = value[i]

                  local deref, err = kong.vault.get(value[i])
                  if deref then
                    value[i] = deref

                  else
                    if err then
                      kong.log.warn("unable to resolve reference ", value[i], " (", err, ")")
                    else
                      kong.log.warn("unable to resolve reference ", value[i])
                    end

                    value[i] = nil
                  end
                end
              end
            end

            if prev_refs and prev_refs[key] then
              if refs then
                if not refs[key] then
                  refs[key] = prev_refs[key]
                end

              else
                refs = { [key] = prev_refs[key] }
              end
            end
          end
        end
      end

    elseif context == "update" and field.immutable then
      check_immutable_fields = true
    end

    data[key] = value
  end

  if not is_select then
    return data, nil, check_immutable_fields
  end

  if self.ttl and data.ttl == null and not nulls then
    data.ttl = nil
  end

  local show_ws = opts and opts.show_ws_id
  for key in pairs(data) do
    local field = self.fields[key]
    if field then
      if field.type == "string" and (field.len_min or 1) > 0 and data[key] == ""
      then
        data[key] = nulls and null or nil
      end

    elseif not ((key == "ttl"   and self.ttl) or
                (key == "ws_id" and show_ws)) then
      data[key] = nil
    end
  end

  data["$refs"] = refs

  return data
end