Browse Source

feat: support filter or sort using formula column

re #466

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/473/head
Pranav C 3 years ago
parent
commit
058cfd8156
  1. 8
      packages/nc-gui/components/project/spreadsheet/mixins/spreadsheet.js
  2. 4
      packages/nc-gui/components/project/spreadsheet/rowsXcDataTable.vue
  3. 2
      packages/nocodb/src/lib/dataMapper/lib/BaseModel.ts
  4. 28
      packages/nocodb/src/lib/dataMapper/lib/sql/BaseModelSql.ts
  5. 2
      packages/nocodb/src/lib/dataMapper/lib/sql/CustomKnex.ts

8
packages/nc-gui/components/project/spreadsheet/mixins/spreadsheet.js

@ -72,6 +72,14 @@ export default {
return c._cn return c._cn
}) })
}, },
formulaFieldList() {
return this.availableColumns.reduce((arr, c) => {
if (c.formula) {
arr.push(c._cn)
}
return arr
}, [])
},
availableRealColumns() { availableRealColumns() {
return this.availableColumns && this.availableColumns.filter(c => !c.virtual) return this.availableColumns && this.availableColumns.filter(c => !c.virtual)
}, },

4
packages/nc-gui/components/project/spreadsheet/rowsXcDataTable.vue

@ -109,12 +109,12 @@
<sort-list <sort-list
v-model="sortList" v-model="sortList"
:is-locked="isLocked" :is-locked="isLocked"
:field-list="realFieldList" :field-list="[...realFieldList, ...formulaFieldList]"
/> />
<column-filter <column-filter
v-model="filters" v-model="filters"
:is-locked="isLocked" :is-locked="isLocked"
:field-list="realFieldList" :field-list="[...realFieldList, ...formulaFieldList]"
dense dense
/> />
<v-tooltip bottom> <v-tooltip bottom>

2
packages/nocodb/src/lib/dataMapper/lib/BaseModel.ts

