Difference between revisions of "Store Module"
(Created page with "This XQuery Module provides functions to organize values in a main-memory cache. Caching is advisable if data (a system configuration, maps serving as inde...") |
m (Text replacement - "</syntaxhighlight>" to "</pre>") |
||
(19 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
− | This [[Module Library|XQuery Module]] provides functions to organize values in a main-memory | + | This [[Module Library|XQuery Module]] provides functions to organize values in a persistent main-memory key-value store. |
− | + | The store is useful if data (a system configuration, maps serving as indexes) needs to be repeatedly accessed. The store is persistent: Contents will be written to disk at shutdown time, and the serialized store will be retrieved from disk as soon as the store is used for the first time. The store will be stored in a binary {{Code|store.basex}} file in the database directory. | |
− | In addition, custom | + | In addition, custom stores can be read and written. Custom stores have filenames with the pattern {{Code|store-NAME.basex}}. The implicit write of the standard store at shutdown time will be disabled if a custom store is used. |
− | Functions of this module are | + | Functions of this module are nondeterministic and side-effecting: Updates will immediately be visible, and a repeated call of the same function may yield different results if the contents of the store have changed. |
=Conventions= | =Conventions= | ||
− | All functions and errors in this module are assigned to the <code><nowiki>http://basex.org/modules/ | + | All functions and errors in this module are assigned to the <code><nowiki>http://basex.org/modules/store</nowiki></code> namespace, which is statically bound to the {{Code|store}} prefix.<br/> |
− | = | + | =Key-value operations= |
− | == | + | ==store:get== |
{| width='100%' | {| width='100%' | ||
− | |- | + | |- valign="top" |
− | | width='120' | ''' | + | | width='120' | '''Signature''' |
− | | | + | |<pre>store:get( |
− | |- | + | $key as xs:string |
+ | ) as item()*</pre> | ||
+ | |- valign="top" | ||
|'''Summary''' | |'''Summary''' | ||
− | |Retrieves an entry from the | + | |Retrieves an entry from the store with the given {{Code|$key}}. If the addressed entry does not exist, an empty sequence is returned. |
|} | |} | ||
− | == | + | ==store:put== |
{| width='100%' | {| width='100%' | ||
− | |- | + | |- valign="top" |
− | | width='120' | ''' | + | | width='120' | '''Signature''' |
− | | | + | |<pre>store:put( |
− | |- | + | $key as xs:string, |
+ | $value as item()* | ||
+ | ) as empty-sequence()</pre> | ||
+ | |- valign="top" | ||
|'''Summary''' | |'''Summary''' | ||
− | |Stores an entry with the given {{Code|$key}} and {{Code|$value}} in the | + | |Stores an entry with the given {{Code|$key}} and {{Code|$value}} in the store: |
* If the value is an empty sequence, the entry is removed. | * If the value is an empty sequence, the entry is removed. | ||
* If a value refers to an opened database or is [[Lazy Module|a lazy item]], its contents are materialized in main memory. | * If a value refers to an opened database or is [[Lazy Module|a lazy item]], its contents are materialized in main memory. | ||
Line 38: | Line 43: | ||
|} | |} | ||
− | == | + | ==store:get-or-put== |
{| width='100%' | {| width='100%' | ||
− | |- | + | |- valign="top" |
− | | width='120' | ''' | + | | width='120' | '''Signature''' |
− | | | + | |<pre>store:get-or-put( |
− | |- | + | $key as xs:string, |
+ | $put as function(*) | ||
+ | ) as item()*</pre> | ||
+ | |- valign="top" | ||
|'''Summary''' | |'''Summary''' | ||
− | |Retrieves an entry from the | + | |Retrieves an entry from the store with the given {{Code|$key}}. The {{Code|$put}} function will only be invoked if the entry does not exist, and its result will be stored and returned instead. |
|} | |} | ||
− | == | + | ==store:remove== |
{| width='100%' | {| width='100%' | ||
− | |- | + | |- valign="top" |
− | | width='120' | ''' | + | | width='120' | '''Signature''' |
− | | | + | |<pre>store:remove( |
− | |- | + | $key as xs:string |
+ | ) as empty-sequence()</pre> | ||
+ | |- valign="top" | ||
|'''Summary''' | |'''Summary''' | ||
− | |Removes an entry with the given {{Code|$key}} from the | + | |Removes an entry with the given {{Code|$key}} from the store. No error will be raised if an addressed entry does not exist. |
|} | |} | ||
− | == | + | ==store:keys== |
{| width='100%' | {| width='100%' | ||
− | |- | + | |- valign="top" |
− | | width='120' | ''' | + | | width='120' | '''Signature''' |
− | | | + | |<pre>store:keys() as xs:string*</pre> |
− | |- | + | |- valign="top" |
|'''Summary''' | |'''Summary''' | ||
|Lists the names of all keys. | |Lists the names of all keys. | ||
|} | |} | ||
− | == | + | ==store:clear== |
{| width='100%' | {| width='100%' | ||
− | |- | + | |- valign="top" |
− | | width='120' | ''' | + | | width='120' | '''Signature''' |
− | | | + | |<pre>store:clear() as empty-sequence()</pre> |
− | |- | + | |- valign="top" |
|'''Summary''' | |'''Summary''' | ||
− | |Resets the | + | |Resets the store by removing all its entries. |
|} | |} | ||
− | = | + | =Store Operations= |
− | == | + | ==store:read== |
{| width='100%' | {| width='100%' | ||
− | |- | + | |- valign="top" |
− | | width='120' | ''' | + | | width='120' | '''Signature''' |
− | | | + | |<pre>store:read( |
− | |- | + | $name as xs:string? := () |
+ | ) as empty-sequence()</pre> | ||
+ | |- valign="top" | ||
|'''Summary''' | |'''Summary''' | ||
− | |Retrieves the standard | + | |Retrieves the standard store from disk, or a custom store if a {{Code|$name}} is supplied. |
− | |- | + | |- valign="top" |
|'''Errors''' | |'''Errors''' | ||
− | |{{Error|io|#Errors}} The | + | |{{Error|io|#Errors}} The store could not be read.<br/>{{Error|name|#Errors}} The specified name is invalid.<br/>{{Error|not-found|#Errors}} A store with the specified name does not exist. |
|} | |} | ||
− | == | + | ==store:write== |
{| width='100%' | {| width='100%' | ||
− | |- | + | |- valign="top" |
− | | width='120' | ''' | + | | width='120' | '''Signature''' |
− | | | + | |<pre>store:write( |
− | |- | + | $name as xs:string? := () |
+ | ) as empty-sequence()</pre> | ||
+ | |- valign="top" | ||
|'''Summary''' | |'''Summary''' | ||
− | |Writes the standard | + | |Writes the standard store to disk, or to a custom store file if a {{Code|$name}} is supplied. If the standard store is empty, the store file will be deleted. |
− | |- | + | |- valign="top" |
|'''Errors''' | |'''Errors''' | ||
− | |{{Error|io|#Errors}} The | + | |{{Error|io|#Errors}} The store could not be written.<br/>{{Error|name|#Errors}} The specified name is invalid. |
|} | |} | ||
− | == | + | ==store:list== |
{| width='100%' | {| width='100%' | ||
− | |- | + | |- valign="top" |
− | | width='120' | ''' | + | | width='120' | '''Signature''' |
− | | | + | |<pre>store:list() as xs:string*</pre> |
− | |- | + | |- valign="top" |
|'''Summary''' | |'''Summary''' | ||
− | |Lists the names of all custom | + | |Lists the names of all custom stores. |
|} | |} | ||
− | == | + | ==store:delete== |
{| width='100%' | {| width='100%' | ||
− | |- | + | |- valign="top" |
− | | width='120' | ''' | + | | width='120' | '''Signature''' |
− | | | + | |<pre>store:delete( |
− | |- | + | $name as xs:string |
+ | ) as empty-sequence()</pre> | ||
+ | |- valign="top" | ||
|'''Summary''' | |'''Summary''' | ||
− | |Deletes a custom | + | |Deletes a custom store from disk. |
− | |- | + | |- valign="top" |
|'''Errors''' | |'''Errors''' | ||
− | |{{Error|name|#Errors}} The specified name is invalid.<br/>{{Error|not-found|#Errors}} A | + | |{{Error|name|#Errors}} The specified name is invalid.<br/>{{Error|not-found|#Errors}} A store with the specified name does not exist. |
|} | |} | ||
Line 141: | Line 157: | ||
'''Use Case 1: Create/update a system configuration in a running BaseX server instance: | '''Use Case 1: Create/update a system configuration in a running BaseX server instance: | ||
− | < | + | <pre lang='xquery'> |
(: store an integer :) | (: store an integer :) | ||
− | + | store:put('version', 1), | |
(: retrieve existing or new value, store an element :) | (: retrieve existing or new value, store an element :) | ||
− | let $license := | + | let $license := store:get-or-put('license', function() { 'free' }) |
− | return | + | return store:put('info', <info>{ $license = 'free' ?? 'Free' !! 'Professional' } License</info>), |
(: store a map :) | (: store a map :) | ||
− | + | store:put('data', map { 'year': 2022 }), | |
(: serialize configuration to disk :) | (: serialize configuration to disk :) | ||
− | + | store:write() | |
− | </ | + | </pre> |
The configuration can be requested by further operations, e.g. a client request: | The configuration can be requested by further operations, e.g. a client request: | ||
− | < | + | <pre lang='xquery'> |
− | + | store:get('version') | |
− | </ | + | </pre> |
− | The | + | The store will still be available if BaseX is restarted until it is cleared. |
'''Use Case 2: Create index for fast lookup operations in the GUI: | '''Use Case 2: Create index for fast lookup operations in the GUI: | ||
− | < | + | <pre lang='xquery'> |
let $map := map:merge( | let $map := map:merge( | ||
− | for $country in db: | + | for $country in db:get('factbook')//country |
for $religion in $country//religions | for $religion in $country//religions | ||
group by $religion | group by $religion | ||
return map:entry($religion, data($country/@name)) | return map:entry($religion, data($country/@name)) | ||
) | ) | ||
− | return | + | return store:put('religions', $map) |
− | </ | + | </pre> |
A subsequent query can be used to access its contents: | A subsequent query can be used to access its contents: | ||
− | < | + | <pre lang='xquery'> |
− | + | store:get('religions')?Buddhism | |
− | </ | + | </pre> |
− | Note that the | + | Note that the store will eventually be written to disk unless it is invalidated before closing the GUI. |
=Errors= | =Errors= | ||
Line 186: | Line 202: | ||
! width="110"|Code | ! width="110"|Code | ||
|Description | |Description | ||
− | |- | + | |- valign="top" |
|{{Code|io}} | |{{Code|io}} | ||
− | | The | + | | The store could not be read or written. |
− | |- | + | |- valign="top" |
|{{Code|name}} | |{{Code|name}} | ||
| The specified name is invalid. | | The specified name is invalid. | ||
− | |- | + | |- valign="top" |
|{{Code|not-found}} | |{{Code|not-found}} | ||
− | | A | + | | A store with the specified name does not exist. |
|} | |} | ||
Latest revision as of 18:37, 1 December 2023
This XQuery Module provides functions to organize values in a persistent main-memory key-value store.
The store is useful if data (a system configuration, maps serving as indexes) needs to be repeatedly accessed. The store is persistent: Contents will be written to disk at shutdown time, and the serialized store will be retrieved from disk as soon as the store is used for the first time. The store will be stored in a binary store.basex
file in the database directory.
In addition, custom stores can be read and written. Custom stores have filenames with the pattern store-NAME.basex
. The implicit write of the standard store at shutdown time will be disabled if a custom store is used.
Functions of this module are nondeterministic and side-effecting: Updates will immediately be visible, and a repeated call of the same function may yield different results if the contents of the store have changed.
Contents
Conventions[edit]
All functions and errors in this module are assigned to the http://basex.org/modules/store
namespace, which is statically bound to the store
prefix.
Key-value operations[edit]
store:get[edit]
Signature | store:get( $key as xs:string ) as item()* |
Summary | Retrieves an entry from the store with the given $key . If the addressed entry does not exist, an empty sequence is returned.
|
store:put[edit]
Signature | store:put( $key as xs:string, $value as item()* ) as empty-sequence() |
Summary | Stores an entry with the given $key and $value in the store:
|
store:get-or-put[edit]
Signature | store:get-or-put( $key as xs:string, $put as function(*) ) as item()* |
Summary | Retrieves an entry from the store with the given $key . The $put function will only be invoked if the entry does not exist, and its result will be stored and returned instead.
|
store:remove[edit]
Signature | store:remove( $key as xs:string ) as empty-sequence() |
Summary | Removes an entry with the given $key from the store. No error will be raised if an addressed entry does not exist.
|
store:keys[edit]
Signature | store:keys() as xs:string* |
Summary | Lists the names of all keys. |
store:clear[edit]
Signature | store:clear() as empty-sequence() |
Summary | Resets the store by removing all its entries. |
Store Operations[edit]
store:read[edit]
Signature | store:read( $name as xs:string? := () ) as empty-sequence() |
Summary | Retrieves the standard store from disk, or a custom store if a $name is supplied.
|
Errors | io : The store could not be read.name : The specified name is invalid.not-found : A store with the specified name does not exist.
|
store:write[edit]
Signature | store:write( $name as xs:string? := () ) as empty-sequence() |
Summary | Writes the standard store to disk, or to a custom store file if a $name is supplied. If the standard store is empty, the store file will be deleted.
|
Errors | io : The store could not be written.name : The specified name is invalid.
|
store:list[edit]
Signature | store:list() as xs:string* |
Summary | Lists the names of all custom stores. |
store:delete[edit]
Signature | store:delete( $name as xs:string ) as empty-sequence() |
Summary | Deletes a custom store from disk. |
Errors | name : The specified name is invalid.not-found : A store with the specified name does not exist.
|
Examples[edit]
Use Case 1: Create/update a system configuration in a running BaseX server instance:
(: store an integer :)
store:put('version', 1),
(: retrieve existing or new value, store an element :)
let $license := store:get-or-put('license', function() { 'free' })
return store:put('info', <info>{ $license = 'free' ?? 'Free' !! 'Professional' } License</info>),
(: store a map :)
store:put('data', map { 'year': 2022 }),
(: serialize configuration to disk :)
store:write()
The configuration can be requested by further operations, e.g. a client request:
store:get('version')
The store will still be available if BaseX is restarted until it is cleared.
Use Case 2: Create index for fast lookup operations in the GUI:
let $map := map:merge(
for $country in db:get('factbook')//country
for $religion in $country//religions
group by $religion
return map:entry($religion, data($country/@name))
)
return store:put('religions', $map)
A subsequent query can be used to access its contents:
store:get('religions')?Buddhism
Note that the store will eventually be written to disk unless it is invalidated before closing the GUI.
Errors[edit]
Code | Description |
---|---|
io
|
The store could not be read or written. |
name
|
The specified name is invalid. |
not-found
|
A store with the specified name does not exist. |
Changelog[edit]
The module was introduced with Version 10.