Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync handlers fix #208

Merged
merged 7 commits into from
Aug 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 131 additions & 17 deletions migrations/1655979260869-sync-handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -318,20 +318,10 @@ const generateSelectWhereCode = /*javascript*/`({ string, object, number, value,
const keys = Object.keys(_where);
for (let i = 0; i < keys.length; i++ ){
if (_where[keys[i]]) {
if ( _where[keys[i]] !== 'object') {
where.push('"main".'.concat(keys[i], ' = ', _where[keys[i]]));
if (_where[keys[i]]['in']){
where.push('"main".'.concat(keys[i], ' IN (', _where[keys[i]]['in'].join(', '), ')'));
} else {
if (_where[keys[i]]['in']){
if(typeof _where[keys[i]]['in'][0] === 'number'){
where.push('"main".'.concat(keys[i], ' IN (', _where[keys[i]]['in'].join(', '), ')'));
} else if(typeof _where[keys[i]]['in'][0] === 'string'){
where.push('"main".'.concat(keys[i], " IN ('", _where[keys[i]]['in'].join("', '"), "')"));
} else {
where.push('"main".'.concat(keys[i], " IN ('", _where[keys[i]]['in'].map((key)=>JSON.stringify(key)).join("'::jsonb, '"), "'::jsonb)"));
}
} else {
where.push('"main".'.concat(keys[i], " = '", JSON.stringify(_where[keys[i]]), "'::jsonb"));
}
where.push('"main".'.concat(keys[i], ' = ', _where[keys[i]]));
}
}
}
Expand All @@ -355,6 +345,126 @@ const fillValueByLinksCode = /*javascript*/`(links) => {
}
}`;

const filterLinksByValueCode = /*javascript*/`(links, _where) => {
let table;
let linkId;
if (!links.length) return links;
linksLoop: for (let i = 0; i < links.length; i++){
if (_where.string){
const stringKeys = _where?.string ? Object.keys(_where.string) : undefined;
for (let j = 0; j < stringKeys.length; j++ ){
if (_where.string[stringKeys[j]]['_in']){
if (!_where.string[stringKeys[j]]['_in'].includes(links[i]?.value?.[stringKeys[j]])){
links[i] = undefined;
continue linksLoop;
}
} else {
if (links[i]?.value?.[stringKeys[j]] != _where.string[stringKeys[j]]) {
links[i] = undefined;
continue linksLoop;
}
}
}
}
if (_where.number){
const numberKeys = _where?.number ? Object.keys(_where.number) : undefined;
for (let j = 0; j < numberKeys.length; j++ ){
if (_where.number[numberKeys[j]]['_in']){
if (!_where.number[numberKeys[j]]['_in'].includes(links[i]?.value?.[numberKeys[j]])){
links[i] = undefined;
continue linksLoop;
}
} else {
if (links[i]?.value?.[numberKeys[j]] != _where.number[numberKeys[j]]) {
links[i] = undefined;
continue linksLoop;
}
}
}
}
if (_where.object){
const objectKeys = _where?.object ? Object.keys(_where.object) : undefined;
for (let j = 0; j < objectKeys.length; j++ ){
if (_where.object[objectKeys[j]]['_in']){
if (objectKeys[j] === 'value'){
let founded = false;
for (let l = 0; l < _where.object[objectKeys[j]]['_in'].length; l++ ){
if (typeof links[i]?.value?.[objectKeys[j]] === 'object' && isDeepEqual(_where.object[objectKeys[j]]['_in'][l], links[i]?.value?.[objectKeys[j]])) founded = true;
}
if (!founded){
links[i] = undefined;
continue linksLoop;
}
} else {
if (!_where.number[numberKeys[j]]['_in'].includes(links[i]?.value?.[numberKeys[j]])){
links[i] = undefined;
continue linksLoop;
}
}
} else {
if (objectKeys[j] === 'value' && typeof links[i]?.value?.value === 'object' && isDeepEqual(_where.object[objectKeys[j]], links[i]?.value?.[objectKeys[j]])) {
founded = true;
} else if (links[i]?.value?.[objectKeys[j]] != _where.object[objectKeys[j]]) {
links[i] = undefined;
continue linksLoop;
}
}
}
}
if (_where.value){
const valueKeys = _where?.value ? Object.keys(_where.value) : undefined;
for (let j = 0; j < valueKeys.length; j++ ){
if (_where.value?.[valueKeys[j]]['_in']){
if (valueKeys[j] === 'value'){
let founded = false;
for (let l = 0; l < _where.value[valueKeys[j]]['_in'].length; l++ ){
if (typeof _where.value[valueKeys[j]]['_in'][l] === 'object'){
if (typeof links[i]?.value?.[valueKeys[j]] === 'object' && isDeepEqual(_where.value[valueKeys[j]]['_in'][l], links[i]?.value?.[valueKeys[j]])) founded = true;
} else {
if (_where.value[valueKeys[j]]['_in'][l] === links[i]?.value?.[valueKeys[j]]) founded = true;
}
}
if (!founded){
links[i] = undefined;
continue linksLoop;
}
} else if (!_where.value?.[valueKeys[j]]['_in'].includes(links[i]?.value?.[valueKeys[j]])){
links[i] = undefined;
continue linksLoop;
}
} else {
if (links[i]?.value?.[valueKeys[j]] != _where?.value[valueKeys[j]]) {
links[i] = undefined;
continue linksLoop;
}
}
}
}
}
}`;

const isDeepEqualCode = /*javascript*/`(object1, object2) => {
const objKeys1 = Object.keys(object1);
const objKeys2 = Object.keys(object2);

if (objKeys1.length !== objKeys2.length) return false;

for (var key of objKeys1) {
const value1 = object1[key];
const value2 = object2[key];

const isObjects = value1 != null && typeof value1 === "object" && value2 != null && typeof value2 === "object"

if ((isObjects && !isDeepEqual(value1, value2)) ||
(!isObjects && value1 !== value2)
) {
return false;
}
}
return true;
}`;


const findLinkIdByValueCode = /*javascript*/`({ string, object, number, value }) => {
let table;
if (string) {
Expand Down Expand Up @@ -393,8 +503,8 @@ const findLinkIdByValueCode = /*javascript*/`({ string, object, number, value })
}
}`;

const wherePush = `\`\${whereFileds[i]} = '\${exp[whereFileds[i]]}'::\${(typeof exp[whereFileds[i]]) == 'string' ? 'text' : 'bigint'}\``;
const setPush = `\`\${setFileds[i]} = '\${_set[setFileds[i]]}'::\${table === 'strings' ? 'text' : 'bigint'}\``;
const wherePush = `\`\${whereFileds[i]} = '\${ (typeof exp[whereFileds[i]]) == 'object' ? JSON.stringify(exp[whereFileds[i]]) : exp[whereFileds[i]]}'::\${(typeof exp[whereFileds[i]]) == 'string' ? 'text' : (typeof exp[whereFileds[i]]) == 'object' ? 'jsonb' : 'bigint'}\``;
const setPush = `\`\${setFileds[i]} = '\${ table === 'objects' ? JSON.stringify(_set[setFileds[i]]) : _set[setFileds[i]]}'::\${table === 'strings' ? 'text' : table === 'objects' ? 'jsonb' : 'bigint'}\``;

const deepFabric = /*javascript*/`(ownerId, hasura_session) => {
hasura_session['x-hasura-role'] = 'link';
Expand Down Expand Up @@ -428,18 +538,22 @@ const deepFabric = /*javascript*/`(ownerId, hasura_session) => {
},
select: function(_where, options) {
if (options?.table && !['links', 'tree', 'can', 'selectors'].includes(options?.table)) plv8.elog(ERROR, 'select not from "links" not permitted');
if (_where?.object) plv8.elog(ERROR, 'link.object relation is not supported in deep.client mini');
plv8.execute('SELECT set_config($1, $2, $3)', [ 'hasura.user', JSON.stringify({...hasura_session, 'x-hasura-user-id': this.linkId}), true]);
hasura_session['x-hasura-user-id'] = this.linkId;
if (!options?.table || options?.table === 'links'){
const { id, type_id, from_id, to_id, number, string, object, value } = _where;
const generateSelectWhere = ${generateSelectWhereCode};
const findLinkIdByValue = ${findLinkIdByValueCode};
const fillValueByLinks = ${fillValueByLinksCode};
const isDeepEqual = ${isDeepEqualCode};
const filterLinksByValue = ${filterLinksByValueCode};
let where = generateSelectWhere(_where);
let links = [];
if (where) links = plv8.execute(${selectWithPermissions}, [ this.linkId ]);
fillValueByLinks(links);
if (_where.string || _where.object || _where.number || _where.value){
filterLinksByValue(links, _where);
}
if (options?.returning) return { data: links.map(link=>link[options?.returning]) };
return { data: links };
}
Expand Down Expand Up @@ -499,7 +613,7 @@ const deepFabric = /*javascript*/`(ownerId, hasura_session) => {
update: function(criteria, _set, options) {
const exp = typeof criteria === 'object' ? criteria : typeof criteria === 'number' || typeof criteria === 'bigint' ? { id: criteria } : null;
const { id, link_id, value } = criteria || {};
if (options?.table && !['strings', 'numbers'].includes(options?.table)) plv8.elog(ERROR, 'update '.concat(options?.table, ' not permitted'));
if (options?.table && !['strings', 'numbers', 'objects'].includes(options?.table)) plv8.elog(ERROR, 'update '.concat(options?.table, ' not permitted'));
const { table } = options || {};
plv8.execute('SELECT set_config($1, $2, $3)', [ 'hasura.user', JSON.stringify({...hasura_session, 'x-hasura-user-id': this.linkId}), true]);
hasura_session['x-hasura-user-id'] = this.linkId;
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
"benchmark": "export DEEPLINKS_HASURA_PATH=localhost:8080; export DEEPLINKS_HASURA_SSL=0; export DEEPLINKS_HASURA_SECRET=myadminsecretkey; ts-node benchmarks/index.ts",
"migrate": "npm run package:build && npx migrate@latest up --matches '*.js'",
"unmigrate": "npm run package:build && npx migrate@latest down --matches '*.js'",
"migrate-s-h": "npm run package:build && npx migrate@latest up 1655979260869-sync-handlers --matches '*.js'",
"unmigrate-s-h": "npm run package:build && npx migrate@latest down 1655979260869-sync-handlers --matches '*.js'",
"start-engine-docker": "npm run start-engine-docker-core",
"start-engine-docker-core": "cd ./node_modules/@deep-foundation/hasura && npm run docker",
"stop-engine-docker": "cd ./node_modules/@deep-foundation/hasura/local && docker-compose --project-name deep down",
Expand Down
Loading
Loading