@ -1467,6 +1467,7 @@ abstract class BaseModel {
export interface XcFilter { export interface XcFilter {
where?: string; where?: string;
having?: string;
condition?: any; condition?: any;
conditionGraph?: any; conditionGraph?: any;
limit?: string | number; limit?: string | number;
@ -1477,6 +1478,7 @@ export interface XcFilter {
export interface XcFilterWithAlias extends XcFilter { export interface XcFilterWithAlias extends XcFilter {
w?: string; w?: string;
h?: string;
c?: any; c?: any;
l?: string | number; l?: string | number;
o?: string | number; o?: string | number;

28
packages/nocodb/src/lib/dataMapper/lib/sql/BaseModelSql.ts

@ -20,6 +20,7 @@ class BaseModelSql extends BaseModel {
public readonly _tn: string; public readonly _tn: string;
private _selectFormulas: any; private _selectFormulas: any;
private _selectFormulasObj: any;
private _defaultNestedQueryParams: any; private _defaultNestedQueryParams: any;
/** /**
@ -719,13 +720,14 @@ class BaseModelSql extends BaseModel {
try { try {
const {fields, where, limit, offset, sort, condition, conditionGraph = null} = this._getListArgs(args); const {fields, where, limit, offset, sort, condition, conditionGraph = null, having} = this._getListArgs(args);
const query = this.$db const query = this.$db
// .select(...fields.split(',')) // .select(...fields.split(','))
.select(this.selectQuery(fields)) .select(this.selectQuery(fields))
.select(...this.selectFormulas) .select(...this.selectFormulas)
.xwhere(where, this.selectQuery('')) .xwhere(where, {...this.selectQuery(''),...this.selectFormulasObj})
.xhaving(having, this.selectQuery(''))
.condition(condition, this.selectQuery('')) .condition(condition, this.selectQuery(''))
.conditionGraph(conditionGraph); .conditionGraph(conditionGraph);
@ -820,9 +822,9 @@ class BaseModelSql extends BaseModel {
* @memberof BaseModel * @memberof BaseModel
* @throws {Error} * @throws {Error}
*/ */
async countByPk({where = '', conditionGraph = null}) { async countByPk({where = '', conditionGraph = null, having = ''}) {
try { try {
if (this.isPg() && !conditionGraph && !where) { if (this.isPg() && !conditionGraph && !where && !having) {
const res = (await this._run( const res = (await this._run(
this.dbDriver.raw(`select reltuples::int8 as count this.dbDriver.raw(`select reltuples::int8 as count
from pg_class c JOIN pg_catalog.pg_namespace n ON n.oid=c.relnamespace from pg_class c JOIN pg_catalog.pg_namespace n ON n.oid=c.relnamespace
@ -836,7 +838,8 @@ class BaseModelSql extends BaseModel {
return await this._run(this.$db return await this._run(this.$db
.conditionGraph(conditionGraph) .conditionGraph(conditionGraph)
.count(`${this.tn}.${(this.pks[0] || this.columns[0]).cn} as count`) .count(`${this.tn}.${(this.pks[0] || this.columns[0]).cn} as count`)
.xwhere(where, this.selectQuery('')) .xwhere(where, {...this.selectQuery(''),...this.selectFormulasObj})
.xhaving(having, this.selectQuery(''))
.first()); .first());
} catch (e) { } catch (e) {
console.log(e); console.log(e);
@ -1710,6 +1713,7 @@ class BaseModelSql extends BaseModel {
_getListArgs(args: XcFilterWithAlias): XcFilter { _getListArgs(args: XcFilterWithAlias): XcFilter {
const obj: XcFilter = {}; const obj: XcFilter = {};
obj.where = args.where || args.w || ''; obj.where = args.where || args.w || '';
obj.having = args.having || args.h || '';
obj.condition = args.condition || args.c || {}; obj.condition = args.condition || args.c || {};
obj.conditionGraph = args.conditionGraph || {}; obj.conditionGraph = args.conditionGraph || {};
obj.limit = Math.max(Math.min(args.limit || args.l || this.config.limitDefault, this.config.limitMax), this.config.limitMin); obj.limit = Math.max(Math.min(args.limit || args.l || this.config.limitDefault, this.config.limitMax), this.config.limitMin);
@ -1808,7 +1812,7 @@ class BaseModelSql extends BaseModel {
} }
protected get defaultNestedQueryParams(): any { protected get defaultNestedQueryParams(): any {
if(!this._defaultNestedQueryParams) { if (!this._defaultNestedQueryParams) {
// generate default nested fields args based on virtual column list // generate default nested fields args based on virtual column list
try { try {
const nestedFields: { const nestedFields: {
@ -1882,6 +1886,18 @@ class BaseModelSql extends BaseModel {
return this._selectFormulas return this._selectFormulas
} }
protected get selectFormulasObj() {
if (!this._selectFormulasObj) {
this._selectFormulasObj = (this.virtualColumns || [])?.reduce((obj, v) => {
if (v.formula?.value && !v.formula?.error?.length) {
obj[v._cn] = formulaQueryBuilder(v.formula?.tree, null, this.dbDriver, this.aliasToColumn);
}
return obj;
}, {})
}
return this._selectFormulasObj;
}
} }

2
packages/nocodb/src/lib/dataMapper/lib/sql/CustomKnex.ts

@ -323,7 +323,7 @@ declare module 'knex' {
* Append xwhere to knex query builder * Append xwhere to knex query builder
*/ */
Knex.QueryBuilder.extend('xwhere', function (conditionString, columnAliases?: { Knex.QueryBuilder.extend('xwhere', function (conditionString, columnAliases?: {
[columnAlias: string]: string [columnAlias: string]: string|any
}) { }) {
const conditions = toArrayOfConditions(conditionString); const conditions = toArrayOfConditions(conditionString);
return appendWhereCondition(conditions, columnAliases || {}, this); return appendWhereCondition(conditions, columnAliases || {}, this);

Loading…
Cancel
Save