Skip to content

Commit

Permalink
update / updateChanges
Browse files Browse the repository at this point in the history
  • Loading branch information
Lars-Erik Roald committed Dec 20, 2023
1 parent f566ed2 commit e95e292
Show file tree
Hide file tree
Showing 29 changed files with 866 additions and 77 deletions.
2 changes: 1 addition & 1 deletion .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# FROM node:18-alpine
FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-16-bullseye
FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-20-bullseye


# [Optional] Uncomment this section to install additional OS packages.
Expand Down
2 changes: 1 addition & 1 deletion .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ services:
- SA_PASSWORD=P@assword123
ports:
- 14330:1433
restart: always
#restart: always
mysql:
image: mysql:8.0.31
environment:
Expand Down
37 changes: 37 additions & 0 deletions src/client/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ function rdbClient(options = {}) {
getOne,
getById,
proxify,
update,
updateChanges,
insert,
insertAndForget,
delete: _delete,
Expand Down Expand Up @@ -292,6 +294,41 @@ function rdbClient(options = {}) {
return adapter.post(body);
}

async function update(rows, ...rest) {
const concurrency = undefined;
const args = [concurrency].concat(rest);
if (Array.isArray(rows)) {
const proxy = await getMany.apply(null, [rows, ...rest]);
proxy.splice.apply(proxy, [0, proxy.length, ...rows]);
await proxy.saveChanges.apply(proxy, args);
return proxy;
}
else {
const proxy = await getMany.apply(null, [[rows], ...rest]);
proxy.splice.apply(proxy, [0, 1, rows]);
await proxy.saveChanges.apply(proxy, args);
return proxify(proxy[0], args[0]);
}
}

async function updateChanges(rows, oldRows, ...rest) {
const concurrency = undefined;
const args = [concurrency].concat(rest);
if (Array.isArray(rows)) {
//todo
const proxy = await getMany.apply(null, [rows, ...rest]);
proxy.splice.apply(proxy, [0, proxy.length, ...rows]);
await proxy.saveChanges.apply(proxy, args);
return proxy;
}
else {
let proxy = proxify([oldRows], args[0]);
proxy.splice.apply(proxy, [0, 1, rows]);
await proxy.saveChanges.apply(proxy, args);
return proxify(proxy[0], args[0]);
}
}

async function insert(rows, ...rest) {
const concurrency = undefined;
const args = [concurrency].concat(rest);
Expand Down
37 changes: 37 additions & 0 deletions src/client/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5481,6 +5481,8 @@ function rdbClient(options = {}) {
getOne,
getById,
proxify,
update,
updateChanges,
insert,
insertAndForget,
delete: _delete,
Expand Down Expand Up @@ -5586,6 +5588,41 @@ function rdbClient(options = {}) {
return adapter.post(body);
}

async function update(rows, ...rest) {
const concurrency = undefined;
const args = [concurrency].concat(rest);
if (Array.isArray(rows)) {
const proxy = await getMany.apply(null, [rows, ...rest]);
proxy.splice.apply(proxy, [0, proxy.length, ...rows]);
await proxy.saveChanges.apply(proxy, args);
return proxy;
}
else {
const proxy = await getMany.apply(null, [[rows], ...rest]);
proxy.splice.apply(proxy, [0, 1, rows]);
await proxy.saveChanges.apply(proxy, args);
return proxify(proxy[0], args[0]);
}
}

async function updateChanges(rows, oldRows, ...rest) {
const concurrency = undefined;
const args = [concurrency].concat(rest);
if (Array.isArray(rows)) {
//todo
const proxy = await getMany.apply(null, [rows, ...rest]);
proxy.splice.apply(proxy, [0, proxy.length, ...rows]);
await proxy.saveChanges.apply(proxy, args);
return proxy;
}
else {
let proxy = proxify([oldRows], args[0]);
proxy.splice.apply(proxy, [0, 1, rows]);
await proxy.saveChanges.apply(proxy, args);
return proxify(proxy[0], args[0]);
}
}

async function insert(rows, ...rest) {
const concurrency = undefined;
const args = [concurrency].concat(rest);
Expand Down
238 changes: 238 additions & 0 deletions src/getManyDto.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
const newQuery = require('./getManyDto/newQuery');
const negotiateRawSqlFilter = require('./table/column/negotiateRawSqlFilter');
const strategyToSpan = require('./table/strategyToSpan');
const executeQueries = require('./table/executeQueries');
const newPrimaryKeyFilter = require('./table/newPrimaryKeyFilter');
const newForeignKeyFilter = require('./table/relation/newForeignKeyFilter');

async function getManyDto(table, filter, strategy) {
filter = negotiateRawSqlFilter(filter, table);
let span = strategyToSpan(table, strategy);
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);
const manyNames = [];

const c = {};
c.visitJoin = () => {};
c.visitOne = () => {};
c.visitMany = function(leg) {
manyNames.push(leg.name);
};

span.legs.forEach(onEachLeg);
return createRow;

function onEachLeg(leg) {
leg.accept(c);
}

function createRow() {
const obj = Object.create(protoRow);
for (let i = 0; i < manyNames.length; i++) {
obj[manyNames[i]] = [];
}
return obj;
}
}

function createProto(columns, span) {
let obj = {};
for (let i = 0; i < columns.length; i++) {
obj[columns[i].alias] = null;
}
const c = {};

c.visitJoin = function(leg) {
obj[leg.name] = null;
};
c.visitOne = c.visitJoin;
c.visitMany = function(leg) {
obj[leg.name] = null;
};

span.legs.forEach(onEachLeg);

function onEachLeg(leg) {
leg.accept(c);
}

return obj;
}

function hasManyRelations(span) {
let result;
const c = {};
c.visitJoin = () => {};
c.visitOne = c.visitJoin;
c.visitMany = function() {
result = true;
};

span.legs.forEach(onEachLeg);
return result;

function onEachLeg(leg) {
leg.accept(c);
}
}

async function decode(strategy, span, rows, keys = rows.length > 0 ? Object.keys(rows[0]) : []) {
const table = span.table;
let columnsMap = span.columns;
const columns = table._columns.filter(column => !columnsMap || columnsMap.get(column));
const rowsLength = rows.length;
const columnsLength = columns.length;
const primaryColumns = table._primaryColumns;
const primaryColumnsLength = primaryColumns.length;
const rowsMap = new Map();
const fkIds = new Array(rows.length);
const getIds = createGetIds();

const outRows = new Array(rowsLength);
const createRow = newCreateRow(span);
const shouldCreateMap = hasManyRelations(span);
for (let i = 0; i < rowsLength; i++) {
const row = rows[i];
let outRow = createRow();
let pkWithNullCount = 0;
for (let j = 0; j < columnsLength; j++) {
if (j < primaryColumnsLength) {
if (row[keys[j]] === null)
pkWithNullCount++;
if (pkWithNullCount === primaryColumnsLength) {
outRow = null;
break;
}
}
const column = columns[j];
outRow[column.alias] = column.decode(row[keys[j]]);
if (shouldCreateMap)
fkIds[i] = getIds(outRow);
}
outRows[i] = outRow;
if (shouldCreateMap)
addToMap(rowsMap, primaryColumns, outRow);
}
span._rowsMap = rowsMap;
span._ids = fkIds;
for (let i = 0; i < columnsLength; i++) {
keys.shift();
}
await decodeRelations(strategy, span, rows, outRows, keys);
return outRows;


function createGetIds() {
const primaryColumns = table._primaryColumns;
const length = primaryColumns.length;
if (length > 1) {
const alias = table._primaryColumns[0].alias;
return (row) => row[alias];
}
else
return (row) => {
const result = new Array(length);
for (let i = 0; i < length; i++) {
result[i] = row[primaryColumns[i].alias];
}
return result;
};
}

}

async function decodeRelations(strategy, span, rawRows, resultRows, keys) {
const promises = [];
const c = {};
c.visitJoin = function(leg) {
const name = leg.name;
const p = decode(strategy[name], leg.span, rawRows, keys).then((rows) => {
for (let i = 0; i < rows.length; i++) {
resultRows[i][name] = rows[i];
}
});
promises.push(p);
};

c.visitOne = c.visitJoin;

c.visitMany = function(leg) {
const name = leg.name;
const table = span.table;
const relation = table._relations[name];
const filter = createOneFilter(relation, span._ids, resultRows, table);
const rowsMap = span._rowsMap;
const p = getManyDto(relation.childTable, filter, strategy[name]).then(subRows => {
for (let i = 0; i < subRows.length; i++) {
const key = leg.columns.map(column => subRows[i][column.alias]);
const parentRow = getFromMap(rowsMap, table._primaryColumns, key);
parentRow[name].push(subRows[i]);
}
});
promises.push(p);
};

span.legs.forEach(onEachLeg);

function onEachLeg(leg) {
leg.accept(c);
}

await Promise.all(promises);
}

function createOneFilter(relation, ids, parentRows, table) {
let parentTable = relation.joinRelation.childTable;

if (parentTable._primaryColumns.length === 1)
return relation.joinRelation.columns[0].in(ids);

else
return createCompositeFilter();

function createCompositeFilter() {
var filter = newPrimaryKeyFilter.apply(null, parentRows[0]);

for (var i = 1; i < ids.length; i++) {
const args = [table].concat(parentRows[i]);
filter = filter.or(newForeignKeyFilter.apply(null, args));
}
return filter;
}
}

function addToMap(map, primaryColumns, row) {

const lastIndex = primaryColumns.length - 1;
for (let i = 0; i < lastIndex; i++) {
const id = row[primaryColumns[i].alias];
if (map.has(id))
map = map.get(id);
else {
const next = new Map();
map.set(id, next);
map = next;
}
}
map.set(row[primaryColumns[lastIndex].alias], row);
}

function getFromMap(map, primaryColumns, values) {
const length = primaryColumns.length;
for (let i = 0; i < length; i++) {
map = map.get(values[i]);
}
return map;
}


module.exports = getManyDto;
18 changes: 18 additions & 0 deletions src/getManyDto/newQuery.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
var newSingleQuery = require('./query/newSingleQuery');
var extractFilter = require('../table/query/extractFilter');
var extractOrderBy = require('../table/query/extractOrderBy');
var extractLimit = require('../table/query/extractLimit');
var newParameterized = require('../table/query/newParameterized');
var extractOffset = require('../table/query/extractOffset');

function newQuery(table,filter,span,alias) {
filter = extractFilter(filter);
var orderBy = extractOrderBy(table,alias,span.orderBy);
var limit = extractLimit(span);
var offset = extractOffset(span);

var query = newSingleQuery(table,filter,span,alias,orderBy,limit,offset);
return newParameterized(query.sql(), query.parameters);
}

module.exports = newQuery;
8 changes: 8 additions & 0 deletions src/getManyDto/query/newColumnSql.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
var newShallowColumnSql = require('./singleQuery/newShallowColumnSql');
var newJoinedColumnSql = require('./singleQuery/newJoinedColumnSql');

module.exports = function(table,span,alias) {
var shallowColumnSql = newShallowColumnSql(table,alias, span);
var joinedColumnSql = newJoinedColumnSql(span,alias);
return shallowColumnSql + joinedColumnSql;
};
Loading

0 comments on commit e95e292

Please sign in to comment.