Browse Source

fix(core): Fix "contains" list filter operator for postgres

Michael Bromley 6 years ago
parent
commit
c3898a6fcc

+ 18 - 0
packages/core/src/service/helpers/list-query-builder/get-column-metadata.ts

@@ -0,0 +1,18 @@
+import { Type } from '@vendure/common/lib/shared-types';
+import { Connection } from 'typeorm';
+import { ColumnMetadata } from 'typeorm/metadata/ColumnMetadata';
+
+export function getColumnMetadata<T>(connection: Connection, entity: Type<T>) {
+    const metadata = connection.getMetadata(entity);
+    const columns = metadata.columns;
+    let translationColumns: ColumnMetadata[] = [];
+    const relations = metadata.relations;
+
+    const translationRelation = relations.find(r => r.propertyName === 'translations');
+    if (translationRelation) {
+        const translationMetadata = connection.getMetadata(translationRelation.type);
+        translationColumns = columns.concat(translationMetadata.columns.filter(c => !c.relationMetadata));
+    }
+    const alias = metadata.name.toLowerCase();
+    return { columns, translationColumns, alias };
+}

+ 21 - 19
packages/core/src/service/helpers/list-query-builder/parse-filter-params.ts

@@ -1,7 +1,6 @@
 import { Type } from '@vendure/common/lib/shared-types';
 import { assertNever } from '@vendure/common/lib/shared-utils';
-import { Connection } from 'typeorm';
-import { ColumnMetadata } from 'typeorm/metadata/ColumnMetadata';
+import { Connection, ConnectionOptions } from 'typeorm';
 
 import { UserInputError } from '../../../common/error/errors';
 import {
@@ -14,6 +13,8 @@ import {
 } from '../../../common/types/common-types';
 import { VendureEntity } from '../../../entity/base/base.entity';
 
+import { getColumnMetadata } from './get-column-metadata';
+
 export interface WhereCondition {
     clause: string;
     parameters: { [param: string]: string | number };
@@ -30,21 +31,9 @@ export function parseFilterParams<T extends VendureEntity>(
     if (!filterParams) {
         return [];
     }
-
-    const metadata = connection.getMetadata(entity);
-    const columns = metadata.columns;
-    let translationColumns: ColumnMetadata[] = [];
-    const relations = metadata.relations;
-
-    const translationRelation = relations.find(r => r.propertyName === 'translations');
-    if (translationRelation) {
-        const translationMetadata = connection.getMetadata(translationRelation.type);
-        translationColumns = columns.concat(translationMetadata.columns.filter(c => !c.relationMetadata));
-    }
-
+    const { columns, translationColumns, alias } = getColumnMetadata(connection, entity);
     const output: WhereCondition[] = [];
-    const alias = metadata.name.toLowerCase();
-
+    const dbType = connection.options.type;
     let argIndex = 1;
     for (const [key, operation] of Object.entries(filterParams)) {
         if (operation) {
@@ -57,7 +46,13 @@ export function parseFilterParams<T extends VendureEntity>(
                 } else {
                     throw new UserInputError('error.invalid-filter-field');
                 }
-                const condition = buildWhereCondition(fieldName, operator as Operator, operand, argIndex);
+                const condition = buildWhereCondition(
+                    fieldName,
+                    operator as Operator,
+                    operand,
+                    argIndex,
+                    dbType,
+                );
                 output.push(condition);
                 argIndex++;
             }
@@ -67,7 +62,13 @@ export function parseFilterParams<T extends VendureEntity>(
     return output;
 }
 
-function buildWhereCondition(fieldName: string, operator: Operator, operand: any, argIndex: number): WhereCondition {
+function buildWhereCondition(
+    fieldName: string,
+    operator: Operator,
+    operand: any,
+    argIndex: number,
+    dbType: ConnectionOptions['type'],
+): WhereCondition {
     switch (operator) {
         case 'eq':
             return {
@@ -75,8 +76,9 @@ function buildWhereCondition(fieldName: string, operator: Operator, operand: any
                 parameters: { [`arg${argIndex}`]: operand },
             };
         case 'contains':
+            const LIKE = dbType === 'postgres' ? 'ILIKE' : 'LIKE';
             return {
-                clause: `${fieldName} LIKE :arg${argIndex}`,
+                clause: `${fieldName} ${LIKE} :arg${argIndex}`,
                 parameters: { [`arg${argIndex}`]: `%${operand.trim()}%` },
             };
         case 'lt':

+ 4 - 1
packages/core/src/service/helpers/list-query-builder/parse-sort-params.spec.ts

@@ -145,5 +145,8 @@ export class MockConnection {
             columns: this.columnsMap.get(entity) || [],
             relations: this.relationsMap.get(entity) || [],
         };
-    }
+    };
+    readonly options = {
+        type: 'sqljs',
+    };
 }

+ 3 - 14
packages/core/src/service/helpers/list-query-builder/parse-sort-params.ts

@@ -7,6 +7,8 @@ import { UserInputError } from '../../../common/error/errors';
 import { NullOptionals, SortParameter } from '../../../common/types/common-types';
 import { VendureEntity } from '../../../entity/base/base.entity';
 
+import { getColumnMetadata } from './get-column-metadata';
+
 /**
  * Parses the provided SortParameter array against the metadata of the given entity, ensuring that only
  * valid fields are being sorted against. The output assumes
@@ -22,21 +24,8 @@ export function parseSortParams<T extends VendureEntity>(
     if (!sortParams || Object.keys(sortParams).length === 0) {
         return {};
     }
-
-    const metadata = connection.getMetadata(entity);
-    const columns = metadata.columns;
-    let translationColumns: ColumnMetadata[] = [];
-    const relations = metadata.relations;
-
-    const translationRelation = relations.find(r => r.propertyName === 'translations');
-    if (translationRelation) {
-        const translationMetadata = connection.getMetadata(translationRelation.type);
-        translationColumns = columns.concat(translationMetadata.columns.filter(c => !c.relationMetadata));
-    }
-
+    const { columns, translationColumns, alias } = getColumnMetadata(connection, entity);
     const output: OrderByCondition = {};
-    const alias = metadata.name.toLowerCase();
-
     for (const [key, order] of Object.entries(sortParams)) {
         if (columns.find(c => c.propertyName === key)) {
             output[`${alias}.${key}`] = order as any;