Browse Source

feat: Add SWITCH and IF dort in formula

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/448/head
Pranav C 3 years ago
parent
commit
c2ad42afb6
  1. 2
      packages/nc-gui/components/project/spreadsheet/components/editColumn/formulaOptions.vue
  2. 5
      packages/nc-gui/helpers/formulaList.js
  3. 4
      packages/nocodb/src/lib/dataMapper/lib/sql/formulaQueryBuilderFromString.ts
  4. 28
      packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/commonFns.ts
  5. 4
      packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/mssql.ts
  6. 4
      packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/mysql.ts
  7. 4
      packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/pg.ts
  8. 28
      packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/sqlite.ts

2
packages/nc-gui/components/project/spreadsheet/components/editColumn/formulaOptions.vue

@ -73,7 +73,7 @@ export default {
formula: {},
// formulas: ['AVERAGE()', 'COUNT()', 'COUNTA()', 'COUNTALL()', 'SUM()', 'MIN()', 'MAX()', 'AND()', 'OR()', 'TRUE()', 'FALSE()', 'NOT()', 'XOR()', 'ISERROR()', 'IF()', 'LEN()', 'MID()', 'LEFT()', 'RIGHT()', 'FIND()', 'CONCATENATE()', 'T()', 'VALUE()', 'ARRAYJOIN()', 'ARRAYUNIQUE()', 'ARRAYCOMPACT()', 'ARRAYFLATTEN()', 'ROUND()', 'ROUNDUP()', 'ROUNDDOWN()', 'INT()', 'EVEN()', 'ODD()', 'MOD()', 'LOG()', 'EXP()', 'POWER()', 'SQRT()', 'CEILING()', 'FLOOR()', 'ABS()', 'RECORD_ID()', 'CREATED_TIME()', 'ERROR()', 'BLANK()', 'YEAR()', 'MONTH()', 'DAY()', 'HOUR()', 'MINUTE()', 'SECOND()', 'TODAY()', 'NOW()', 'WORKDAY()', 'DATETIME_PARSE()', 'DATETIME_FORMAT()', 'SET_LOCALE()', 'SET_TIMEZONE()', 'DATESTR()', 'TIMESTR()', 'TONOW()', 'FROMNOW()', 'DATEADD()', 'WEEKDAY()', 'WEEKNUM()', 'DATETIME_DIFF()', 'WORKDAY_DIFF()', 'IS_BEFORE()', 'IS_SAME()', 'IS_AFTER()', 'REPLACE()', 'REPT()', 'LOWER()', 'UPPER()', 'TRIM()', 'SUBSTITUTE()', 'SEARCH()', 'SWITCH()', 'LAST_MODIFIED_TIME()', 'ENCODE_URL_COMPONENT()', 'REGEX_EXTRACT()', 'REGEX_MATCH()', 'REGEX_REPLACE()']
availableFunctions: formulaList,
availableBinOps: ['+', '-', '*', '/'],
availableBinOps: ['+', '-', '*', '/', '>', '==', '<=', '>=', '!='],
autocomplete: false,
suggestion: null,
wordToComplete: '',

5
packages/nc-gui/helpers/formulaList.js

@ -7,7 +7,6 @@ const validations = {
ADD: {
validation: {
args: { min: 1 }
}
},
CONCAT: {
@ -42,7 +41,9 @@ const validations = {
validation: { args: { rqd: 1 } }
},
SUBSTR: { validation: { args: { min: 2, max: 3 } } },
MID: { validation: { args: { rqd: 1 } } }
MID: { validation: { args: { rqd: 1 } } },
IF: { validation: { args: { min: 2, max: 3 } } },
SWITCH: { validation: { args: { min: 3 } } }
}
export default Object.keys(validations)

4
packages/nocodb/src/lib/dataMapper/lib/sql/formulaQueryBuilderFromString.ts

@ -66,6 +66,10 @@ export default function formulaQueryBuilder(tree, alias, knex, aliasToColumn = {
} else if (pt.type === 'Identifier') {
return knex.raw(`??${colAlias}`, [aliasToColumn[pt.name] || pt.name]);
} else if (pt.type === 'BinaryExpression') {
if (pt.operator === '==') {
pt.operator = '='
}
const query = knex.raw(`${fn(pt.left, null, pt.operator).toQuery()} ${pt.operator} ${fn(pt.right, null, pt.operator).toQuery()}${colAlias}`)
if (prevBinaryOp && pt.operator !== prevBinaryOp) {
query.wrap('(', ')')

28
packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/commonFns.ts

@ -0,0 +1,28 @@
import {MapFnArgs} from "../mapFunctionName";
export default {
// todo: handle default case
SWITCH: (args: MapFnArgs) => {
const count = Math.floor((args.pt.arguments.length-1) / 2)
let query = '';
const switchVal = args.fn(args.pt.arguments[0]).toQuery();
for (let i = 0; i < count; i++) {
query += args.knex.raw(`\n\tWHEN ${args.fn(args.pt.arguments[i * 2 + 1]).toQuery()} THEN ${args.fn(args.pt.arguments[i * 2 + 2]).toQuery()}`).toQuery()
}
if (args.pt.arguments.length % 2 === 0) {
query += args.knex.raw(`\n\tELSE ${args.fn(args.pt.arguments[args.pt.arguments.length - 1]).toQuery()}`).toQuery()
}
return args.knex.raw(`CASE ${switchVal} ${query}\n END${args.colAlias}`)
},
IF: (args: MapFnArgs) => {
let query = args.knex.raw(`\n\tWHEN ${args.fn(args.pt.arguments[0]).toQuery()} THEN ${args.fn(args.pt.arguments[1]).toQuery()}`).toQuery();
if (args.pt.arguments[2]) {
query += args.knex.raw(`\n\tELSE ${args.fn(args.pt.arguments[2]).toQuery()}`).toQuery()
}
return args.knex.raw(`CASE ${query}\n END${args.colAlias}`)
},
TRUE:(_args) => 1,
FALSE:(_args) => 0
}

4
packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/mssql.ts

@ -1,6 +1,8 @@
import {MapFnArgs} from "../mapFunctionName";
import commonFns from "./commonFns";
const mssql = {
...commonFns,
MIN: (args: MapFnArgs) => {
if (args.pt.arguments.length === 1) {
return args.fn(args.pt.arguments[0])
@ -49,7 +51,7 @@ const mssql = {
INT: (args: MapFnArgs) => {
return args.knex.raw(`CASE WHEN ISNUMERIC(${args.fn(args.pt.arguments[0]).toQuery()}) = 1 THEN FLOOR(${args.fn(args.pt.arguments[0]).toQuery()}) ELSE 0 END${args.colAlias}`)
},
MID:'SUBSTR'
MID:'SUBSTR',
}
export default mssql;

4
packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/mysql.ts

@ -1,7 +1,9 @@
import {MapFnArgs} from "../mapFunctionName";
import commonFns from "./commonFns";
const mysql2 = {
...commonFns,
LEN: 'CHAR_LENGTH',
MIN: 'LEAST',
MAX: 'GREATEST',
@ -20,7 +22,7 @@ const mysql2 = {
RIGHT:(args: MapFnArgs)=> {
return args.knex.raw(`SUBSTR(${args.fn(args.pt.arguments[0])},-${args.fn(args.pt.arguments[1])})${args.colAlias}`)
},
MID:'SUBSTR'
MID:'SUBSTR',
}

4
packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/pg.ts

@ -1,6 +1,8 @@
import {MapFnArgs} from "../mapFunctionName";
import commonFns from "./commonFns";
const pg = {
...commonFns,
LEN: 'length',
MIN: 'least',
MAX: 'greatest',
@ -15,7 +17,7 @@ const pg = {
// todo: correction
return args.knex.raw(`REGEXP_REPLACE(COALESCE(${args.fn(args.pt.arguments[0])}::character varying, '0'), '[^0-9]+|\\.[0-9]+' ,'')${args.colAlias}`)
},
MID: 'SUBSTR'
MID: 'SUBSTR',
}

28
packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/sqlite.ts

@ -1,38 +1,38 @@
import {MapFnArgs} from "../mapFunctionName";
import commonFns from "./commonFns";
const sqlite3 = {
...commonFns,
LEN: 'LENGTH',
CEILING(_pt) {
// todo:
}, FLOOR(_pt) {
// todo:
CEILING(args) {
return args.knex.raw(`round(${args.fn(args.pt.arguments[0])} + 0.5)${args.colAlias}`)
}, FLOOR(args) {
return args.knex.raw(`round(${args.fn(args.pt.arguments[0])} - 0.5)${args.colAlias}`)
},
MOD:(pt) => {
Object.assign(pt, {
MOD: (args: MapFnArgs) => {
return args.fn({
type: 'BinaryExpression',
operator: '%',
left: pt.arguments[0],
right: pt.arguments[1]
left: args.pt.arguments[0],
right: args.pt.arguments[1]
})
},
REPEAT(args: MapFnArgs) {
return args.knex.raw(`replace(printf('%.' || ${args.fn(args.pt.arguments[1])} || 'c', '/'),'/',${args.fn(args.pt.arguments[0])})${args.colAlias}`)
},
NOW: 'DATE',
SEARCH:'INSTR',
SEARCH: 'INSTR',
INT(args: MapFnArgs) {
return args.knex.raw(`CAST(${args.fn(args.pt.arguments[0])} as INTEGER)${args.colAlias}`)
},
LEFT:(args: MapFnArgs)=> {
LEFT: (args: MapFnArgs) => {
return args.knex.raw(`SUBSTR(${args.fn(args.pt.arguments[0])},1,${args.fn(args.pt.arguments[1])})${args.colAlias}`)
},
RIGHT:(args: MapFnArgs)=> {
RIGHT: (args: MapFnArgs) => {
return args.knex.raw(`SUBSTR(${args.fn(args.pt.arguments[0])},-${args.fn(args.pt.arguments[1])})${args.colAlias}`)
},
MID:'SUBSTR'
MID: 'SUBSTR',
}

Loading…
Cancel
Save