Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
67 changes: 66 additions & 1 deletion lib/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const postgresTypeMap = new WeakMap([

module.exports = {
primaryKeyTypes, postgresTypeMap, inputValue,
inputRecord, outputRecord, getCode
inputRecord, outputRecord, getCode, constructFilterRelationQuery, constructTypesPathToChild, isRelationFilter, getRelationFilterSegments
}


Expand Down Expand Up @@ -117,3 +117,68 @@ function outputBuffer (value) {
if (Buffer.isBuffer(value)) return value
return buffer(value.slice(2), 'hex')
}


function constructFilterRelationQuery( typeMap,
recordTypes,
typesPathToParent,
pathSegmentsToParent,
whereOperation,
value,
query = '' ){

if( !typesPathToParent.length ){
return query
}

const pathSegment = pathSegmentsToParent[0]
const currentType = typesPathToParent[0]
if(!query){
//TODO: can I always assume id here?
query = `SELECT id FROM "${typeMap[currentType] || currentType}" WHERE ${whereOperation(pathSegment, value)} \n`
}
else {
const recordType = recordTypes[currentType]
if(!recordType[pathSegment].isArray) {
query = `SELECT id FROM "${typeMap[currentType] || currentType}" WHERE "${pathSegment}" IN ( ${query} ) \n`
}
else{
query = `SELECT id FROM "${typeMap[currentType] || currentType}" WHERE "${pathSegment}" && ARRAY( ${query} ) \n`
}
}

return constructFilterRelationQuery( typeMap,
recordTypes,
typesPathToParent.slice(1),
pathSegmentsToParent.slice(1),
whereOperation,
value,
query)
}


function constructTypesPathToChild( recordTypes, parent, remainingPathSegments, typesPath ){
if( !remainingPathSegments.length ){
return typesPath
}

const segment = remainingPathSegments[0]
const nextType = parent[segment].link

//complex type
if( nextType ){
typesPath.push( nextType )
parent = recordTypes[nextType]
}
return constructTypesPathToChild(recordTypes, parent, remainingPathSegments.slice(1), typesPath )
}


function isRelationFilter( field ){
return field.split(':').length > 1
}


function getRelationFilterSegments( field ){
return field.split(':')
}
38 changes: 38 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,44 @@ module.exports = Adapter => class PostgreSQLAdapter extends Adapter {
}
}

for (const field in options.fuzzyMatch) {
let value = options.fuzzyMatch[field]
//simple filter
if( ! helpers.isRelationFilter(field) ){
//We assume the request has been validaded on another level. (so only strings, no arrays, etc...)
index++
parameters.push(inputValue(value))
where.push(`"${field}" ~* $${index}`)
}
//relationship filter
else {
const whereOperation = (field, value) => {
index++
parameters.push(inputValue(value))
return `"${field}" ~* $${index}`
}
const relationFilterSegments = helpers.getRelationFilterSegments(field);
const typesPath = helpers.constructTypesPathToChild( recordTypes, recordTypes[type], relationFilterSegments, [] )
const query = helpers.constructFilterRelationQuery( typeMap,
recordTypes,
typesPath.slice().reverse(),
relationFilterSegments.slice().reverse(),
whereOperation,
value,
''
)
const startField = relationFilterSegments[0]
const isArray = fields[startField][isArrayKey]
if(isArray){
where.push(`"${startField}" && ARRAY(${query})`)
}
else {
where.push(`"${startField}" in (${query})`)
}

}
}

where = where.length ? `where ${where.join(' and ')}` : ''

for (const field in options.sort) {
Expand Down