diff --git a/kong/db/declarative/import.lua b/kong/db/declarative/import.lua index 2030da85359a..acd67e25e80b 100644 --- a/kong/db/declarative/import.lua +++ b/kong/db/declarative/import.lua @@ -70,6 +70,7 @@ local function workspace_id(schema, options) return get_workspace_id() end + -- global query, like routes:each(page_size, GLOBAL_QUERY_OPTS) if options.workspace == null then return GLOBAL_WORKSPACE_TAG end @@ -243,26 +244,38 @@ local function find_ws(entities, name) end +-- unique key local function unique_field_key(schema_name, ws_id, field, value) - return string_format("%s|%s|%s|%s", schema_name, ws_id, field, sha256_hex(value)) + return string_format("U|%s|%s|%s|%s", schema_name, field, ws_id, sha256_hex(value)) end +-- foreign key local function foreign_field_key_prefix(schema_name, ws_id, field, foreign_id) - return string_format("%s|%s|%s|%s|", schema_name, ws_id, field, foreign_id) + if ws_id == GLOBAL_WORKSPACE_TAG then + return string_format("F|%s|%s|%s|", schema_name, field, foreign_id) + end + return string_format("F|%s|%s|%s|%s|", schema_name, field, foreign_id, ws_id) end local function foreign_field_key(schema_name, ws_id, field, foreign_id, pk) + assert(ws_id ~= GLOBAL_WORKSPACE_TAG) return foreign_field_key_prefix(schema_name, ws_id, field, foreign_id) .. pk end +-- item key local function item_key_prefix(schema_name, ws_id) - return string_format("%s|%s|*|", schema_name, ws_id) + if ws_id == GLOBAL_WORKSPACE_TAG then + return string_format("I|%s|", schema_name) + end + + return string_format("I|%s|%s|", schema_name, ws_id) end local function item_key(schema_name, ws_id, pk_str) + assert(ws_id ~= GLOBAL_WORKSPACE_TAG) return item_key_prefix(schema_name, ws_id) .. pk_str end @@ -307,10 +320,6 @@ local function _set_entity_for_txn(t, entity_name, item, options, is_delete) -- store serialized entity into lmdb t:set(itm_key, itm_value) - -- for global query - local global_key = item_key(entity_name, GLOBAL_WORKSPACE_TAG, pk) - t:set(global_key, idx_value) - -- select_by_cache_key if schema.cache_key then local cache_key = dao:cache_key(item) @@ -347,12 +356,9 @@ local function _set_entity_for_txn(t, entity_name, item, options, is_delete) value_str = pk_string(kong.db[fdata_reference].schema, value) end - for _, wid in ipairs {field_ws_id, GLOBAL_WORKSPACE_TAG} do - local key = unique_field_key(entity_name, wid, fname, value_str or value) - - -- store item_key or nil into lmdb - t:set(key, idx_value) - end + local key = unique_field_key(entity_name, field_ws_id, fname, value_str or value) + -- store item_key or nil into lmdb + t:set(key, idx_value) end if is_foreign then @@ -361,12 +367,9 @@ local function _set_entity_for_txn(t, entity_name, item, options, is_delete) value_str = pk_string(kong.db[fdata_reference].schema, value) - for _, wid in ipairs {field_ws_id, GLOBAL_WORKSPACE_TAG} do - local key = foreign_field_key(entity_name, wid, fname, value_str, pk) - - -- store item_key or nil into lmdb - t:set(key, idx_value) - end + local key = foreign_field_key(entity_name, field_ws_id, fname, value_str, pk) + -- store item_key or nil into lmdb + t:set(key, idx_value) end ::continue:: @@ -380,18 +383,22 @@ end -- the provided LMDB txn object, this operation is only safe -- is the entity does not already exist inside the LMDB database -- --- The actual item key is: ||*| +-- The actual item key is: I||| +-- +-- This function sets the following key-value pairs: -- --- This function sets the following: +-- key: I||| +-- value: serialized item -- --- * ||*| => serialized item --- * |*|*| => actual item key +-- key: U||||sha256(field_value) +-- value: actual item key -- --- * |||sha256(field_value) => actual item key --- * |*||sha256(field_value) => actual item key +-- key: F||||| +-- value: actual item key -- --- * |||| => actual item key --- * |*||| => actual item key +-- The format of the key string follows the sequence of the construction order: +-- `item type > entity name > specific item info > workspace id > item uuid` +-- This order makes it easier to query all entities using API lmdb_prefix.page(). -- -- DO NOT touch `item`, or else the entity will be changed local function insert_entity_for_txn(t, entity_name, item, options) diff --git a/kong/db/strategies/off/init.lua b/kong/db/strategies/off/init.lua index 1fab71dac502..60e80046a7e6 100644 --- a/kong/db/strategies/off/init.lua +++ b/kong/db/strategies/off/init.lua @@ -21,7 +21,6 @@ local item_key_prefix = declarative.item_key_prefix local workspace_id = declarative.workspace_id local foreign_field_key_prefix = declarative.foreign_field_key_prefix - local PROCESS_AUTO_FIELDS_OPTS = { no_defaults = true, show_ws_id = true, @@ -38,11 +37,6 @@ _mt.__index = _mt local UNINIT_WORKSPACE_ID = "00000000-0000-0000-0000-000000000000" -local function need_follow(ws_id) - return ws_id == "*" -end - - local function get_default_workspace() if kong.default_workspace == UNINIT_WORKSPACE_ID then local res = kong.db.workspaces:select_by_name("default") @@ -324,7 +318,7 @@ local function page(self, size, offset, options) return page_for_tags(self, size, offset, options) end - return page_for_prefix(self, prefix, size, offset, options, need_follow(ws_id)) + return page_for_prefix(self, prefix, size, offset, options) end @@ -333,8 +327,26 @@ local function select(self, pk, options) local schema = self.schema local ws_id = workspace_id(schema, options) local pk = pk_string(schema, pk) + + -- if no specific ws_id is provided, we nedd to search all workspace ids + if ws_id == "*" then + for workspace, err in kong.db.workspaces:each() do + if err then + return nil, err + end + + local key = item_key(schema.name, workspace.id, pk) + local entity = select_by_key(schema, key) + if entity then + return entity + end + end + + return nil, "not found" + end + local key = item_key(schema.name, ws_id, pk) - return select_by_key(schema, key, need_follow(ws_id)) + return select_by_key(schema, key) end @@ -367,6 +379,8 @@ local function select_by_field(self, field, value, options) local key = unique_field_key(schema.name, ws_id, field, value) + ngx.log(ngx.INFO, "xxx select by field: key: ", key) + return select_by_key(schema, key, true) end