Skip to content

Commit

Permalink
Can now manage range indexes.
Browse files Browse the repository at this point in the history
  • Loading branch information
ryangrimm committed Jun 30, 2011
1 parent 02e8fd5 commit 98037d7
Show file tree
Hide file tree
Showing 6 changed files with 199 additions and 31 deletions.
2 changes: 0 additions & 2 deletions config/endpoints.xqy
Expand Up @@ -44,15 +44,13 @@ declare variable $endpoints:ENDPOINTS as element(rest:options) :=
<http method="DELETE"/>
</request>

<!--
<request uri="^/data/manage/range/([A-Za-z0-9-]+)(/)?$" endpoint="/data/manage/range.xqy" user-params="allow">
<uri-param name="name" as="string">$1</uri-param>
<http method="GET"/>
<http method="POST"/>
<http method="PUT"/>
<http method="DELETE"/>
</request>
-->
</options>;

declare function endpoints:options(
Expand Down
11 changes: 1 addition & 10 deletions data/info.xqy
Expand Up @@ -48,16 +48,7 @@ json:document(
"keyValuePhrases", admin:database-get-fast-element-phrase-searches($config, $database),
"keyValueTrailingWildcards", admin:database-get-fast-element-trailing-wildcard-searches($config, $database),
"geo", json:array(),
"keyValueRanges", json:array(
for $index in admin:database-get-range-element-indexes($config, $database)
for $key in tokenize(string($index/*:localname), " ")
where string-length(string($index/*:namespace-uri)) = 0
return json:object((
"type", string($index/*:scalar-type),
"key", json:unescapeNCName($key),
if($index/*:scalar-type = "string") then ("collation", string($index/*:collation)) else ()
)
)),
"ranges", json:array(manage:getRangeDefinitions()),
"fields", json:array(
for $field in admin:database-get-fields($config, $database)
where string-length($field/*:field-name) > 0
Expand Down
68 changes: 68 additions & 0 deletions data/lib/manage.xqy
Expand Up @@ -19,6 +19,7 @@ xquery version "1.0-ml";
module namespace manage="http://marklogic.com/mljson/manage";

import module namespace json="http://marklogic.com/json" at "json.xqy";
import module namespace prop="http://xqdev.com/prop" at "properties.xqy";
import module namespace admin = "http://marklogic.com/xdmp/admin" at "/MarkLogic/admin.xqy";

declare namespace db="http://marklogic.com/xdmp/database";
Expand All @@ -43,3 +44,70 @@ declare function manage:fieldDefinitionToJsonXml(
)
))
};

declare function manage:rangeDefinitionToJsonXml(
$index as element(db:range-element-index),
$name as xs:string,
$operator as xs:string
) as element(json:item)
{
json:object((
"name", $name,
"key", json:unescapeNCName(string($index/*:localname)),
"type", string($index/*:scalar-type),
"operator", $operator
))
};

declare function manage:jsonTypeToSchemaType(
$type as xs:string?
) as xs:string?
{
if(empty($type))
then ()
else if($type = "string")
then "string"
else if($type = "date")
then "dateTime"
else "decimal"
};

declare function manage:getRangeIndexProperties(
) as xs:string*
{
for $key in prop:all()
let $value := prop:get($key)
where starts-with($key, "index-") and starts-with($value, "range/")
return $value
};

declare function manage:getPropertiesAssociatedWithRangeIndex(
$index as element(db:range-element-index)
) as xs:string*
{
for $value in manage:getRangeIndexProperties()
let $bits := tokenize($value, "/")
let $key := $bits[3]
let $type := $bits[4]
where $index/*:scalar-type = manage:jsonTypeToSchemaType($type) and $index/*:namespace-uri = "http://marklogic.com/json" and $index/*:localname = $key
return $value
};

declare function manage:getRangeDefinitions(
) as element(json:item)*
{
let $config := admin:get-configuration()
let $existingIndexes := admin:database-get-range-element-indexes($config, xdmp:database())

for $value in manage:getRangeIndexProperties()
let $bits := tokenize($value, "/")
let $name := $bits[2]
let $key := $bits[3]
let $type := $bits[4]
let $operator := $bits[5]
let $index :=
for $index in $existingIndexes
where $index/*:scalar-type = manage:jsonTypeToSchemaType($type) and $index/*:namespace-uri = "http://marklogic.com/json" and $index/*:localname = $key
return $index
return manage:rangeDefinitionToJsonXml($index, $name, $operator)
};
9 changes: 9 additions & 0 deletions data/lib/properties.xqy
Expand Up @@ -176,3 +176,12 @@ declare function prop:get(
()
}
};

declare function prop:all(
) as xs:string*
{
let $config := admin:get-configuration()
for $ns in admin:group-get-namespaces($config, xdmp:group())
where starts-with($ns/*:namespace-uri, "http://xqdev.com/prop/")
return string($ns/*:prefix)
};
46 changes: 27 additions & 19 deletions data/manage/field.xqy
Expand Up @@ -20,6 +20,7 @@ import module namespace manage="http://marklogic.com/mljson/manage" at "../lib/m
import module namespace common="http://marklogic.com/mljson/common" at "../lib/common.xqy";
import module namespace json="http://marklogic.com/json" at "../lib/json.xqy";

import module namespace prop="http://xqdev.com/prop" at "../lib/properties.xqy";
import module namespace rest="http://marklogic.com/appservices/rest" at "../lib/rest/rest.xqy";
import module namespace endpoints="http://marklogic.com/mljson/endpoints" at "/config/endpoints.xqy";
import module namespace admin = "http://marklogic.com/xdmp/admin" at "/MarkLogic/admin.xqy";
Expand Down Expand Up @@ -47,29 +48,36 @@ return
else common:error(404, "Field not found")

else if($requestMethod = ("PUT", "POST"))
then (
if(exists($existing))
then xdmp:set($config, admin:database-delete-field($config, $database, $name))
else (),
then
if(exists(prop:get(concat("index-", $name))))
then common:error(500, concat("An index, field or alias with the name '", $name, "' already exists"))
else (
if(exists($existing))
then xdmp:set($config, admin:database-delete-field($config, $database, $name))
else (),

let $config := admin:database-add-field($config, $database, admin:database-field($name, false()))
let $includes := xdmp:get-request-field("include")
let $excludes := xdmp:get-request-field("exclude")
let $add :=
for $include in $includes
let $include := json:escapeNCName($include)
let $el := admin:database-included-element("http://marklogic.com/json", $include, 1, (), "", "")
return xdmp:set($config, admin:database-add-field-included-element($config, $database, $name, $el))
let $add :=
for $exclude in $excludes
let $el := admin:database-excluded-element("http://marklogic.com/json", $exclude)
return xdmp:set($config, admin:database-add-field-excluded-element($config, $database, $name, $el))
return admin:save-configuration($config)
)
let $setProp := prop:set(concat("index-", $name), concat("field/", $name))
let $config := admin:database-add-field($config, $database, admin:database-field($name, false()))
let $includes := xdmp:get-request-field("include")
let $excludes := xdmp:get-request-field("exclude")
let $add :=
for $include in $includes
let $include := json:escapeNCName($include)
let $el := admin:database-included-element("http://marklogic.com/json", $include, 1, (), "", "")
return xdmp:set($config, admin:database-add-field-included-element($config, $database, $name, $el))
let $add :=
for $exclude in $excludes
let $el := admin:database-excluded-element("http://marklogic.com/json", $exclude)
return xdmp:set($config, admin:database-add-field-excluded-element($config, $database, $name, $el))
return admin:save-configuration($config)
)

else if($requestMethod = "DELETE")
then
if(exists($existing))
then admin:save-configuration(admin:database-delete-field($config, $database, $name))
then (
admin:save-configuration(admin:database-delete-field($config, $database, $name)),
prop:delete(concat("index-", $name))
)
else common:error(404, "Field not found")
else ()
94 changes: 94 additions & 0 deletions data/manage/range.xqy
@@ -0,0 +1,94 @@
(:
Copyright 2011 MarkLogic Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
:)

xquery version "1.0-ml";

import module namespace manage="http://marklogic.com/mljson/manage" at "../lib/manage.xqy";
import module namespace common="http://marklogic.com/mljson/common" at "../lib/common.xqy";
import module namespace json="http://marklogic.com/json" at "../lib/json.xqy";

import module namespace prop="http://xqdev.com/prop" at "../lib/properties.xqy";
import module namespace rest="http://marklogic.com/appservices/rest" at "../lib/rest/rest.xqy";
import module namespace endpoints="http://marklogic.com/mljson/endpoints" at "/config/endpoints.xqy";
import module namespace admin = "http://marklogic.com/xdmp/admin" at "/MarkLogic/admin.xqy";

declare option xdmp:mapping "false";


let $params := rest:process-request(endpoints:request("/data/jsonstore.xqy"))
let $name := map:get($params, "name")
let $requestMethod := xdmp:get-request-method()

let $database := xdmp:database()
let $config := admin:get-configuration()

let $property := prop:get(concat("index-", $name))
let $property :=
if(starts-with($property, concat("range/", $name, "/")))
then $property
else ()

let $bits := tokenize($property, "/")
let $key := xdmp:get-request-field("key", $bits[3])
let $type := xdmp:get-request-field("type", $bits[4])
let $operator := xdmp:get-request-field("operator", $bits[5])
let $xsType := manage:jsonTypeToSchemaType($type)

let $existingIndexes := admin:database-get-range-element-indexes($config, $database)
let $existing :=
for $index in $existingIndexes
where $index/*:scalar-type = $xsType and $index/*:namespace-uri = "http://marklogic.com/json" and $index/*:localname = $key
return $index

return
if($requestMethod = "GET")
then
if(exists($existing))
then json:xmlToJSON(manage:rangeDefinitionToJsonXml($existing, $name, $operator))
else common:error(404, "Range index not found")

else if($requestMethod = ("PUT", "POST"))
then
if(exists(prop:get(concat("index-", $name))))
then common:error(500, concat("An index, field or alias with the name '", $name, "' already exists"))
else (
if(empty($existing))
then
let $colation :=
if($xsType = "string")
then "http://marklogic.com/collation/"
else ""
let $index := admin:database-range-element-index($xsType, "http://marklogic.com/json", $key, $colation, false())
let $config := admin:database-add-range-element-index($config, $database, $index)
return admin:save-configuration($config)
else (),

prop:set(concat("index-", $name), concat("range/", $name, "/", $key, "/", $type, "/", $operator))
)

else if($requestMethod = "DELETE")
then
if(exists($existing))
then
let $propertiesForIndex := manage:getPropertiesAssociatedWithRangeIndex($existing)
let $deleteIndex :=
if(count($propertiesForIndex) = 1)
then admin:save-configuration(admin:database-delete-range-element-index($config, $database, $existing))
else ()
return prop:delete(concat("index-", $name))
else common:error(404, "Range index not found")
else ()

0 comments on commit 98037d7

Please sign in to comment.