-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
handle data association with filter (#152)
* handle data association with filter * 2.6.50
- Loading branch information
1 parent
bb98840
commit 6231278
Showing
8 changed files
with
294 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
const { QueryExpression } = require('@themost/query'); | ||
// eslint-disable-next-line no-unused-vars | ||
const { DataEventArgs } = require('./types'); | ||
const { instanceOf } = require('./instance-of'); | ||
require('@themost/promise-sequence'); | ||
|
||
|
||
/** | ||
* @implements {BeforeExecuteEventListener} | ||
*/ | ||
class OnNestedQueryOptionsListener { | ||
/** | ||
* | ||
* @param {DataEventArgs} event | ||
* @param {function} callback | ||
*/ | ||
beforeExecute(event, callback) { | ||
OnNestedQueryOptionsListener.prototype.beforeExecuteAsync(event).then(function () { | ||
return callback(); | ||
}).catch(function (err) { | ||
return callback(err); | ||
}); | ||
} | ||
|
||
beforeExecuteAsync(event) { | ||
const query = event.emitter && event.emitter.query; | ||
const context = event.model.context; | ||
if (query == null) { | ||
return Promise.resolve(); | ||
} | ||
// handle only select statements | ||
if (query.$select == null) { | ||
return Promise.resolve(); | ||
} | ||
if (Object.prototype.hasOwnProperty.call(query, '$expand')) { | ||
// exit if expand is null or undefined | ||
if (query.$expand == null) { | ||
return Promise.resolve(); | ||
} | ||
/** | ||
* @type {Array<{ $entity:{ model:string }}>} | ||
*/ | ||
const expand = Array.isArray(query.$expand) ? query.$expand : [query.$expand]; | ||
if (expand.length) { | ||
const sources = expand.map(function (item) { | ||
return function () { | ||
// if entity is already a query expression | ||
if (instanceOf(item.$entity, QueryExpression)) { | ||
// do nothing | ||
return Promise.resolve(); | ||
} | ||
if (item.$entity && item.$entity.model) { | ||
// get entity alias (which is a field of current model) | ||
let options = null; | ||
if (item.$entity.$as != null) { | ||
// get current model | ||
let currentModel = event.model; | ||
/** | ||
* get attribute by name e.g. products.getAttributes('productionDescription') | ||
* @type {DataField} | ||
*/ | ||
let attribute = currentModel.getAttribute(item.$entity.$as); | ||
if (attribute == null) { | ||
if (item.$with) { | ||
// find another join by name | ||
const [key] = Object.keys(item.$with); | ||
if (key) { | ||
// get name e.g. orderedItem.id => orderedItem | ||
const [name] = key.split('.'); | ||
if (name) { | ||
// find expand by name (which is join alias) | ||
// e.g. expand.find(x => x.$entity.$as === 'orderedItem') | ||
const findExpand = expand.find((x) => x.$entity.$as === name); | ||
if (findExpand) { | ||
// get model by name | ||
// e.g. context.model('Producn') | ||
currentModel = context.model(findExpand.$entity.model); | ||
if (currentModel) { | ||
// get attribute by name | ||
// e.g. products.getAttributes('productionDescription') | ||
attribute = currentModel.getAttribute(item.$entity.$as); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
if (attribute == null) { | ||
return Promise.resolve(); | ||
} | ||
} | ||
const mapping = currentModel.inferMapping(attribute.name); | ||
if (mapping == null) { | ||
return Promise.resolve(); | ||
} | ||
options = mapping.options; | ||
if (options == null) { | ||
return Promise.resolve(); | ||
} | ||
if (options.$filter == null) { | ||
return Promise.resolve(); | ||
} | ||
} | ||
/** | ||
* @type {import('./data-model').DataModel} | ||
*/ | ||
const nestedModel = context.model(item.$entity.model); | ||
// if model exists | ||
if (nestedModel != null) { | ||
if (item.$entity.$as != null) { | ||
// change view to follow entity alias defined by the current query | ||
// this operation will be used while parsing filter and creating a new query expression | ||
nestedModel.view = item.$entity.$as; | ||
} | ||
return nestedModel.filterAsync(options).then((q) => { | ||
/** | ||
* @typedef {object} QueryExpressionWithPrepared | ||
* @property {*} $prepared | ||
*/ | ||
/** @type {QueryExpressionWithPrepared} */ | ||
const { query } = q; | ||
if (query && query.$prepared) { | ||
item.$with = { | ||
$and: [ | ||
item.$with, | ||
query.$prepared | ||
] | ||
} | ||
} | ||
return Promise.resolve(); | ||
}); | ||
} | ||
} | ||
return Promise.resolve(); | ||
} | ||
}); | ||
return Promise.sequence(sources); | ||
} | ||
} | ||
return Promise.resolve(); | ||
} | ||
|
||
} | ||
|
||
module.exports = { | ||
OnNestedQueryOptionsListener | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
{ | ||
"$schema": "https://themost-framework.github.io/themost/models/2018/2/schema.json", | ||
"name": "ProductDescription", | ||
"title": "ProductDescription", | ||
"version": "2.0", | ||
"inherits": "StructuredValue", | ||
"fields": [ | ||
{ | ||
"name": "description", | ||
"type": "Note" | ||
}, | ||
{ | ||
"name": "inLanguage", | ||
"type": "Text", | ||
"size": 5, | ||
"nullable": false | ||
}, | ||
{ | ||
"name": "product", | ||
"type": "Product", | ||
"nullable": false | ||
} | ||
], | ||
"constraints": [ | ||
{ | ||
"type": "unique", | ||
"fields": [ | ||
"product", | ||
"inLanguage" | ||
] | ||
} | ||
] | ||
} |