Skip to content
This repository was archived by the owner on Nov 9, 2022. It is now read-only.

Commit 4abf5c6

Browse files
committed
Fixed #692: leveraging search:parse to evaluate if's against properties
1 parent c25b8e3 commit 4abf5c6

File tree

2 files changed

+154
-24
lines changed

2 files changed

+154
-24
lines changed

deploy/lib/server_config.rb

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -761,12 +761,20 @@ def reindex_db(target_db)
761761
logger.info r.body
762762
end
763763

764+
def properties_map
765+
entries = []
766+
@properties.each do |k, v|
767+
entries.push %Q{map:entry("#{k}", "#{v}")}
768+
end
769+
"map:new((\n" + entries.join(",\n ")+ "))"
770+
end
771+
764772
def config
765773
setup = File.read ServerConfig.expand_path("#{@@path}/lib/xquery/setup.xqy")
766774
r = execute_query %Q{
767775
#{setup}
768776
try {
769-
setup:rewrite-config(#{get_config})
777+
setup:rewrite-config(#{get_config}, #{properties_map})
770778
} catch($ex) {
771779
xdmp:log($ex),
772780
fn:concat($ex/err:format-string/text(), '
See MarkLogic Server error log for more details.')
@@ -868,7 +876,7 @@ def bootstrap
868876
end
869877

870878
setup = File.read(ServerConfig.expand_path("#{@@path}/lib/xquery/setup.xqy"))
871-
r = execute_query %Q{#{setup} setup:do-setup(#{config}, "#{apply_changes},#{dointernals}")}
879+
r = execute_query %Q{#{setup} setup:do-setup(#{config}, "#{apply_changes},#{dointernals}", #{properties_map})}
872880
logger.debug "code: #{r.code.to_i}"
873881

874882
r.body = parse_body(r.body)
@@ -895,15 +903,13 @@ def clean_replicas_state
895903
if internals == nil
896904
internals = ''
897905
logger.info "Cleaning application forest decommissioned replica state"
898-
config = get_config
899906
else
900907
logger.info "Cleaning interal forest decommissioned replica state"
901908
internals = 'internals'
902-
config = get_config
903909
end
904910

905911
setup = File.read(ServerConfig.expand_path("#{@@path}/lib/xquery/setup.xqy"))
906-
r = execute_query %Q{#{setup} setup:do-clean-replicas-state(#{config}, "#{internals}")}
912+
r = execute_query %Q{#{setup} setup:do-clean-replicas-state("#{internals}")}
907913

908914
if r.body.match("error log")
909915
logger.error r.body
@@ -930,7 +936,7 @@ def clean_replicas
930936
end
931937

932938
setup = File.read(ServerConfig.expand_path("#{@@path}/lib/xquery/setup.xqy"))
933-
r = execute_query %Q{#{setup} setup:do-clean-replicas(#{config}, "#{internals}")}
939+
r = execute_query %Q{#{setup} setup:do-clean-replicas(#{config}, "#{internals}", #{properties_map})}
934940
logger.debug "code: #{r.code.to_i}"
935941

936942
r.body = parse_body(r.body)
@@ -1088,15 +1094,15 @@ def wipe
10881094
10891095
}
10901096
else
1091-
#logger.debug %Q{#{setup} setup:do-wipe(#{config})}
1097+
#logger.debug %Q{#{setup} setup:do-wipe(#{config}, #{properties_map})}
10921098

10931099
wipe_changes = find_arg(['--apply-changes'])
10941100

10951101
if wipe_changes == nil or wipe_changes == ""
10961102
wipe_changes = "all"
10971103
end
10981104

1099-
r = execute_query %Q{#{setup} setup:do-wipe(#{config}, "#{wipe_changes}")}
1105+
r = execute_query %Q{#{setup} setup:do-wipe(#{config}, "#{wipe_changes}", #{properties_map})}
11001106
end
11011107
logger.debug "code: #{r.code.to_i}"
11021108

@@ -1128,7 +1134,7 @@ def validate_install
11281134
logger.info "Validating your project installation into MarkLogic on #{@hostname}..."
11291135
setup = File.read(ServerConfig.expand_path("#{@@path}/lib/xquery/setup.xqy"))
11301136
begin
1131-
r = execute_query %Q{#{setup} setup:validate-install(#{get_config})}
1137+
r = execute_query %Q{#{setup} setup:validate-install(#{get_config}, #{properties_map})}
11321138
logger.debug "code: #{r.code.to_i}"
11331139

11341140
r.body = parse_body(r.body)

deploy/lib/xquery/setup.xqy

Lines changed: 139 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import module namespace admin = "http://marklogic.com/xdmp/admin" at "/MarkLogic
1919
import module namespace sec="http://marklogic.com/xdmp/security" at "/MarkLogic/security.xqy";
2020
import module namespace pki = "http://marklogic.com/xdmp/pki" at "/MarkLogic/pki.xqy";
2121
import 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

2324
declare namespace setup = "http://marklogic.com/roxy/setup";
2425
declare 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+
423539
declare 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.&#10;&#10;' )
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(), '&#10;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 ), "&#x0a;" ) )
11011225
return( fn:string-join( ( "Clean replicas complete:", $cleaned ), "&#x0a;" ) )
@@ -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

Comments
 (0)