globalstorage
Version:
Global Storage is a Global Distributed Data Warehouse
463 lines (418 loc) • 11.4 kB
JavaScript
'use strict';
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
var _require = require('./errors'),
GSError = _require.GSError,
errorCodes = _require.codes;
var defaultOptions = {
category: null,
schema: null,
provider: null
};
var MemoryCursor = null;
var Cursor =
/*#__PURE__*/
function () {
function Cursor(options) {
_classCallCheck(this, Cursor);
this.dataset = [];
this.children = [];
Object.assign(this, defaultOptions, options);
this.jsql = options && options.jsql ? options.jsql.slice() : [];
this.parents = options && options.parents ? options.parents.slice() : [];
} // Attach schema
// schema - <Metaschema>
// category - <string>, schema name
//
// Returns: <this>
_createClass(Cursor, [{
key: "definition",
value: function definition(schema, category) {
this.schema = schema;
this.category = category;
return this;
}
}, {
key: "enableLogging",
value: function enableLogging(provider, ctx, args) {
return new Proxy(this, {
get: function get(cursor, prop) {
if (prop !== 'fetch') return cursor[prop];
return function (callback) {
for (var _len = arguments.length, rest = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
rest[_key - 1] = arguments[_key];
}
cursor.fetch.apply(cursor, [function (err, result) {
var loggingResult;
if (!err) {
loggingResult = result.length !== 0 && result[0].Id ? result.map(function (r) {
return r.Id;
}) : result.length;
}
provider.log('select', args, ctx, err || loggingResult);
for (var _len2 = arguments.length, rest = new Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
rest[_key2 - 2] = arguments[_key2];
}
callback.apply(void 0, [err, result].concat(rest));
}].concat(rest));
};
}
});
} // Copy references to new dataset
//
// Returns: <Cursor>, new instance
}, {
key: "copy",
value: function copy() {
throw new GSError(errorCodes.NOT_IMPLEMENTED);
} // Clone all dataset objects
//
// Returns: <Cursor>, new instance
}, {
key: "clone",
value: function clone() {
throw new GSError(errorCodes.NOT_IMPLEMENTED);
} // Apply JSQL commands to dataset
// jsql - <Array>, commands array
//
// Returns: <this>
}, {
key: "enroll",
value: function enroll(jsql) {
this.jsql = this.jsql.concat(jsql);
return this;
} // Remove all instances from dataset
//
// Returns: <this>
}, {
key: "empty",
value: function empty() {
throw new GSError(errorCodes.NOT_IMPLEMENTED);
} // Synchronous virtualization converts Array to Cursor
// arr - <Iterable>
//
// Returns: <Cursor>, new instance
// eslint-disable-next-line no-unused-vars
}, {
key: "from",
value: function from(arr) {
throw new GSError(errorCodes.NOT_IMPLEMENTED);
} // Lazy map
// fn - <Function>, map function
//
// Returns: <this>
}, {
key: "map",
value: function map(fn) {
this.jsql.push({
op: 'map',
fn: fn
});
return this;
} // Declarative lazy projection
// fields - <string[]> | <Object>, projection metadata array of
// field names or object with structure:
// { toKey: [ fromKey, functions... ] }
//
// Returns: <this>
}, {
key: "projection",
value: function projection(fields) {
this.jsql.push({
op: 'projection',
fields: fields
});
return this;
} // Lazy functional filter
// fn - <Function>, filtering function
//
// Returns: <this>
}, {
key: "filter",
value: function filter(fn) {
this.jsql.push({
op: 'filter',
fn: fn
});
return this;
} // Declarative lazy filter
// query - <Function>, filtering expression
//
// Returns: <Cursor>, new instance
}, {
key: "select",
value: function select(query) {
this.jsql.push({
op: 'select',
query: query
});
return this;
} // Lazy functional distinct filter
//
// Returns: <this>
}, {
key: "distinct",
value: function distinct() {
this.jsql.push({
op: 'distinct'
});
return this;
} // Lazy functional sort
// fn - <Function>, comparing function
//
// Returns: <this>
}, {
key: "sort",
value: function sort(fn) {
this.jsql.push({
op: 'sort',
fn: fn
});
return this;
} // Declarative lazy ascending sort
// fields - <string> | <string[]>
//
// Returns: <this>
}, {
key: "order",
value: function order(fields) {
if (typeof fields === 'string') fields = [fields];
this.jsql.push({
op: 'order',
fields: fields
});
return this;
} // Declarative lazy descending sort
// fields - <string> | <string[]>
//
// Returns: <this>
}, {
key: "desc",
value: function desc(fields) {
if (typeof fields === 'string') fields = [fields];
this.jsql.push({
op: 'desc',
fields: fields
});
return this;
} // Calculate count
// field - <string>, field to use for count, optional
//
// Returns: <this>
}, {
key: "count",
value: function count(field) {
this.jsql.push({
op: 'count',
field: field
});
return this;
} // Calculate sum
// field - <string>, field to use for sum
//
// Returns: <this>
}, {
key: "sum",
value: function sum(field) {
this.jsql.push({
op: 'sum',
field: field
});
return this;
} // Calculate avg
// field - <string>, field to use for avg
//
// Returns: <this>
}, {
key: "avg",
value: function avg(field) {
this.jsql.push({
op: 'avg',
field: field
});
return this;
} // Calculate max
// field - <string>, field to use for max
//
// Returns: <this>
}, {
key: "max",
value: function max(field) {
this.jsql.push({
op: 'max',
field: field
});
return this;
} // Calculate min
// field - <string>, field to use for min
//
// Returns: <this>
}, {
key: "min",
value: function min(field) {
this.jsql.push({
op: 'min',
field: field
});
return this;
} // Convert first column of dataset to Array
//
// Returns: <this>
}, {
key: "col",
value: function col() {
this.jsql.push({
op: 'col'
});
return this;
} // Return first row from dataset
//
// Returns: <this>
}, {
key: "row",
value: function row() {
this.jsql.push({
op: 'row'
});
return this;
} // Get single first record from dataset
//
// Returns: <this>
}, {
key: "one",
value: function one() {
this.jsql.push({
op: 'limit',
count: 1
});
return this;
} // Get first n records from dataset
// count - <number>
//
// Returns: <this>
}, {
key: "limit",
value: function limit(count) {
this.jsql.push({
op: 'limit',
count: count
});
return this;
} // Offset into the dataset
// offset - <number>
//
// Returns: <this>
}, {
key: "offset",
value: function offset(_offset) {
this.jsql.push({
op: 'offset',
offset: _offset
});
return this;
} // Calculate union and put results to this Cursor instance
// cursor - <Cursor>
//
// Returns: <this>
}, {
key: "union",
value: function union(cursor) {
this.jsql.push({
op: 'union',
cursor: cursor
});
this.parents.push(cursor);
return this;
} // Calculate intersection and put results to this Cursor instance
// cursor - <Cursor>
//
// Returns: <this>
}, {
key: "intersection",
value: function intersection(cursor) {
this.jsql.push({
op: 'intersection',
cursor: cursor
});
this.parents.push(cursor);
return this;
} // Calculate difference and put results to this Cursor instance
// cursor - <Cursor>
//
// Returns: <this>
}, {
key: "difference",
value: function difference(cursor) {
this.jsql.push({
op: 'difference',
cursor: cursor
});
this.parents.push(cursor);
return this;
} // Calculate complement and put results to this Cursor instance
// cursor - <Cursor>
//
// Returns: <this>
}, {
key: "complement",
value: function complement(cursor) {
this.jsql.push({
op: 'complement',
cursor: cursor
});
this.parents.push(cursor);
return this;
}
}, {
key: "selectToMemory",
value: function selectToMemory(query) {
return new Cursor.MemoryCursor([], {
jsql: query ? [{
op: 'select',
query: query
}] : [],
schema: this.schema,
parents: [this]
});
} // Continue computations via i.e. MemoryCursor or other cursor
// to handle remaining operations unsupported by current cursor
// data - <Array>, rows to date
// callback - <Function>, to be called upon completion
// err - <Error> | <null>
// dataset - <Object[]>
// cursor - <MemoryCursor>
}, {
key: "continue",
value: function _continue(data, callback) {
new MemoryCursor(data, {
parents: this.parents,
category: this.category,
schema: this.schema,
jsql: this.jsql
}).fetch(callback);
} // Get results after applying consolidated jsql
// callback - <Function>
// err - <Error> | <null>
// dataset - <Object[]>
// cursor - <MemoryCursor>
// permissionChecker - <Function>, optional
// category - <string>
// options - <Object>
// callback - <Function>
// err - <Error> | <null>
//
// Returns: <this>
// eslint-disable-next-line no-unused-vars
}, {
key: "fetch",
value: function fetch(callback, permissionChecker) {
throw new GSError(errorCodes.NOT_IMPLEMENTED);
}
}]);
return Cursor;
}();
module.exports = {
Cursor: Cursor
};
MemoryCursor = require('./memory.cursor').MemoryCursor;