From b489090b45249eeeb2e8bb1671e92cd7b1d0143f Mon Sep 17 00:00:00 2001 From: Pavel Tiunov Date: Wed, 24 Apr 2019 18:07:50 +0300 Subject: [PATCH] feat(schema-compiler): Allow to pass functions to USER_CONTEXT Fixes #88 --- .../adapter/BaseQuery.js | 26 ++++++++++++++---- .../test/GraphBuilderTest.js | 27 ++++++++++++++++++- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/packages/cubejs-schema-compiler/adapter/BaseQuery.js b/packages/cubejs-schema-compiler/adapter/BaseQuery.js index f2389cc14c20c..7156379f06315 100644 --- a/packages/cubejs-schema-compiler/adapter/BaseQuery.js +++ b/packages/cubejs-schema-compiler/adapter/BaseQuery.js @@ -1299,16 +1299,32 @@ class BaseQuery { contextSymbolsProxy(symbols) { return new Proxy(symbols, { get: (target, name) => { - const paramValue = target[name]; - return { - filter: (column) => (paramValue ? `${column} = ${this.paramAllocator.allocateParam(paramValue)}` : '1 = 1'), + const propValue = target[name]; + const methods = (paramValue) => ({ + filter: (column) => { + if (paramValue) { + const value = Array.isArray(paramValue) ? + paramValue.map(this.paramAllocator.allocateParam.bind(this.paramAllocator)) : + this.paramAllocator.allocateParam(paramValue); + if (typeof column === "function") { + return column(value); + } else { + return `${column} = ${value}`; + } + } else { + return '1 = 1'; + } + }, requiredFilter: (column) => { if (!paramValue) { throw new UserError(`Filter for ${column} is required`); } - return `${column} = ${this.paramAllocator.allocateParam(paramValue)}`; + return methods.filter(column); } - }; + }); + return methods(target)[name] || + typeof propValue === 'object' && this.contextSymbolsProxy(propValue) || + methods(propValue); } }); } diff --git a/packages/cubejs-schema-compiler/test/GraphBuilderTest.js b/packages/cubejs-schema-compiler/test/GraphBuilderTest.js index ef340a4eeee3f..6e2271c7147c7 100644 --- a/packages/cubejs-schema-compiler/test/GraphBuilderTest.js +++ b/packages/cubejs-schema-compiler/test/GraphBuilderTest.js @@ -17,7 +17,8 @@ describe('JoinGraph', () => { cube(\`visitors\`, { sql: \` - select * from visitors WHERE \${USER_CONTEXT.source.filter('source')} + select * from visitors WHERE \${USER_CONTEXT.source.filter('source')} AND + \${USER_CONTEXT.sourceArray.filter(sourceArray => \`source in (\${sourceArray.join(',')})\`)} \`, sqlAlias: 'visitors_table', @@ -1175,6 +1176,30 @@ describe('JoinGraph', () => { }); }); + it('user context array', () => compiler.compile().then(() => { + const query = new PostgresQuery({ joinGraph, cubeEvaluator, compiler }, { + measures: [ + 'visitor_checkins.revenue_per_checkin' + ], + timeDimensions: [], + timezone: 'America/Los_Angeles', + contextSymbols: { + userContext: { + sourceArray: ['some', 'google'] + } + } + }); + + console.log(query.buildSqlAndParams()); + + return dbRunner.testQuery(query.buildSqlAndParams()).then(res => { + console.log(JSON.stringify(res)); + res.should.be.deepEqual( + [{ "visitor_checkins.revenue_per_checkin": "50" }] + ); + }); + })); + it('reference cube sql', () => runQueryTest({ measures: [