@@ -19,6 +19,7 @@ import module namespace admin = "http://marklogic.com/xdmp/admin" at "/MarkLogic
1919import module namespace sec="http://marklogic.com/xdmp/security" at "/MarkLogic/security.xqy" ;
2020import module namespace pki = "http://marklogic.com/xdmp/pki" at "/MarkLogic/pki.xqy" ;
2121import module namespace functx="http://www.functx.com" at "/MarkLogic/functx/functx-1.0-nodoc-2007-01.xqy" ;
22+ import module namespace search = "http://marklogic.com/appservices/search" at "/MarkLogic/appservices/search/search.xqy" ;
2223
2324declare namespace setup = "http://marklogic.com/roxy/setup" ;
2425declare namespace xdmp="http://marklogic.com/xdmp" ;
@@ -374,6 +375,8 @@ declare function setup:get-rollback-config()
374375{
375376 element configuration
376377 {
378+ attribute rollback { fn:true () },
379+
377380 map:get ($roll-back, "task-server" ),
378381
379382 element gr:http-servers
@@ -420,6 +423,119 @@ declare function setup:get-rollback-config()
420423 }
421424};
422425
426+ declare variable $cts:element-reference := fn:function-lookup (xs:QName ("cts:element-reference" ), 2 );
427+ declare variable $cts:parse := fn:function-lookup (xs:QName ("cts:parse" ), 2 );
428+
429+ declare variable $if-parser := ();
430+
431+ declare function setup:get-if-parser ($properties as map:map) {
432+ if ($if-parser) then
433+ $if-parser
434+ else
435+ let $parser := function ($query) {
436+ (:
437+ if (fn:exists($cts:parse)) then
438+ if (fn:number(substring-before(xdmp:version(), ".")) ge 8) then
439+ :)
440+ (: [GJo] There are some issue with cts:parse, like it choking on "rest-ext.dir EQ something"
441+ Bug filed. Using search:parse for now.
442+ :)
443+ if (fn:false ()) then
444+ let $bindings := map:new ((
445+ for $property in map:keys ($properties)
446+ let $name := fn:replace ($property, "^ml[._\-]" , "" )
447+ return map:entry ($name, $cts:element-reference(xs:QName ($property), ("type=int" , "unchecked" )))
448+ ))
449+ return ($cts:parse($query, $bindings), $bindings)
450+ else
451+ let $options := <options xmlns = "http://marklogic.com/appservices/search" >{
452+ for $property in map:keys ($properties)
453+ let $name := fn:replace ($property, "^ml[._\-]" , "" )
454+ return <constraint name = "{$name} " >
455+ <range type = "xs:string" collation = "http://marklogic.com/collation/" >
456+ <element ns = "" name = "{$property} " />
457+ </range>
458+ </constraint>
459+ }</options>
460+ return (cts:query (search:parse (fn:replace ($query, " EQ " , " : " ), $options)), $options)
461+ }
462+ let $_ := xdmp:set ($if-parser, $parser)
463+ return $parser
464+ };
465+
466+ declare function setup:eval-query ($query as cts:query, $properties as map:map) {
467+ typeswitch ($query)
468+ case cts:and-query return fn:not (
469+ (cts:and-query-queries ($query) ! setup:eval-query (., $properties)) = fn:false ()
470+ )
471+ case cts:or-query return (
472+ (cts:or-query-queries ($query) ! setup:eval-query (., $properties)) = fn:true ()
473+ )
474+ case cts:not-query return fn:not (
475+ cts:not-query-query ($query) ! setup:eval-query (., $properties)
476+ )
477+ case cts:element-value-query return (
478+ let $property := fn:string (cts:element-value-query-element-name ($query))
479+ let $operator := '='
480+ let $values := cts:element-value-query-text ($query)
481+ return map:get ($properties, $property) = $values
482+ )
483+ case cts:element-word-query return (
484+ let $property := fn:string (cts:element-word-query-element-name ($query))
485+ let $operator := '='
486+ let $values := cts:element-word-query-text ($query)
487+ return map:get ($properties, $property) = $values
488+ )
489+ case cts:element-range-query return (
490+ let $property := fn:string (cts:element-range-query-element-name ($query))
491+ let $operator := cts:element-range-query-operator ($query)
492+ let $values := cts:element-range-query-value ($query)
493+ return
494+ if ($operator = ('=' , '!=' , '>' , '>=' , '<' , '<=' )) then
495+ xdmp:value ("map:get($properties, $property) " || $operator || " $values" )
496+ else
497+ fn:error (xs:QName ("UNSUPPORTED" ), "Unsupported operator " || $operator)
498+ )
499+ case cts:word-query return (
500+ fn:error (xs:QName ("SYNTAX" ), "Syntax error near " || cts:word-query-text ($query))
501+ )
502+ default return (
503+ fn:error (xs:QName ("UNSUPPORTED" ), "Cannot parse " || fn:upper-case (fn:replace (fn:string (xdmp:type ($query)), "-query$" , "" )))
504+ )
505+ };
506+
507+ declare function setup:process-conditionals ($nodes, $properties) {
508+ for $node in $nodes
509+ return
510+ typeswitch ($node)
511+ case element () return
512+ let $if-valid :=
513+ if (fn:exists ($node/@if )) then
514+ let $parser := setup:get-if-parser ($properties)
515+ let $expression := string ($node/@if )
516+ return try {
517+ let $query := $parser($expression)[1 ]
518+ return try {
519+ setup:eval-query ($query, $properties)
520+ } catch ($e) {
521+ fn:error (xs:QName ("IF-PARSE-ERROR" ),
522+ "Unable to evauluate the expression '" || $expression || "': " || $e/error:format-string/data ())
523+ }
524+ } catch ($e) {
525+ fn:error (xs:QName ("IF-PARSE-ERROR" ),
526+ "Unable to parse the expression '" || $expression || "': " || $e/error:format-string/data ())
527+ }
528+ else
529+ fn:true ()
530+ where $if-valid
531+ return element { fn:node-name ($node) } {
532+ $node/@*,
533+ setup:process-conditionals ($node/node (), $properties)
534+ }
535+ case comment () return ()
536+ default return $node
537+ };
538+
423539declare function setup:suppress-comments ($nodes) {
424540 for $node in $nodes
425541 return
@@ -434,18 +550,20 @@ declare function setup:suppress-comments($nodes) {
434550};
435551
436552(: for backwards-compatibility :)
437- declare function setup:rewrite-config ($import-configs as element (configuration)+) as element (configuration)
553+ declare function setup:rewrite-config ($import-configs as element (configuration)+, $properties as map:map ) as element (configuration)
438554{
439- setup:rewrite-config ($import-configs, ())
555+ setup:rewrite-config ($import-configs, $properties, ())
440556};
441557
442- declare function setup:rewrite-config ($import-configs as element (configuration)+, $silent as xs:boolean?) as element (configuration)
558+ declare function setup:rewrite-config ($import-configs as element (configuration)+, $properties as map:map, $ silent as xs:boolean?) as element (configuration)
443559{
444560 let $config :=
445561 element { fn:node-name ($import-configs[1 ]) } {
446562 $import-configs/@*,
447563
448- <groups xmlns = "http://marklogic.com/xdmp/group" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://marklogic.com/xdmp/group group.xsd" >{
564+ <groups xmlns = "http://marklogic.com/xdmp/group" >{
565+ $import-configs/gr:groups/@*,
566+
449567 let $default-group := ($import-configs/@default-group , "Default" )[1 ]
450568 for $group in fn:distinct-values (
451569 ($import-configs/gr:groups/gr:group /gr:group-name, $import-configs/(gr:http-servers/gr:http-server, gr:xdbc-servers/gr:xdbc-server,
@@ -460,6 +578,7 @@ declare function setup:rewrite-config($import-configs as element(configuration)+
460578 where fn:exists ($servers | $databases | $group-config)
461579 return
462580 <group>
581+ { $group-config/@* }
463582 <group-name>{$group}</group-name>
464583 {
465584 if ($http-servers) then
@@ -495,7 +614,7 @@ declare function setup:rewrite-config($import-configs as element(configuration)+
495614 fn:concat ("No hosts assigned to group " , $group, ", needed for app servers and forests!" ))
496615
497616 (: all good :)
498- return setup:suppress-comments ($config)
617+ return setup:process-conditionals ( setup: suppress-comments ($config), $properties )
499618};
500619
501620
@@ -544,15 +663,15 @@ declare private function setup:parse-options( $options as xs:string ) as map:map
544663 return $optionsMap
545664};
546665
547- declare function setup:do-setup ($import-config as element (configuration)+, $options as xs:string) as item ()*
666+ declare function setup:do-setup ($import-config as element (configuration)+, $options as xs:string, $properties as map:map ) as item ()*
548667{
549668 let $optionsMap := setup:parse-options ( $options )
550669 let $do-internals := map:contains ( $optionsMap, "internals" )
551670
552671 return
553672 try
554673 {
555- let $import-config := setup:rewrite-config ($import-config)
674+ let $import-config := setup:rewrite-config ($import-config, $properties )
556675 return (
557676 if (fn:not ($do-internals)) then (
558677 (: Security related :)
@@ -606,12 +725,12 @@ declare function setup:do-setup($import-config as element(configuration)+, $opti
606725 configuring external authentication. ' )
607726 else (),
608727 xdmp:log ($ex),
609- setup:do-wipe (setup:get-rollback-config (), "" ),
728+ setup:do-wipe (setup:get-rollback-config (), $options, $properties ),
610729 fn:concat ($ex/err:format-string/text (), ' See MarkLogic Server error log for more details.' )
611730 }
612731};
613732
614- declare function setup:do-wipe ($import-config as element (configuration)+, $options as xs:string) as item ()*
733+ declare function setup:do-wipe ($import-config as element (configuration)+, $options as xs:string, $properties as map:map ) as item ()*
615734{
616735 let $options := if (fn:empty ($options) or $options eq "" ) then ("all" ) else fn:tokenize ($options, "," )
617736
@@ -623,7 +742,11 @@ declare function setup:do-wipe($import-config as element(configuration)+, $optio
623742 return
624743 try
625744 {
626- let $import-config := setup:rewrite-config ($import-config, fn:true ())
745+ let $import-config :=
746+ if ($import-config/@rollback = "true" ) then
747+ $import-config
748+ else
749+ setup:rewrite-config ($import-config, fn:true (), $properties)
627750 return (
628751
629752 (: remove scheduled tasks :)
@@ -1038,7 +1161,7 @@ declare function setup:do-wipe($import-config as element(configuration)+, $optio
10381161 Attempt to remove replicas that are to be decommissioned due to scaling out of the cluster.
10391162 Replicas are only removed after their new replacements have gone to sync replication.
10401163:)
1041- declare function setup:do-clean-replicas ($import-config as element (configuration)+, $options as xs:string) as item ()*
1164+ declare function setup:do-clean-replicas ($import-config as element (configuration)+, $options as xs:string, $properties as map:map ) as item ()*
10421165{
10431166 let $optionsMap := setup:parse-options ( $options )
10441167 let $do-internals := map:contains ( $optionsMap, "internals" )
@@ -1048,6 +1171,7 @@ declare function setup:do-clean-replicas($import-config as element(configuration
10481171 return
10491172 try {
10501173 if (map:count ( $delete-map ) ) then
1174+ let $import-config := setup:rewrite-config ($import-config, $properties)
10511175 (: Loop over the replicas we are waiting for and check state :)
10521176 let $reps-waiting :=
10531177 for $rep in map:keys ( $replicating-map )
@@ -1095,7 +1219,7 @@ declare function setup:do-clean-replicas($import-config as element(configuration
10951219 let $_ := xdmp:log ( "Updating configuration." )
10961220 let $_ := admin:save-configuration ( map:get ( $updated-config, "admin-config" ) )
10971221
1098- let $_ := setup:do-clean-replicas-state ( $import-config, $ options )
1222+ let $_ := setup:do-clean-replicas-state ( $options )
10991223
11001224 let $_ := xdmp:log ( fn:string-join ( ( "Clean replicas complete:" , $cleaned ), "
 " ) )
11011225 return ( fn:string-join ( ( "Clean replicas complete:" , $cleaned ), "
 " ) )
@@ -1119,7 +1243,7 @@ declare function setup:do-clean-replicas($import-config as element(configuration
11191243(:
11201244 Cleanup scale-out replica state files.
11211245:)
1122- declare function setup:do-clean-replicas-state ($import-config as element (configuration)+, $ options as xs:string) as item ()*
1246+ declare function setup:do-clean-replicas-state ($options as xs:string) as item ()*
11231247{
11241248 let $optionsMap := setup:parse-options ( $options )
11251249 let $do-internals := map:contains ( $optionsMap, "internals" )
@@ -6058,11 +6182,11 @@ declare function setup:validation-fail($message)
60586182 fn:error (xs:QName ("VALIDATION-FAIL" ), $message)
60596183};
60606184
6061- declare function setup:validate-install ($import-config as element (configuration))
6185+ declare function setup:validate-install ($import-config as element (configuration), $properties as map:map )
60626186{
60636187 try
60646188 {
6065- let $import-config := setup:rewrite-config ($import-config)
6189+ let $import-config := setup:rewrite-config ($import-config, $properties )
60666190 return (
60676191 setup:validate-external-security ($import-config),
60686192 setup:validate-privileges ($import-config),
0 commit comments