This is a distributed DBMS for technological stack Metarhia and it is built with following assumptions:
- GS is designed to be built-in DBMS, to work inside Impress Applications Server; it is needed to avoid or minimize interprocess communication to access DB;
- GS is compatible with JSTP JavaScript Transfer Protocol, all data slould be stored, stansmitted, handled and placed in RAM in the same format;
- All data structures can be reduced to array representation to redice size by removing key names, we can do that with the help of metadata schemas and we can dynamicaly build prototypes from schemas and assign them to arrays, so getters/setters will convert access by name (hash) to assess by position (array);
- Maximum memory usage, read-ahead and lazy-write, minimizing data conversion;
- Using metadata everywhere, special declarative format for subject domein representation including fields, relations, and indices so we can automatically build a storage scheme in the relational database, memory structures and structure for the database, different the GUI, API server, etc.
- The same API for client-side runtime and server-side runtime:
- server-side storage engine;
- client-side storage engine (multiple implementations for different platforms including mobile, desktop and browser);
- sharding for distributed storage of large data amounts, geo-distribution, save backup copies, access load balancing;
- allows user to exchange data in P2P mode;
- Syncronization between client and server in realtime (close to realtime) and in lazy mode; so applications can work in online and offline (with locally stored data); having bidirectional data sync and hieratchical versioning like git have;
- Global data structures unification for applications working with Metarhia technological stack: GlobalStorage, Impress, JSTP and Console through moderated distributed metadata repositories;
- Ability to work with non-unified data structures (custom schemas), specific to certain subject domain;
- GlobalStorage provides DAC (data access layer) abstraction, it substitutes ORM but it does not necessarily make maping on the relational model (though RDBMS are also supported);
- Data structures have global distributed identification system, so data can be inserted anywhere and will not bring ID conflicts;
- Data reliability is provided by distributed storage facilities, so each data structure should have master server and multiple backup and cache servers; using those servers GlobalStorage supports addressing, versioning and branching.
Using this domain specific language we will describe subject domain in declarative format. To build GUI, API, business-loguic, data structures dynamically in runtime. For example we can build JavaScript prototype and assign it to positional array to access fields by name, so arrays will work like objects.
Example:
{
code: { type: 'string', primary: true },
name: {
caption: 'City',
type: 'string',
size: 32,
nullable: false,
index: { unique: false },
master: { dataset: 'Cities', key: 'name' }
},
birth: 'Date',
city: 'string',
addresses: {
type: { array: 'Address' }
},
gender: {
type: 'char',
lookup: { dictionary: { M: 'Male', F: 'Female' } }
},
age: function() {
var difference = new Date() - this.birth;
return Math.floor(difference / 31536000000);
}
}
Data types:
- Built-in JavaScript types: string, number, boolean, Date, etc.
- Global Storage types: id, uid, tree, ip, etc.
- RDBMS data types: char, int, real, text, money, time, date...
- Links to other data structures in GlobalStorage
- Links to other data structures in Application
JSQL is a query language for data structures manipulation. JSQL have syntax for:
filter, projection, dataset join and set operations. We have a separate
repository for examples and specification:
metarhia/JSQL. Current Implementation can
be found in lib/transformations.js
.
See github for full contributors list
Create provider
<Object>
metaschema config
schema
:<Metaschema>
category
:<string>
schema name
Returns: <this>
Attach schema
Returns: <Cursor>
new instance
Copy references to new dataset
Returns: <Cursor>
new instance
Clone all dataset objects
jsql
:<Array>
commands array
Returns: <this>
Apply JSQL commands to dataset
Returns: <this>
Remove all instances from dataset
arr
:<Iterable>
Returns: <Cursor>
new instance
Synchronous virtualization converts Array to Cursor
Returns: <this>
Lazy map
fn - <Function>
, map function
fields
:<string[]>
|<Object>
projection metadata array of field names or object with structure:{ toKey: [ fromKey, functions... ] }
Returns: <this>
Declarative lazy projection
fn
:<Function>
filtering function
Returns: <this>
Lazy functional filter
query
:<Function>
filtering expression
Returns: <Cursor>
new instance
Declarative lazy filter
Returns: <this>
Lazy functional distinct filter
fn
:<Function>
comparing function
Returns: <this>
Lazy functional sort
fields
:<string>
|<string[]>
Returns: <this>
Declarative lazy ascending sort
fields
:<string>
|<string[]>
Returns: <this>
Declarative lazy descending sort
field
:<string>
field to use for count, optional
Returns: <this>
Calculate count
field
:<string>
field to use for sum
Returns: <this>
Calculate sum
field
:<string>
field to use for avg
Returns: <this>
Calculate avg
field
:<string>
field to use for max
Returns: <this>
Calculate max
field
:<string>
field to use for min
Returns: <this>
Calculate min
Returns: <this>
Convert first column of dataset to Array
Returns: <this>
Return first row from dataset
Returns: <this>
Get single first record from dataset
count
:<number>
Returns: <this>
Get first n records from dataset
offset
:<number>
Returns: <this>
Offset into the dataset
cursor
:<Cursor>
Returns: <this>
Calculate union and put results to this Cursor instance
cursor
:<Cursor>
Returns: <this>
Calculate intersection and put results to this Cursor instance
cursor
:<Cursor>
Returns: <this>
Calculate difference and put results to this Cursor instance
cursor
:<Cursor>
Returns: <this>
Calculate complement and put results to this Cursor instance
data
:<Array>
rows to date
Returns: <Promise>
Continue computations via i.e. MemoryCursor or other cursor
to handle remaining operations unsupported by current cursor
permissionChecker
:<Function>
optional- Returns:
<Promise>
Returns: <Promise>
Get results after applying consolidated jsql
Abstract Storage Provider
options
:<Object>
Create StorageProvider
options
:<Object>
schema
:<Metaschema>
Returns: <Promise>
Open StorageProvider
Returns: <Promise>
Close StorageProvider
Returns: <Promise>
Setup StorageProvider
name
:<string>
error name that must be equal to one of the values from the Action's Errors fieldctx
:<Array>
Utility method to generate <ActionError>
from inside the Action
Returns: <Promise>
Generate globally unique id
id
:<string>
globally unique object idpermissionChecker
:<Function>
optional- Returns:
<Promise>
Returns: <Promise>
Get object from GlobalStorage
category
:<string>
category to get details inid
:<string>
object idfieldName
:<string>
field with the Many decoratorpermissionChecker
:<Function>
optional- Returns:
<Promise>
Returns: <Promise>
Get details for many-to-many link from GlobalStorage
obj
:<Object>
to be storedpermissionChecker
:<Function>
optional- Returns:
<Promise>
Returns: <Promise>
Set object in GlobalStorage
category
:<string>
category to store the object inobj
:<Object>
to be storedpermissionChecker
:<Function>
optional- Returns:
<Promise>
Returns: <Promise>
Create object in GlobalStorage
category
:<string>
category to update the records inquery
:<Object>
example:{ Id }
patch
:<Object>
fields to updatepermissionChecker
:<Function>
optional- Returns:
<Promise>
Returns: <Promise>
Update object in GlobalStorage
category
:<string>
category to delete the records fromquery
:<Object>
example:{ Id }
permissionChecker
:<Function>
optional- Returns:
<Promise>
Returns: <Promise>
Delete object in GlobalStorage
category
:<string>
category with field having the Many decoratorfield
:<string>
field with the Many decoratorfromId
:<Uint64>
Id of the record in category specified in the first argumenttoIds
:<Uint64>
|<Uint64[]>
Id(s) of the record(s) in category specified in the Many decorator of the specified fieldpermissionChecker
:<Function>
optional- Returns:
<Promise>
Returns: <Promise>
Link records with Many relation between them
category
:<string>
category with field having the Many decoratorfield
:<string>
field with the Many decoratorfromId
:<Uint64>
Id of the record in category specified in the first argumenttoIds
:<Uint64>
|<Uint64[]>
Id(s) of the record(s) in category specified in the Many decorator of the specified fieldpermissionChecker
:<Function>
optional- Returns:
<Promise>
Returns: <Promise>
Unlink records with Many relation between them
category
:<string>
category to select the records fromquery
:<Object>
fields conditionspermissionChecker
:<Function>
optional- Returns:
<Promise>
Returns: <Cursor>
Select objects from GlobalStorage
category
:<string>
|<null>
category name or null to execute public actionaction
:<string>
action nameactionArgs
:<Object>
permissionChecker
:<Function>
optional- Returns:
<Promise>
Returns: <Promise>
Execute an action
id
:<Uint64>
Returns: <Uint64>
Get system suffix for given id
id
:<Uint64>
Returns: <boolean>
Check whether data with given id is stored on this system
id
:<Uint64>
Returns: <Uint64>
Get server suffix for given id
id
:<Uint64>
Returns: <boolean>
Check whether data with given id is stored on this server
id
:<Uint64>
Returns: <Uint64>
Get id without system and server suffix
id
:<Uint64>
Returns: <Object>
systemSuffix
:<Uint64>
system suffix for given idserverSuffix
:<Uint64>
server suffix for given idlocalId
:<Uint64>
id without system and server suffix
Parse id
filtererByRoles
:<Function>
optionalapplications
:<string[]>
- Returns:
<Promise>
Returns: <Promise>
List all available applications
filtererByPermission
:<Function>
optionalcategories
:<string[]>
- Returns:
<Promise>
Returns: <Promise>
List all available categories
filtererByPermission
:<Function>
optionalactions
:<Object>
- Returns:
<Promise>
Returns: <Promise>
List all available actions
class FsProvider extends StorageProvider
class MemoryProvider extends StorageProvider
class PostgresProvider extends StorageProvider
Create PostgresProvider
options
:<Object>
to be passed to pg
Returns: <Promise>
Open PostgresProvider
Returns: <Promise>
Close PostgresProvider
Returns: <Promise>
Setup StorageProvider
client
:<pg.Pool>
|<pg.Client>
Returns: <Promise>
Generate globally unique id
options
:<Object>
transaction options
Returns: <Promise>
Begin transaction, returns a Promise that resolves in an object containing
some of the methods of the current provider and also the methods commit()
,
rollback()
, and release()
. For more detailed description of the options see
https://www.postgresql.org/docs/current/sql-set-transaction.html
id
:<string>
globally unique object idpermissionChecker
:<Function>
optional- Returns:
<Promise>
Returns: <Promise>
Get object from GlobalStorage
category
:<string>
category to get details inid
:<string>
object idfieldName
:<string>
field with the Many decoratorpermissionChecker
:<Function>
optional- Returns:
<Promise>
Returns: <Promise>
Get details for many-to-many link from GlobalStorage
obj
:<Object>
to be storedpermissionChecker
:<Function>
optional- Returns:
<Promise>
Returns: <Promise>
Set object in GlobalStorage
category
:<string>
category to store the object inobj
:<Object>
to be storedpermissionChecker
:<Function>
optional- Returns:
<Promise>
Returns: <Promise>
Create object in GlobalStorage
category
:<string>
category to update the records inquery
:<Object>
example:{ Id }
patch
:<Object>
fields to updatepermissionChecker
:<Function>
optional- Returns:
<Promise>
Returns: <Promise>
Update object in GlobalStorage
category
:<string>
category to delete the records fromquery
:<Object>
example:{ Id }
permissionChecker
:<Function>
optional- Returns:
<Promise>
Returns: <Promise>
Delete object in GlobalStorage
category
:<string>
category with field having the Many decoratorfield
:<string>
field with the Many decoratorfromId
:<Uint64>
Id of the record in category specified in the first argumenttoIds
:<Uint64>
|<Uint64[]>
Id(s) of the record(s) in category specified in the Many decorator of the specified fieldpermissionChecker
:<Function>
optional- Returns:
<Promise>
Returns: <Promise>
Link records with Many relation between them
category
:<string>
category with field having the Many decoratorfield
:<string>
field with the Many decoratorfromId
:<Uint64>
Id of the record in category specified in the first argumenttoIds
:<Uint64>
|<Uint64[]>
Id(s) of the record(s) in category specified in the Many decorator of the specified fieldpermissionChecker
:<Function>
optional- Returns:
<Promise>
Returns: <Promise>
Unlink records with Many relation between them
Returns: <Cursor>
Select objects from GlobalStorage
class RemoteProvider extends StorageProvider
options
:<Object>
options for jstp connection
Returns: <Promise>
Open RemoteProvider
Returns: <Promise>
Close RemoteProvider
id
:<string>
globally unique record id
Returns: <Promise>
Get record from GlobalStorage
category
:<string>
category to get details inid
:<string>
object idfieldName
:<string>
field with the Many decorator
Returns: <Promise>
Get details for many-to-many link from GlobalStorage
record
:<Object>
record to be stored
Returns: <Promise>
Set record in GlobalStorage
Returns: <Promise>
Create record in GlobalStorage
category
:<string>
category of recordquery
:<Object>
record, example:{ Id }
patch
:<Object>
record, fields to update
Returns: <Promise>
Update record in GlobalStorage
Returns: <Promise>
Delete record in GlobalStorage
category
:<string>
category with field having the Many decoratorfield
:<string>
field with the Many decoratorfromId
:<Uint64>
Id of the record in category specified in the first argumenttoIds
:<Uint64>
|<Uint64[]>
Id(s) of the record(s) in category specified in the Many decorator of the specified field
Returns: <Promise>
Unlink records with Many relation between them
category
:<string>
category with field having the Many decoratorfield
:<string>
field with the Many decoratorfromId
:<Uint64>
Id of the record in category specified in the first argumenttoIds
:<Uint64>
|<Uint64[]>
Id(s) of the record(s) in category specified in the Many decorator of the specified field
Returns: <Promise>
Link records with Many relation between them
Returns: <Cursor>
cursor
Select record from GlobalStorage
category
:<string>
|<null>
category name or null to execute public actionaction
:<string>
action nameactionArgs
:<Object>
Returns: <Promise>
Execute an action
Returns: <Promise>
List categories permission flags