@@ -7,6 +7,7 @@ local dev_checks = require('crud.common.dev_checks')
77local cache = require (' crud.common.sharding_key_cache' )
88local utils = require (' crud.common.utils' )
99
10+ local ShardingKeyError = errors .new_class (" ShardingKeyError" , {capture_stack = false })
1011local FetchShardingKeyError = errors .new_class (' FetchShardingKeyError' , {capture_stack = false })
1112local WrongShardingConfigurationError = errors .new_class (' WrongShardingConfigurationError' , {capture_stack = false })
1213
@@ -151,12 +152,86 @@ function sharding_key_module.fetch_on_router(space_name, timeout)
151152 " Fetching sharding key for space '%s' is failed" , space_name )
152153end
153154
155+ -- Make sure sharding key definition is a part of primary key.
156+ local function is_part_of_pk (space_name , primary_index_parts , sharding_key_as_index_obj )
157+ dev_checks (' string' , ' table' , ' table' )
158+
159+ if cache .is_part_of_pk [space_name ] ~= nil then
160+ return cache .is_part_of_pk [space_name ]
161+ end
162+
163+ local is_part_of_pk = true
164+ local pk_fieldno_map = utils .get_index_fieldno_map (primary_index_parts )
165+ for _ , part in ipairs (sharding_key_as_index_obj .parts ) do
166+ if pk_fieldno_map [part .fieldno ] == nil then
167+ is_part_of_pk = false
168+ break
169+ end
170+ end
171+ cache .is_part_of_pk [space_name ] = is_part_of_pk
172+
173+ return is_part_of_pk
174+ end
175+
176+ -- Build an array with sharding key values. Function extracts those values from
177+ -- primary key that are part of sharding key (passed as index object).
178+ local function extract_from_index (primary_key , primary_index_parts , sharding_key_as_index_obj )
179+ dev_checks (' table' , ' table' , ' table' )
180+
181+ -- TODO: extract_from_index() calculates primary_index_parts on each
182+ -- request. It is better to cache it's value.
183+ -- https://github.com/tarantool/crud/issues/243
184+ local primary_index_fieldno_map = utils .get_index_fieldno_map (primary_index_parts )
185+
186+ local sharding_key = {}
187+ for _ , part in ipairs (sharding_key_as_index_obj .parts ) do
188+ -- part_number cannot be nil because earlier we checked that tuple
189+ -- field names defined in sharding key definition are part of primary
190+ -- key.
191+ local part_number = primary_index_fieldno_map [part .fieldno ]
192+ assert (part_number ~= nil )
193+ local field_value = primary_key [part_number ]
194+ table.insert (sharding_key , field_value )
195+ end
196+
197+ return sharding_key
198+ end
199+
200+ -- Extract sharding key from pk.
201+ -- Returns a table with sharding key or pair of nil and error.
202+ function sharding_key_module .extract_from_pk (space_name , primary_index_parts , primary_key , timeout )
203+ dev_checks (' string' , ' table' , ' ?' , ' ?number' )
204+
205+ local sharding_key_as_index_obj , err = sharding_key_module .fetch_on_router (space_name , timeout )
206+ if err ~= nil then
207+ return nil , err
208+ end
209+ if sharding_key_as_index_obj == nil then
210+ return primary_key
211+ end
212+
213+ local res = is_part_of_pk (space_name , primary_index_parts , sharding_key_as_index_obj )
214+ if res == false then
215+ return nil , ShardingKeyError :new (
216+ " Sharding key for space %q is missed in primary index, specify bucket_id" ,
217+ space_name
218+ )
219+ end
220+ if type (primary_key ) ~= ' table' then
221+ primary_key = {primary_key }
222+ end
223+
224+ return extract_from_index (primary_key , primary_index_parts , sharding_key_as_index_obj )
225+ end
226+
154227function sharding_key_module .init ()
155228 _G ._crud .fetch_on_storage = sharding_key_module .fetch_on_storage
156229end
157230
158231sharding_key_module .internal = {
159232 as_index_object = as_index_object ,
233+ extract_from_index = extract_from_index ,
234+ is_part_of_pk = is_part_of_pk ,
160235}
161236
162237return sharding_key_module
0 commit comments