Skip to content

Commit

Permalink
wip groupBy
Browse files Browse the repository at this point in the history
  • Loading branch information
lroal committed May 9, 2024
1 parent 6c0cc43 commit 6e1e433
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 33 deletions.
13 changes: 12 additions & 1 deletion src/hostExpress/executePath.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ let _allowedOps = {

async function executePath({ table, JSONFilter, baseFilter, customFilters = {}, request, response, readonly, disableBulkDeletes, isHttp, client }) {
let allowedOps = { ..._allowedOps, insert: !readonly, ...extractRelations(getMeta(table)) };
let ops = { ..._ops, ...getCustomFilterPaths(customFilters), getManyDto, getMany, count, delete: _delete, cascadeDelete };
let ops = { ..._ops, ...getCustomFilterPaths(customFilters), getManyDto, getMany, groupBy, count, delete: _delete, cascadeDelete };
let res = await parseFilter(JSONFilter, table);
if (res === undefined)
return {};
Expand Down Expand Up @@ -267,6 +267,17 @@ async function executePath({ table, JSONFilter, baseFilter, customFilters = {},
return table.getManyDto.apply(null, args);
}

async function groupBy(filter, strategy) {
validateStrategy(table, strategy);
filter = negotiateFilter(filter);
const _baseFilter = await invokeBaseFilter();
if (_baseFilter)
filter = filter.and(_baseFilter);
let args = [filter].concat(Array.prototype.slice.call(arguments).slice(1));
await negotiateWhereAndAggregate(strategy);
return table.groupBy.apply(null, args);
}

async function negotiateWhereAndAggregate(strategy) {
if (typeof strategy !== 'object')
return;
Expand Down
56 changes: 31 additions & 25 deletions src/table.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
var newColumn = require('./table/column/newColumn');
var column = require('./table/column');
var join = require('./table/join');
var hasMany = require('./table/hasMany');
var hasOne = require('./table/hasOne');
var getMany = require('./table/getMany');
var count = require('./table/count');
var getManyDto = require('./table/getManyDto');
var getById = require('./table/getById');
var tryGetById = require('./table/tryGetById');
var tryGetFirst = require('./table/tryGetFirstFromDb');
var newCache = require('./table/newRowCache');
var newContext = require('./newObject');
var insert = require('./table/insert');
var _delete = require('./table/delete');
var cascadeDelete = require('./table/cascadeDelete');
var createReadStream = require('./table/createReadStream');
var createJSONReadStream = require('./table/createJSONReadStream');
var getIdArgs = require('./table/getIdArgs');
var patchTable = require('./patchTable');
var newEmitEvent = require('./emitEvent');
var hostLocal = require('./hostLocal');
var getTSDefinition = require('./getTSDefinition');
var where = require('./table/where');
var aggregate = require('./table/aggregate');
const newColumn = require('./table/column/newColumn');
const column = require('./table/column');
const join = require('./table/join');
const hasMany = require('./table/hasMany');
const hasOne = require('./table/hasOne');
const getMany = require('./table/getMany');
const count = require('./table/count');
const getManyDto = require('./table/getManyDto');
const getById = require('./table/getById');
const tryGetById = require('./table/tryGetById');
const tryGetFirst = require('./table/tryGetFirstFromDb');
const newCache = require('./table/newRowCache');
const newContext = require('./newObject');
const insert = require('./table/insert');
const _delete = require('./table/delete');
const cascadeDelete = require('./table/cascadeDelete');
const createReadStream = require('./table/createReadStream');
const createJSONReadStream = require('./table/createJSONReadStream');
const getIdArgs = require('./table/getIdArgs');
const patchTable = require('./patchTable');
const newEmitEvent = require('./emitEvent');
const hostLocal = require('./hostLocal');
const getTSDefinition = require('./getTSDefinition');
const where = require('./table/where');
const aggregate = require('./table/aggregate');
const groupBy = require('./table/groupBy');


function _new(tableName) {
var table = newContext();
Expand Down Expand Up @@ -71,6 +73,10 @@ function _new(tableName) {
return Promise.resolve().then(() => getManyDto(table, filter, strategy));
};

table.getManyDto = function(filter, strategy) {
return groupBy(table, filter, strategy);
};

table.getMany.exclusive = function(filter, strategy) {
return Promise.resolve().then(() => getMany.exclusive(table, filter, strategy));
};
Expand Down
65 changes: 65 additions & 0 deletions src/table/groupBy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
const newQuery = require('./groupBy/newQuery');
const negotiateRawSqlFilter = require('./column/negotiateRawSqlFilter');
const strategyToSpan = require('./strategyToSpan');
const executeQueries = require('./executeQueries');

async function groupBy(table, filter, strategy) {
filter = negotiateRawSqlFilter(filter, table);
if (strategy && strategy.where) {
let arg = typeof strategy.where === 'function' ? strategy.where(table) : strategy.where;
filter = filter.and(arg);
}

let span = strategyToSpan(table, strategy, { skipPrimary: true });
let alias = table._dbName;

const query = newQuery(table, filter, span, alias);
const res = await executeQueries([query]);
return decode(strategy, span, await res[0]);
}

function newCreateRow(span) {
let columnsMap = span.columns;
const columns = span.table._columns.filter(column => !columnsMap || columnsMap.get(column));
const protoRow = createProto(columns, span);

return createRow;

function createRow() {
return Object.create(protoRow);
}
}

function createProto(span) {
let obj = {};
for (let key in span.aggregates) {
obj[key] = null;
}

return obj;
}


async function decode(strategy, span, rows, keys = rows.length > 0 ? Object.keys(rows[0]) : []) {
const rowsLength = rows.length;
const aggregateKeys = Object.keys(span.aggregates);

const outRows = new Array(rowsLength);
const createRow = newCreateRow(span);
for (let i = 0; i < rowsLength; i++) {
const row = rows[i];
let outRow = createRow();

for (let j = 0; j < aggregateKeys.length; j++) {
const key = aggregateKeys[j];
const parse = span.aggregates[key].column?.decode || Number.parseFloat;
outRow[key] = parse(row[keys[j]]);
}

outRows[i] = outRow;
}

return outRows;
}

module.exports = groupBy;
16 changes: 16 additions & 0 deletions src/table/groupBy/newQuery.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const newQueryCore = require('../../getManyDto/newQuery');

function newQuery(_table,_filter,span,_alias) {
const query = newQueryCore.apply(null, arguments);
const groupClause = groupBy(span);
return newParameterized(query.sql(), query.parameters).append(groupClause);
}

function groupBy(span) {
const keys = Object.keys(span.aggregates);
if (keys.length === 0)
return '';
return ' ' + keys.join(',');
}

module.exports = newQuery;
11 changes: 6 additions & 5 deletions src/table/purifyStrategy.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function purifyStrategy(table, strategy, columns = new Map()) {
function purifyStrategy(table, strategy, {skipPrimary, columns = new Map()} = {}) {
strategy = { ...strategy };
for (let p in strategy) {
if (strategy[p] === null)
Expand All @@ -20,9 +20,10 @@ function purifyStrategy(table, strategy, columns = new Map()) {
let column = table._columns[i];
strategy[column.alias] = !hasIncludedColumns;
}
table._primaryColumns.forEach(column => {
strategy[column.alias] = true;
});
if (!skipPrimary)
table._primaryColumns.forEach(column => {
strategy[column.alias] = true;
});
columns.forEach((value, key) => strategy[key.alias] = value);

return strategy;
Expand All @@ -41,7 +42,7 @@ function addLeg(relation, strategy, columns) {
});
}
let childTable = relation.childTable;
return purifyStrategy(childTable, strategy, nextColumns);
return purifyStrategy(childTable, strategy, {columns: nextColumns});
}

module.exports = purifyStrategy;
4 changes: 2 additions & 2 deletions src/table/strategyToSpan.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ var newCollection = require('../newCollection');
var newQueryContext = require('./query/singleQuery/newQueryContext');
var purifyStrategy = require('./purifyStrategy');

function toSpan(table,strategy) {
function toSpan(table, strategy, options) {
var span = {};
span.aggregates = {};
span.legs = newCollection();
span.table = table;
strategy = purifyStrategy(table, strategy);
strategy = purifyStrategy(table, strategy, options);
applyStrategy(table,span,strategy);
span.queryContext = newQueryContext();
span.queryContext.strategy = strategy;
Expand Down

0 comments on commit 6e1e433

Please sign in to comment.