3333 name /1 ,
3434 type /1 ,
3535 def /1 ,
36+ partitioned /1 ,
3637 opts /1 ,
3738 columns /1 ,
3839 is_usable /3 ,
@@ -59,8 +60,10 @@ list(Db) ->
5960
6061get_usable_indexes (Db , Selector , Opts ) ->
6162 ExistingIndexes = mango_idx :list (Db ),
62-
63- GlobalIndexes = mango_cursor :remove_indexes_with_partial_filter_selector (ExistingIndexes ),
63+ MatchingPartitionIndexes = filter_partition_indexes (ExistingIndexes , Opts ),
64+ GlobalIndexes = mango_cursor :remove_indexes_with_partial_filter_selector (
65+ MatchingPartitionIndexes
66+ ),
6467 UserSpecifiedIndex = mango_cursor :maybe_filter_indexes_by_ddoc (ExistingIndexes , Opts ),
6568 UsableIndexes0 = lists :usort (GlobalIndexes ++ UserSpecifiedIndex ),
6669
@@ -110,6 +113,7 @@ new(Db, Opts) ->
110113 name = IdxName ,
111114 type = Type ,
112115 def = Def ,
116+ partitioned = get_idx_partitioned (Opts ),
113117 opts = filter_opts (Opts )
114118 }}.
115119
@@ -121,10 +125,11 @@ validate_new(Idx, Db) ->
121125
122126add (DDoc , Idx ) ->
123127 Mod = idx_mod (Idx ),
124- {ok , NewDDoc } = Mod :add (DDoc , Idx ),
128+ {ok , NewDDoc1 } = Mod :add (DDoc , Idx ),
129+ NewDDoc2 = set_ddoc_partitioned (NewDDoc1 , Idx ),
125130 % Round trip through JSON for normalization
126- Body = ? JSON_DECODE (? JSON_ENCODE (NewDDoc # doc .body )),
127- {ok , NewDDoc # doc {body = Body }}.
131+ Body = ? JSON_DECODE (? JSON_ENCODE (NewDDoc2 # doc .body )),
132+ {ok , NewDDoc2 # doc {body = Body }}.
128133
129134
130135remove (DDoc , Idx ) ->
@@ -176,7 +181,8 @@ from_ddoc(Db, {Props}) ->
176181 lists :map (fun (Idx ) ->
177182 Idx # idx {
178183 dbname = DbName ,
179- ddoc = DDoc
184+ ddoc = DDoc ,
185+ partitioned = set_idx_partitioned (Db , Props )
180186 }
181187 end , Idxs ).
182188
@@ -213,6 +219,10 @@ def(#idx{def=Def}) ->
213219 Def .
214220
215221
222+ partitioned (# idx {partitioned = Partitioned }) ->
223+ Partitioned .
224+
225+
216226opts (# idx {opts = Opts }) ->
217227 Opts .
218228
@@ -329,6 +339,87 @@ gen_name(Idx, Opts0) ->
329339 mango_util :enc_hex (Sha ).
330340
331341
342+ get_idx_partitioned (Opts ) ->
343+ case proplists :get_value (partitioned , Opts ) of
344+ B when is_boolean (B ) ->
345+ B ;
346+ default ->
347+ undefined
348+ end .
349+
350+
351+ set_ddoc_partitioned (DDoc , Idx ) ->
352+ % We have to verify that the new index being added
353+ % to this design document either matches the current
354+ % ddoc's design options *or* this is a new design doc
355+ # doc {
356+ id = DDocId ,
357+ revs = Revs ,
358+ body = {BodyProps }
359+ } = DDoc ,
360+ OldDOpts = couch_util :get_value (<<" options" >>, BodyProps ),
361+ OldOpt = case OldDOpts of
362+ {OldDOptProps } when is_list (OldDOptProps ) ->
363+ couch_util :get_value (<<" partitioned" >>, OldDOptProps );
364+ _ ->
365+ undefined
366+ end ,
367+ % If new matches old we're done
368+ if Idx # idx .partitioned == OldOpt -> DDoc ; true ->
369+ % If we're creating a ddoc then we can set the options
370+ case Revs == {0 , []} of
371+ true when Idx # idx .partitioned /= undefined ->
372+ set_ddoc_partitioned_option (DDoc , Idx # idx .partitioned );
373+ true when Idx # idx .partitioned == undefined ->
374+ DDoc ;
375+ false ->
376+ ? MANGO_ERROR ({partitioned_option_mismatch , DDocId })
377+ end
378+ end .
379+
380+
381+ set_ddoc_partitioned_option (DDoc , Partitioned ) ->
382+ # doc {
383+ body = {BodyProps }
384+ } = DDoc ,
385+ NewProps = case couch_util :get_value (<<" options" >>, BodyProps ) of
386+ {Existing } when is_list (Existing ) ->
387+ Opt = {<<" partitioned" >>, Partitioned },
388+ New = lists :keystore (<<" partitioned" >>, 1 , Existing , Opt ),
389+ lists :keystore (<<" options" >>, 1 , BodyProps , {<<" options" >>, New });
390+ undefined ->
391+ New = {<<" options" >>, {[{<<" partitioned" >>, Partitioned }]}},
392+ lists :keystore (<<" options" >>, 1 , BodyProps , New )
393+ end ,
394+ DDoc # doc {body = {NewProps }}.
395+
396+
397+ set_idx_partitioned (Db , DDocProps ) ->
398+ Default = fabric_util :is_partitioned (Db ),
399+ case couch_util :get_value (<<" options" >>, DDocProps ) of
400+ {DesignOpts } ->
401+ case couch_util :get_value (<<" partitioned" >>, DesignOpts ) of
402+ P when is_boolean (P ) ->
403+ P ;
404+ undefined ->
405+ Default
406+ end ;
407+ undefined ->
408+ Default
409+ end .
410+
411+
412+ filter_partition_indexes (Indexes , Opts ) ->
413+ PFilt = case couch_util :get_value (partition , Opts ) of
414+ <<>> ->
415+ fun (# idx {partitioned = P }) -> not P end ;
416+ Partition when is_binary (Partition ) ->
417+ fun (# idx {partitioned = P }) -> P end
418+ end ,
419+ Filt = fun (Idx ) -> type (Idx ) == <<" special" >> orelse PFilt (Idx ) end ,
420+ lists :filter (Filt , Indexes ).
421+
422+
332423filter_opts ([]) ->
333424 [];
334425filter_opts ([{user_ctx , _ } | Rest ]) ->
@@ -341,6 +432,8 @@ filter_opts([{type, _} | Rest]) ->
341432 filter_opts (Rest );
342433filter_opts ([{w , _ } | Rest ]) ->
343434 filter_opts (Rest );
435+ filter_opts ([{partitioned , _ } | Rest ]) ->
436+ filter_opts (Rest );
344437filter_opts ([Opt | Rest ]) ->
345438 [Opt | filter_opts (Rest )].
346439
0 commit comments