Browse Source

feat: Formula argument validation

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/448/head
Pranav C 3 years ago
parent
commit
3240ce4228
  1. 32
      packages/nc-gui/components/project/spreadsheet/components/editColumn/formulaOptions.vue
  2. 49
      packages/nc-gui/helpers/formulaList.js

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

@ -64,6 +64,7 @@ import NcAutocompleteTree from '@/helpers/NcAutocompleteTree'
import { getWordUntilCaret, insertAtCursor } from '@/helpers' import { getWordUntilCaret, insertAtCursor } from '@/helpers'
import debounce from 'debounce' import debounce from 'debounce'
import jsep from 'jsep' import jsep from 'jsep'
import formulaList, { validations } from '../../../../../helpers/formulaList'
export default { export default {
name: 'FormulaOptions', name: 'FormulaOptions',
@ -71,26 +72,7 @@ export default {
data: () => ({ data: () => ({
formula: {}, 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()'] // 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: [ availableFunctions: formulaList,
'AVG', 'ADD', 'CONCAT', 'TRIM',
'UPPER',
'LOWER',
'LEN',
'MIN',
'MAX',
'CEILING', 'FLOOR', 'ROUND',
'MOD', 'REPEAT',
'LOG', 'EXP', 'POWER', 'SQRT', // todo: remove in sqlite
'ABS',
'NOW',
'REPLACE',
'SEARCH',
'INT',
'RIGHT',
'LEFT',
'SUBSTR',
'MID'
],
availableBinOps: ['+', '-', '*', '/'], availableBinOps: ['+', '-', '*', '/'],
autocomplete: false, autocomplete: false,
suggestion: null, suggestion: null,
@ -200,6 +182,16 @@ export default {
if (!this.availableFunctions.includes(pt.callee.name)) { if (!this.availableFunctions.includes(pt.callee.name)) {
arr.push(`'${pt.callee.name}' function is not available`) arr.push(`'${pt.callee.name}' function is not available`)
} }
const validation = validations[pt.callee.name] && validations[pt.callee.name].validation
if (validation && validation.args) {
if (validation.args.rqd !== undefined && validation.args.rqd !== pt.arguments.length) {
arr.push(`'${pt.callee.name}' required ${validation.args.rqd} arguments`)
} else if (validation.args.min !== undefined && validation.args.min > pt.arguments.length) {
arr.push(`'${pt.callee.name}' required minimum ${validation.args.min} arguments`)
} else if (validation.args.max !== undefined && validation.args.max < pt.arguments.length) {
arr.push(`'${pt.callee.name}' required maximum ${validation.args.max} arguments`)
}
}
pt.arguments.map(arg => this.validateAgainstMeta(arg, arr)) pt.arguments.map(arg => this.validateAgainstMeta(arg, arr))
} else if (pt.type === 'Identifier') { } else if (pt.type === 'Identifier') {
if (this.meta.columns.every(c => c._cn !== pt.name)) { if (this.meta.columns.every(c => c._cn !== pt.name)) {

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

@ -0,0 +1,49 @@
const validations = {
AVG: {
validation: {
args: { min: 1 }
}
},
ADD: {
validation: {
args: { min: 1 }
}
},
CONCAT: {
validation: { args: { min: 1 } }
},
TRIM: {
validation: { args: { min: 1 } }
},
UPPER: {
validation: { args: { rqd: 1 } }
},
LOWER: { validation: { args: { rqd: 1 } } },
LEN: { validation: { args: { rqd: 1 } } },
MIN: { validation: { args: { min: 1 } } },
MAX: { validation: { args: { min: 1 } } },
CEILING: { validation: { args: { rqd: 1 } } },
FLOOR: { validation: { args: { rqd: 1 } } },
ROUND: { validation: { args: { rqd: 1 } } },
MOD: { validation: { args: { rqd: 2 } } },
REPEAT: { validation: { args: { rqd: 2 } } },
LOG: { validation: {} },
EXP: { validation: {} },
POWER: { validation: { args: { rqd: 2 } } },
SQRT: { validation: { args: { rqd: 1 } } },
ABS: { validation: { args: { rqd: 1 } } },
NOW: { validation: { args: { rqd: 0 } } },
REPLACE: { validation: { args: { rqd: 2 } } },
SEARCH: { validation: { args: { rqd: 2 } } },
INT: { validation: { args: { rqd: 1 } } },
RIGHT: { validation: { args: { rqd: 2 } } },
LEFT: {
validation: { args: { rqd: 1 } }
},
SUBSTR: { validation: { args: { min: 2, max: 3 } } },
MID: { validation: { args: { rqd: 1 } } }
}
export default Object.keys(validations)
export { validations }
Loading…
Cancel
Save