Skip to content

Commit

Permalink
handle member expession (#93)
Browse files Browse the repository at this point in the history
* handle member expression

* handle member expression

* 2.13.1
  • Loading branch information
kbarbounakis authored Jul 7, 2024
1 parent 26dd7f0 commit 92d1f48
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 25 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@themost/query",
"version": "2.13.0",
"version": "2.13.1",
"description": "MOST Web Framework Codename ZeroGravity - Query Module",
"main": "dist/index.cjs.js",
"module": "dist/index.esm.js",
Expand Down
56 changes: 56 additions & 0 deletions spec/ResolvingMember.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { LiteralExpression, MemberExpression, MethodCallExpression, QueryEntity, QueryExpression, QueryField } from '../src/index';
import { MemoryAdapter } from './test/TestMemoryAdapter';
import { MemoryFormatter } from './test/TestMemoryFormatter';

describe('ResolvingMember', () => {

/**
* @type {MemoryAdapter}
*/
let db;
beforeAll(() => {
db = new MemoryAdapter();
});
afterAll(async () => {
if (db) {
await db.closeAsync();
}
});

it('should resolve custom member', async () => {
const orders = new QueryEntity('OrderData');
const people = new QueryEntity('PersonData');
const q = new QueryExpression();
q.resolvingMember.subscribe((event) => {
if (typeof event.member === 'string') {
const member = event.member.split('.');
const [,field] = member;
if (field === 'orderCustomer') {
event.member = new MethodCallExpression('concat', [
new QueryField('givenName').from(people),
new LiteralExpression(' '),
new QueryField('familyName').from(people),
])
}
}
})
q.select(
({id, orderCustomer}) => {
return {
id,
orderCustomer
}
}
).from(orders)
.join(people).with((x, {id}) => x.customer === id, people)
.orderBy(
({customer}) => customer
).take(10);
const items = await db.executeAsync(q);
for (let i = 0; i < items.length; i++) {
const item = items[i];
expect(item.orderCustomer).toBeTruthy();
}
});

});
5 changes: 3 additions & 2 deletions src/closures/ClosureParser.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// MOST Web Framework Codename Zero Gravity Copyright (c) 2017-2022, THEMOST LP All rights reserved
import {SyncSeriesEventEmitter} from '@themost/events';
import { Expression } from '../expressions';

export type SelectClosure = (x: any, ...params: any[]) => any;
export type FilterClosure = (x: any, ...params: any[]) => any;
Expand Down Expand Up @@ -28,7 +29,7 @@ export declare class ClosureParser {
parseMethod(expr: any): any;
parseIdentifier(expr: any): any;
parseLiteral(expr: any): any;
resolvingMember: SyncSeriesEventEmitter<{ target: any, member: string }>;
resolvingJoinMember: SyncSeriesEventEmitter<{ target: any, object: string, member: string, fullyQualifiedMember?: string }>;
resolvingMember: SyncSeriesEventEmitter<{ target: any, member: string | Expression }>;
resolvingJoinMember: SyncSeriesEventEmitter<{ target: any, object: string, member: string | Expression, fullyQualifiedMember?: string }>;
resolvingMethod: SyncSeriesEventEmitter<{ target: any, method: string }>;
}
19 changes: 18 additions & 1 deletion src/closures/ClosureParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
import {
LiteralExpression, ObjectExpression, Operators, SequenceExpression,
MemberExpression, ArithmeticExpression, LogicalExpression,
AggregateComparisonExpression, MethodCallExpression, ComparisonExpression
AggregateComparisonExpression, MethodCallExpression, ComparisonExpression,
Expression
} from '../expressions';
const isComparisonOperator = ComparisonExpression.isComparisonOperator;
const isArithmeticOperator = ArithmeticExpression.isArithmeticOperator;
Expand Down Expand Up @@ -806,6 +807,10 @@ class ClosureParser {
// otherwise resolve member of joined collection
self.resolvingJoinMember.emit(event);
}
// #handle-event-member
if (event.member instanceof Expression) {
return event.member;
}
// if event.object is not null
if (event.object != null) {
// concat member expression e.g. new MemberExpression(address.id)
Expand Down Expand Up @@ -857,6 +862,10 @@ class ClosureParser {
fullyQualifiedMember: fullyQualifiedMember
};
this.resolvingJoinMember.emit(event);
// #handle-event-member
if (event.member instanceof Expression) {
return event.member;
}
return new MemberExpression(event.object + '.' + event.member);
}
else {
Expand Down Expand Up @@ -892,6 +901,10 @@ class ClosureParser {
alias = null;
}
self.resolvingMember.emit(memberEvent);
// #handle-event-member
if (memberEvent.member instanceof Expression) {
return memberEvent.member;
}
return new MemberExpression(memberEvent.member);
} else {
let findQualifiedMember;
Expand Down Expand Up @@ -964,6 +977,10 @@ class ClosureParser {
fullyQualifiedMember: memberPath.join('.')
}
self.resolvingJoinMember.emit(memberEvent);
// #handle-event-member
if (memberEvent.member instanceof Expression) {
return memberEvent.member;
}
if (memberEvent.object != null) {
// concat member expression e.g. new MemberExpression(address.id)
return new MemberExpression(memberEvent.object + '.' + memberEvent.member);
Expand Down
21 changes: 13 additions & 8 deletions src/expressions.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ export declare interface ExpressionBase {
source?: string;
}

export declare abstract class Expression implements ExpressionBase {
exprOf(): any;
source?: string;
}

export declare interface SelectExpressionBase extends ExpressionBase {
as?: string;
}
Expand All @@ -28,50 +33,50 @@ export declare const Operators: {
BitAnd: string
}

export declare class ArithmeticExpression implements ExpressionBase {
export declare class ArithmeticExpression extends Expression {

static isArithmeticOperator(op: string): boolean;

constructor(left: any, operator: string, right:any);
exprOf(): any;
}

export declare class MemberExpression implements ExpressionBase {
export declare class MemberExpression extends Expression {
constructor(name: string);
exprOf(): any;
}

export declare class LogicalExpression implements ExpressionBase {
export declare class LogicalExpression extends Expression {

static isLogicalOperator(op: string): boolean;

constructor(operator: string, args: Array<any>);
exprOf(): any;
}

export declare class LiteralExpression implements ExpressionBase {
export declare class LiteralExpression extends Expression {
constructor(value: any);
exprOf(): any;
}

export declare class ComparisonExpression implements ExpressionBase {
export declare class ComparisonExpression extends Expression {

static isComparisonOperator(op: string): boolean;
constructor(left: any, operator: string, right:any);
exprOf(): any;
}

export declare class MethodCallExpression implements ExpressionBase {
export declare class MethodCallExpression extends Expression {
constructor(name: string, args: Array<any>);
exprOf(): any;
}

export declare class SequenceExpression implements ExpressionBase {
export declare class SequenceExpression extends Expression {
constructor();
exprOf(): any;
}

export declare class ObjectExpression implements ExpressionBase {
export declare class ObjectExpression extends Expression {
constructor();
exprOf(): any;
}
Expand Down
47 changes: 36 additions & 11 deletions src/expressions.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
// MOST Web Framework Codename Zero Gravity Copyright (c) 2017-2022, THEMOST LP All rights reserved
class ArithmeticExpression {

import { AbstractMethodError } from "@themost/common";

/**
* @abstract
*/
class Expression {
constructor() {
//
}
exprOf() {
throw new AbstractMethodError();
}
}

class ArithmeticExpression extends Expression {
constructor(p0, operator, p1) {
super();
this.left = p0;
this.operator = operator || '$add';
this.right = p1;
Expand Down Expand Up @@ -37,8 +53,9 @@ class ArithmeticExpression {
ArithmeticExpression.OperatorRegEx = /^(\$add|\$sub|\$mul|\$div|\$mod|\$bit)$/g;


class MemberExpression {
class MemberExpression extends Expression {
constructor(name) {
super();
this.name = name;
}
exprOf() {
Expand All @@ -48,8 +65,9 @@ class MemberExpression {
}
}

class LogicalExpression {
class LogicalExpression extends Expression {
constructor(operator, args) {
super();
this.operator = operator || '$and';
this.args = args || [];
}
Expand Down Expand Up @@ -83,8 +101,9 @@ class LogicalExpression {

LogicalExpression.OperatorRegEx = /^(\$and|\$or|\$not|\$nor)$/g;

class LiteralExpression {
class LiteralExpression extends Expression {
constructor(value) {
super();
this.value = value;
}
exprOf() {
Expand All @@ -94,8 +113,9 @@ class LiteralExpression {
}
}

class ComparisonExpression {
class ComparisonExpression extends Expression {
constructor(left, op, right) {
super();
this.left = left;
this.operator = op || '$eq';
this.right = right;
Expand Down Expand Up @@ -124,8 +144,9 @@ class ComparisonExpression {

ComparisonExpression.OperatorRegEx = /^(\$eq|\$ne|\$lte|\$lt|\$gte|\$gt|\$in|\$nin)$/g;

class MethodCallExpression {
class MethodCallExpression extends Expression {
constructor(name, args) {
super();
/**
* Gets or sets the name of this method
* @type {String}
Expand Down Expand Up @@ -199,8 +220,9 @@ const Operators = {
BitAnd: '$bit',
};

class SequenceExpression {
class SequenceExpression extends Expression {
constructor() {
super();
this.value = [];
}
exprOf() {
Expand Down Expand Up @@ -229,9 +251,9 @@ class SequenceExpression {
}
}

class ObjectExpression {
class ObjectExpression extends Expression {
constructor() {
//
super();
}
exprOf() {
let finalResult = {};
Expand Down Expand Up @@ -310,8 +332,9 @@ class AggregateComparisonExpression extends ComparisonExpression {
}


class SelectAnyExpression {
class SelectAnyExpression extends Expression {
constructor(expr, alias) {
super();
this.expression = expr;
this.as = alias;
}
Expand Down Expand Up @@ -350,8 +373,9 @@ class AnyExpressionFormatter {
}
}

class OrderByAnyExpression {
class OrderByAnyExpression extends Expression {
constructor(expr, direction) {
super();
this.expression = expr;
this.direction = direction || 'asc';
}
Expand Down Expand Up @@ -403,6 +427,7 @@ class SwitchExpression extends MethodCallExpression {

export {
Operators,
Expression,
ArithmeticExpression,
MemberExpression,
MethodCallExpression,
Expand Down
7 changes: 7 additions & 0 deletions src/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import './polyfills';
import {ObjectNameValidator} from './object-name.validator';
import {SyncSeriesEventEmitter} from '@themost/events';
import { instanceOf } from './instance-of';
import { Expression } from './expressions';

class QueryParameter {
constructor() {
Expand Down Expand Up @@ -78,12 +79,18 @@ class QueryExpression {
this.resolvingMethod = new SyncSeriesEventEmitter();

this.resolvingMember.subscribe((event) => {
if (event.member instanceof Expression) {
return;
}
if (this.$collection) {
event.member = this.$collection.concat('.', event.member);
}
});

this.resolvingJoinMember.subscribe((event) => {
if (event.member instanceof Expression) {
return;
}
if (this.$joinCollection != null && event.object == null) {
event.object = this.$joinCollection;
}
Expand Down

0 comments on commit 92d1f48

Please sign in to comment.