You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
390 lines
18 KiB
390 lines
18 KiB
/** |
|
* Interface database class that provides all Acedia's functionality for |
|
* querying databases. For most of the cases, this is a class you are expected |
|
* to work with and providing appropriate implementation is Acedia's `DBAPI` |
|
* responsibility. Choice of the implementation is done based on user's |
|
* config files. |
|
* All of the methods are asynchronous - they do not return requested |
|
* values immediately and instead require user to provide a handler function |
|
* that will be called once operation is completed. |
|
* Copyright 2021-2023 Anton Tarasenko |
|
*------------------------------------------------------------------------------ |
|
* This file is part of Acedia. |
|
* |
|
* Acedia is free software: you can redistribute it and/or modify |
|
* it under the terms of the GNU General Public License as published by |
|
* the Free Software Foundation, version 3 of the License, or |
|
* (at your option) any later version. |
|
* |
|
* Acedia is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* GNU General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License |
|
* along with Acedia. If not, see <https://www.gnu.org/licenses/>. |
|
*/ |
|
class Database extends AcediaObject |
|
abstract; |
|
|
|
/** |
|
* Describes possible data types that can be stored in Acedia's databases. |
|
* Lists consists of all possible JSON values types (with self-explanatory |
|
* names) plus technical `JSON_Undefined` type that is used to indicate that |
|
* a particular value does not exist. |
|
*/ |
|
enum DataType |
|
{ |
|
JSON_Undefined, |
|
JSON_Null, |
|
JSON_Boolean, |
|
JSON_Number, |
|
JSON_String, |
|
JSON_Array, |
|
JSON_Object |
|
}; |
|
|
|
/** |
|
* Possible outcomes of any query: success (only `DBR_Success`) or |
|
* some kind of failure (any other value). |
|
* This type is common for all queries, however reasons as to why |
|
* a particular result value was obtained can differ from one to another. |
|
*/ |
|
enum DBQueryResult |
|
{ |
|
// Means query has succeeded; |
|
DBR_Success, |
|
// Query was provided with an invalid JSON pointer |
|
// (`none` or somehow otherwise unfit to be used with a particular query); |
|
DBR_InvalidPointer, |
|
// Operation could not finish because database is damaged and unusable; |
|
DBR_InvalidDatabase, |
|
// Means that data (provided for the query) is somehow invalid. |
|
DBR_InvalidData |
|
}; |
|
|
|
/** |
|
* Schedules reading data, located at the given `pointer` in |
|
* the caller database. |
|
* |
|
* @param pointerToData JSON pointer to the value in database to read. |
|
* `none` is always treated as an invalid JSON pointer. |
|
* @param makeMutable Setting this to `false` (default) will force method |
|
* to load data as immutable Acedia's types and `true` will make it load |
|
* data as mutable types. This setting does not affect `Collection`s into |
|
* which JSON arrays and objects are converted - they are always mutable. |
|
* @param requestID ID of this request. It will be reported when |
|
* database's task is completed. Can be used to correspond database's |
|
* responses with particular requests. |
|
* @return Task object that corresponds to this `ReadData()` call. |
|
* * Guaranteed to be not `none`; |
|
* * Use it to connect a handler for when reading task is complete: |
|
* `ReadData(...).connect = handler`, |
|
* where `handler` must have the following signature: |
|
* ``` |
|
* connect( |
|
* DBQueryResult result, |
|
* take AcediaObject data, |
|
* Database source, |
|
* int requestID)`; |
|
* ``` |
|
* * Ownership of `data` object returned in the `connect()` is considered |
|
* to be transferred to whoever handled result of this query. |
|
* It must be deallocated once no longer needed. |
|
* * `source` provides reference to the database, whose data was |
|
* requested, `requestID` provides the same number as `requestID` |
|
* parameter of this method. |
|
* * Possible `DBQueryResult` types are `DBR_Success`, |
|
* `DBR_InvalidPointer` and `DBR_InvalidDatabase`; |
|
* * `data` is guaranteed to be `none` if `result != DBR_Success`; |
|
* * `DBR_InvalidPointer` can be produced if either `pointer == none` or |
|
* it does not point at any existing value inside the caller database. |
|
*/ |
|
public function DBReadTask ReadData( |
|
BaseJSONPointer pointer, |
|
optional bool makeMutable, |
|
optional int requestID) |
|
{ |
|
return none; |
|
} |
|
|
|
/** |
|
* Schedules writing `data` at the location inside the caller database, |
|
* given by the `pointer`. |
|
* |
|
* Only `HashTable` (that represents JSON object) can be recorded as |
|
* a database's root value (referred to by an empty JSON pointer ""). |
|
* |
|
* @param pointer JSON pointer to the location in the database, where `data` |
|
* should be written (as a JSON value). |
|
* This JSON pointer can make use of "-" index for JSON arrays that allows |
|
* appending data at their end. |
|
* `none` is always treated as an invalid JSON pointer. |
|
* @param data Data that needs to be written at the specified location |
|
* inside the database. For method to succeed this object needs to have |
|
* JSON-compatible type (see `_.json.IsCompatible()` for more details). |
|
* @param requestID ID of this request. It will be reported when |
|
* database's task is completed. Can be used to correspond database's |
|
* responses with particular requests. |
|
* @return Task object that corresponds to this `WriteData()` call. |
|
* * Guaranteed to be not `none`; |
|
* * Use it to connect a handler for when writing task is complete: |
|
* `WriteData(...).connect = handler`, |
|
* where `handler` must have the following signature: |
|
* `connect(DBQueryResult result, Database source, int requestID)`; |
|
* * `source` provides reference to the database, whose data was |
|
* requested, `requestID` provides the same number as `requestID` |
|
* parameter of this method. |
|
* * Possible `DBQueryResult` types are `DBR_Success`, |
|
* `DBR_InvalidPointer`, `DBR_InvalidDatabase` and `DBR_InvalidData`; |
|
* * Data is actually written inside the database iff |
|
* `result == DBR_Success`; |
|
* * `result == DBR_InvalidData` iff either given `data`'s type is not |
|
* JSON-compatible or a non-`HashTable` was attempted to be |
|
* recorded as caller database's root value; |
|
* * `DBR_InvalidPointer` can be produced if either `pointer == none` or |
|
* container of the value `pointer` points at does not exist. |
|
* Example: writing data at "/sub-object/valueA" will always fail if |
|
* "sub-object" does not exist. |
|
*/ |
|
public function DBWriteTask WriteData( |
|
BaseJSONPointer pointer, |
|
AcediaObject data, |
|
optional int requestID) |
|
{ |
|
return none; |
|
} |
|
|
|
/** |
|
* Schedules removing data at the location inside the caller database, |
|
* given by the `pointer`. |
|
* |
|
* "Removing" root object results in simply erasing all of it's stored data. |
|
* |
|
* @param pointer JSON pointer to the location of the data to remove from |
|
* database. `none` is always treated as an invalid JSON pointer. |
|
* @param requestID ID of this request. It will be reported when |
|
* database's task is completed. Can be used to correspond database's |
|
* responses with particular requests. |
|
* @return Task object that corresponds to this `RemoveData()` call. |
|
* * Guaranteed to be not `none`; |
|
* * Use it to connect a handler for when writing task is complete: |
|
* `RemoveData(...).connect = handler`, |
|
* where `handler` must have the following signature: |
|
* `connect(DBQueryResult result, Database source, int requestID)`. |
|
* * `source` provides reference to the database, whose data was |
|
* requested, `requestID` provides the same number as `requestID` |
|
* parameter of this method. |
|
* * Possible `DBQueryResult` types are `DBR_Success`, |
|
* `DBR_InvalidPointer` and `DBR_InvalidDatabase`; |
|
* * Data is actually removed from the database iff |
|
* `result == DBR_Success`. |
|
* * `DBR_InvalidPointer` can be produced if either `pointer == none` or |
|
* it does not point at any existing value inside the caller database. |
|
*/ |
|
public function DBRemoveTask RemoveData( |
|
BaseJSONPointer pointer, |
|
optional int requestID) |
|
{ |
|
return none; |
|
} |
|
|
|
/** |
|
* Schedules checking type of data at the location inside the caller database, |
|
* given by the `pointer`. |
|
* |
|
* @param pointer JSON pointer to the location of the data for which type |
|
* needs to be checked. |
|
* `none` is always treated as an invalid JSON pointer. |
|
* @param requestID ID of this request. It will be reported when |
|
* database's task is completed. Can be used to correspond database's |
|
* responses with particular requests. |
|
* @return Task object that corresponds to this `CheckDataType()` call. |
|
* * Guaranteed to be not `none`; |
|
* * Use it to connect a handler for when reading task is complete: |
|
* `CheckDataType(...).connect = handler`, |
|
* where `handler` must have the following signature: |
|
* ``` |
|
* connect( |
|
* DBQueryResult result, |
|
* Database.DataType type, |
|
* Database source, |
|
* int requestID) |
|
* ``` |
|
* * `source` provides reference to the database, whose data was |
|
* requested, `requestID` provides the same number as `requestID` |
|
* parameter of this method. |
|
* * Possible `DBQueryResult` types are `DBR_Success`, |
|
* `DBR_InvalidPointer` and `DBR_InvalidDatabase`; |
|
* * This task can only fail if either caller database is broken |
|
* (task will produce `DBR_InvalidDatabase` result) or given `pointer` |
|
* is `none` (task will produce `DBR_InvalidPointer` result). |
|
* Otherwise the result will be `DBR_Success`. |
|
* * Data is actually removed from the database iff |
|
* `result == DBR_Success`. |
|
*/ |
|
public function DBCheckTask CheckDataType( |
|
BaseJSONPointer pointer, |
|
optional int requestID) |
|
{ |
|
return none; |
|
} |
|
|
|
/** |
|
* Schedules obtaining "size": amount of elements stored inside |
|
* either JSON object or JSON array, which location inside the caller database |
|
* is given by provided `pointer`. |
|
* |
|
* For every JSON value that is neither object or array size is |
|
* defined as `-1`. |
|
* |
|
* @param pointer JSON pointer to the location of the JSON object or array |
|
* for which size needs to be obtained. |
|
* `none` is always treated as an invalid JSON pointer. |
|
* @param requestID ID of this request. It will be reported when |
|
* database's task is completed. Can be used to correspond database's |
|
* responses with particular requests. |
|
* @return Task object that corresponds to this `GetDataSize()` call. |
|
* * Guaranteed to be not `none`; |
|
* * Use it to connect a handler for when reading task is complete: |
|
* `GetDataSize(...).connect = handler`, |
|
* where `handler` must have the following signature: |
|
* ``` |
|
* connect( |
|
* DBQueryResult result, |
|
* int size, |
|
* Database source, |
|
* int requestID) |
|
* ``` |
|
* * `source` provides reference to the database, whose data was |
|
* requested, `requestID` provides the same number as `requestID` |
|
* parameter of this method. |
|
* * Possible `DBQueryResult` types are `DBR_Success`, |
|
* `DBR_InvalidPointer` and `DBR_InvalidDatabase`; |
|
* * Returned `size` value is actually a size of referred |
|
* JSON object/array inside the database iff `result == DBR_Success`; |
|
* * `DBR_InvalidPointer` can be produced if either `pointer == none` or |
|
* it does not point at a JSON object or array inside the |
|
* caller database. |
|
*/ |
|
public function DBSizeTask GetDataSize( |
|
BaseJSONPointer pointer, |
|
optional int requestID) |
|
{ |
|
return none; |
|
} |
|
|
|
/** |
|
* Schedules obtaining set of keys inside the JSON object, which location in |
|
* the caller database is given by provided `pointer`. |
|
* |
|
* Only JSON objects have (and will return) keys (names of their sub-values). |
|
* |
|
* @param pointer JSON pointer to the location of the JSON object for which |
|
* keys need to be obtained. |
|
* `none` is always treated as an invalid JSON pointer. |
|
* @param requestID ID of this request. It will be reported when |
|
* database's task is completed. Can be used to correspond database's |
|
* responses with particular requests. |
|
* @return Task object that corresponds to this `GetDataKeys()` call. |
|
* * Guaranteed to be not `none`; |
|
* * Use it to connect a handler for when reading task is complete: |
|
* `GetDataKeys(...).connect = handler`, |
|
* where `handler` must have the following signature: |
|
* ``` |
|
* connect( |
|
* DBQueryResult result, |
|
* take ArrayList keys, |
|
* Database source, |
|
* int requestID) |
|
* ``` |
|
* * Ownership of `keys` array returned in the `connect()` is considered |
|
* to be transferred to whoever handled result of this query. |
|
* It must be deallocated once no longer needed. |
|
* * `source` provides reference to the database, whose data was |
|
* requested, `requestID` provides the same number as `requestID` |
|
* parameter of this method. |
|
* * Possible `DBQueryResult` types are `DBR_Success`, |
|
* `DBR_InvalidPointer`, `DBR_InvalidData` and `DBR_InvalidDatabase`; |
|
* * Returned `keys` will be non-`none` and contain keys of the referred |
|
* JSON object inside the database iff `result == DBR_Success`; |
|
* * `DBR_InvalidPointer` can be produced iff `pointer == none`; |
|
* * `result == DBR_InvalidData` iff `pointer != none`, but does not |
|
* point at a JSON object inside caller database |
|
* (value can either not exist at all or have some other type). |
|
*/ |
|
public function DBKeysTask GetDataKeys( |
|
BaseJSONPointer pointer, |
|
optional int requestID) |
|
{ |
|
return none; |
|
} |
|
|
|
/** |
|
* Schedules "incrementing" data, located at the given `pointer` in |
|
* the caller database. |
|
* |
|
* "Incrementing" is an operation that is safe from the point of view of |
|
* simultaneous access. What "incrementing" actually does depends on |
|
* the passed JSON value (`increment` parameter): |
|
* |
|
* (0. ...unless `pointer` points at the JSON null or missing value (within |
|
* existing container - then "increment" acts as a `WriteData()` method |
|
* regardless of `increment`'s value;) |
|
* 1. JSON null: it never modifies existing value and reports an error if |
|
* existing value was not itself JSON null; |
|
* 2. JSON bool: if combined with stored JSON bool value - |
|
* performs logical "or" operation. Otherwise fails; |
|
* 3. JSON number: if combined with stored JSON numeric value - |
|
* adds values together. Otherwise fails. |
|
* 4. JSON string: if combined with stored JSON string value - |
|
* concatenates itself at the end. Otherwise fails. |
|
* 5. JSON array: if combined with stored JSON array value - |
|
* concatenates itself at the end. Otherwise fails. |
|
* 6. JSON object: if combined with stored JSON object value - |
|
* `increment` adds it's own values with new keys into the stored |
|
* JSON object. Does not override old values. |
|
* Fails when combined with any other type. |
|
* |
|
* @param pointer JSON pointer to the location in the database, where |
|
* data should be incremented (by `increment`). |
|
* `none` is always treated as an invalid JSON pointer. |
|
* This JSON pointer can make use of "-" index for JSON arrays that allows |
|
* to add `none` value at the end of that array and then "increment" it |
|
* with `increment` parameter. |
|
* @param increment JSON-compatible value to be used as an increment for |
|
* the data at the specified location inside the database. |
|
* @param requestID ID of this request. It will be reported when |
|
* database's task is completed. Can be used to correspond database's |
|
* responses with particular requests. |
|
* @return Task object that corresponds to this `IncrementData()` call. |
|
* * Guaranteed to be not `none`; |
|
* * Use it to connect a handler for when reading task is complete: |
|
* `IncrementData(...).connect = handler`, |
|
* where `handler` must have the following signature: |
|
* `connect(DBQueryResult result, Database source, int requestID)`. |
|
* * `source` provides reference to the database, whose data was |
|
* requested, `requestID` provides the same number as `requestID` |
|
* parameter of this method. |
|
* * Possible `DBQueryResult` types are `DBR_Success`, |
|
* `DBR_InvalidPointer`, `DBR_InvalidData` and `DBR_InvalidDatabase`; |
|
* * Data is actually incremented iff `result == DBR_Success`; |
|
* * `DBR_InvalidPointer` can be produced if either `pointer == none` or |
|
* container of the value `pointer` points at does not exist. |
|
* Example: incrementing data at "/sub-object/valueA" will always fail |
|
* if "sub-object" does not exist. |
|
* * `result == DBR_InvalidData` iff `pointer != none`, but does not |
|
* point at a JSON value compatible (in the sense of "increment" |
|
* operation) with `increment` parameter. |
|
*/ |
|
public function DBIncrementTask IncrementData( |
|
BaseJSONPointer pointer, |
|
AcediaObject increment, |
|
optional int requestID) |
|
{ |
|
return none; |
|
} |
|
|
|
defaultproperties |
|
{ |
|
} |