diff --git a/.gitignore b/.gitignore index 0a0e0646..70861e8b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -.DS_Store /nbproject/private/ /node_modules .brackets.json @@ -8,4 +7,4 @@ build /bower_components /tmp /yarn-error.log -**/reports \ No newline at end of file +/reports/ \ No newline at end of file diff --git a/src/calc2/main.tsx b/src/calc2/main.tsx index fcaf6631..c047802b 100644 --- a/src/calc2/main.tsx +++ b/src/calc2/main.tsx @@ -64,10 +64,10 @@ export class Main extends React.Component { - + - + (

404

diff --git a/src/calc2/store/groups.ts b/src/calc2/store/groups.ts index c6becf8d..f29ed385 100644 --- a/src/calc2/store/groups.ts +++ b/src/calc2/store/groups.ts @@ -68,39 +68,16 @@ export function* rootSaga() { }; yield saga.put(success); if (setCurrent !== undefined && loadedGroups.length > 0) { - // In case the :filename and :index are set in the URL, - // it's necessary to set the correct group accordingly - if (setCurrent && setCurrent != 'first' && - setCurrent.filename && setCurrent.index) { - for(var i=0;i { constructor(props: Props) { super(props); this.state = {}; - // Fix issue of parsing + as a space - // https://www.npmjs.com/package/query-string - // https://github.com/sindresorhus/query-string/issues/305 - // https://stackoverflow.com/questions/2678551/when-to-encode-space-to-plus-or-20 - // https://stackoverflow.com/questions/3794919/replace-all-spaces-in-a-string-with - this.query = atob(props.params.query.split(' ').join('+')) + this.query = atob(props.params.query) } componentDidMount() { diff --git a/src/calc2/views/calc.tsx b/src/calc2/views/calc.tsx index 525ceeae..c70b5b99 100644 --- a/src/calc2/views/calc.tsx +++ b/src/calc2/views/calc.tsx @@ -50,11 +50,6 @@ export class Calc extends React.Component { })*/ this.apiView = this.props.location.pathname.split("/")[2] == "api" this.params = queryString.parse(this.props.location.search) - - // It's necessary to load remote group synchronouly - if (this.apiView) { - this.loadGroup(this.props); - } } componentDidUpdate(prevProps: Props): void { diff --git a/src/calc2/views/help.tsx b/src/calc2/views/help.tsx index 863ffd07..461dcea5 100644 --- a/src/calc2/views/help.tsx +++ b/src/calc2/views/help.tsx @@ -1942,18 +1942,6 @@ export class Help extends React.Component {
This is not in the SQL standard but is a PostgreSQL extension. - - a:string REGEXP 'PATTERN'
- a:string RLIKE 'PATTERN'
- boolean - returns true if expression evaluating to a string a matches - the pattern given as the second operand, false otherwise. -
- The pattern has to be given as a string literal and it can be an extended regular expression, the syntax for - which is discussed in Regular Expression Syntax. -
This might not be in the SQL standard but is supported in MySQL. - - a + b @@ -2052,12 +2040,9 @@ export class Help extends React.Component { - concat(a:"any" [, ...]) + concat(a:string [, ...]) string - returns the string that results from concatenating the arguments. -
May have one or more arguments. A non-string argument is implicitly converted to its equivalent string form and then concatenated. Returns null if any argument is null (like in MySQL). - + concatenates the given strings upper(a:string) @@ -2072,24 +2057,6 @@ export class Help extends React.Component { converts the given string to lower-case - - repeat(str:string, count:number) - string - returns a string consisting of the string str repeated count times. If count is less than 1, returns an empty string. Returns null if str or count are null. - - - - replace(str:string, from_str:string, to_str:string) - string - returns the string str with all occurrences of the string from_str replaced by the string to_str. replace() performs a case-sensitive match when searching for from_str. - - - - reverse(a:string) - string - returns the given string with the order of the characters reversed. - - strlen(a:string) number @@ -2185,7 +2152,7 @@ export class Help extends React.Component { 5 - = (comparison), {'>'}=, {'>'}, {'<'}=, {'<'}, {'<'}{'>'}, !=, LIKE, ILIKE, REGEXP, RLIKE + = (comparison), {'>'}=, {'>'}, {'<'}=, {'<'}, {'<'}{'>'}, !=, LIKE, ILIKE 6 diff --git a/src/db/exec/ValueExpr.ts b/src/db/exec/ValueExpr.ts index 04cfee59..cedeeaf0 100644 --- a/src/db/exec/ValueExpr.ts +++ b/src/db/exec/ValueExpr.ts @@ -445,8 +445,6 @@ export class ValueExprGeneric extends ValueExpr { return ValueExprGeneric._condition_compare(a, b, typeA, this._func); case 'like': case 'ilike': - case 'regexp': - case 'rlike': if(!this._regex){ throw new Error(`regex should have been set by check`); } @@ -598,18 +596,6 @@ export class ValueExprGeneric extends ValueExpr { this._regex = new RegExp('^' + regex_str + '$', flags); - break; - case 'regexp': - case 'rlike': - this._args[0].check(schemaA, schemaB); - if (this._args[1].getDataType() !== 'string' || this._args[1]._func !== 'constant') { - return false; - } - - // cache regex - const txt = this._args[1]._args[0]; // direct access of constant value - let regex_txt = txt; - this._regex = new RegExp(regex_txt); break; default: throw new Error('this should not happen!'); @@ -644,30 +630,6 @@ export class ValueExprGeneric extends ValueExpr { value += a; } return value; - case 'repeat': - const rep = this._args[0].evaluate(tupleA, tupleB, row, statementSession); - const count = this._args[1].evaluate(tupleA, tupleB, row, statementSession); - - if (rep === null || count === null) { - return null; - } - else { - return rep.repeat(count >= 0 ? count : 0); - } - case 'replace': - const str = this._args[0].evaluate(tupleA, tupleB, row, statementSession); - const from_str = this._args[1].evaluate(tupleA, tupleB, row, statementSession); - const to_str = this._args[2].evaluate(tupleA, tupleB, row, statementSession); - return str.replace(new RegExp(from_str, 'g'), to_str); - case 'reverse': - const r = this._args[0].evaluate(tupleA, tupleB, row, statementSession); - - if (r === null) { - return null; - } - else { - return r.split('').reverse().join(''); - } default: throw new Error('this should not happen!'); } @@ -904,32 +866,7 @@ export class ValueExprGeneric extends ValueExpr { return true; case 'lower': case 'upper': - case 'reverse': return this._checkArgsDataType(schemaA, schemaB, ['string']); - case 'replace': - return this._checkArgsDataType(schemaA, schemaB, ['string', 'string', 'string']); - case 'repeat': - //return this._checkArgsDataType(schemaA, schemaB, ['string', 'number']); - - if (this._args.length !== 2) { - throw new Error('this should not happen!'); - } - - // arguments must be of type string and number, or null - this._args[0].check(schemaA, schemaB); - const typeStr = this._args[0].getDataType(); - this._args[1].check(schemaA, schemaB); - const typeCount = this._args[1].getDataType(); - - if ( (typeStr !== 'string' && typeStr !== 'null') || - (typeCount !== 'number' && typeCount !== 'null') ) { - this.throwExecutionError(i18n.t('db.messages.exec.error-function-expects-type', { - func: 'repeat()', - expected: ['string', 'number'], - given: [typeStr, typeCount], - })); - } - break; case 'concat': if (this._args.length === 0) { throw new Error('this should not happen!'); @@ -946,9 +883,9 @@ export class ValueExprGeneric extends ValueExpr { if (this._dataType === 'null' && dataType !== 'null') { this._dataTypeCalculated = dataType; } - // else if (dataType !== 'null' && this._dataType !== dataType) { - // this.throwExecutionError(i18n.t('db.messages.exec.error-function-expects-arguments-of-same-type', {func: 'CONCAT()'})); - // } + else if (dataType !== 'null' && this._dataType !== dataType) { + this.throwExecutionError(i18n.t('db.messages.exec.error-function-expects-arguments-of-same-type', {func: 'CONCAT()'})); + } } break; default: @@ -1064,8 +1001,6 @@ export class ValueExprGeneric extends ValueExpr { case 'concat': case 'upper': case 'lower': - case 'replace': - case 'reverse': case 'date': return printFunction.call(this, _func.toUpperCase()); case 'strlen': @@ -1097,8 +1032,6 @@ export class ValueExprGeneric extends ValueExpr { case 'xor': case 'like': case 'ilike': - case 'regexp': - case 'rlike': case '=': return binary.call(this, _func); diff --git a/src/db/parser/grammar_ra.d.ts b/src/db/parser/grammar_ra.d.ts index e0bb5b61..5aa1b7df 100644 --- a/src/db/parser/grammar_ra.d.ts +++ b/src/db/parser/grammar_ra.d.ts @@ -340,8 +340,6 @@ declare module relalgAst { | 'and' | 'like' | 'ilike' - | 'regexp' - | 'rlike' | 'add' | 'sub' | 'mul' @@ -355,9 +353,6 @@ declare module relalgAst { | 'subdate' | 'upper' | 'lower' - | 'repeat' - | 'replace' - | 'reverse' | 'strlen' | 'abs' | 'floor' diff --git a/src/db/parser/grammar_ra.pegjs b/src/db/parser/grammar_ra.pegjs index 4df081b3..5e52bdaa 100644 --- a/src/db/parser/grammar_ra.pegjs +++ b/src/db/parser/grammar_ra.pegjs @@ -1419,7 +1419,7 @@ expr_rest_boolean_comparison codeInfo: getCodeInfo() }; } -/ _ o:('like'i / 'ilike'i / 'regexp'i / 'rlike'i) _ right:valueExprConstants +/ _ o:('like'i / 'ilike'i) _ right:valueExprConstants { if(right.datatype !== 'string'){ error(t('db.messages.parser.error-valueexpr-like-operand-no-string')); @@ -1505,7 +1505,6 @@ valueExprFunctionsNary = func:( ('coalesce'i { return ['coalesce', 'null']; }) / ('concat'i { return ['concat', 'string']; }) - / ('replace'i { return ['replace', 'string']; }) ) '(' _ arg0:valueExpr _ argn:(',' _ valueExpr _ )* ')' { @@ -1533,7 +1532,6 @@ valueExprFunctionsBinary / ('sub'i { return ['sub', 'number']; }) / ('mul'i { return ['mul', 'number']; }) / ('div'i { return ['div', 'number']; }) - / ('repeat'i { return ['repeat', 'string']; }) ) '(' _ arg0:valueExpr _ ',' _ arg1:valueExpr _ ')' { @@ -1553,7 +1551,6 @@ valueExprFunctionsUnary / ('ucase'i { return ['upper', 'string']; }) / ('lower'i { return ['lower', 'string']; }) / ('lcase'i { return ['lower', 'string']; }) - / ('reverse'i { return ['reverse', 'string']; }) / ('length'i { return ['strlen', 'number']; }) / ('abs'i { return ['abs', 'number']; }) / ('floor'i { return ['floor', 'number']; }) @@ -1708,7 +1705,7 @@ reference: https://dev.mysql.com/doc/refman/5.7/en/operator-precedence.html 2: - (unary minus) 3: *, /, % 4: -, + -5: = (comparison), >=, >, <=, <, <>, !=, IS, LIKE, REGEXP, RLIKE +5: = (comparison), >=, >, <=, <, <>, !=, IS, LIKE 6: CASE, WHEN, THEN, ELSE 7: AND 8: XOR diff --git a/src/db/parser/grammar_sql.pegjs b/src/db/parser/grammar_sql.pegjs index 447498e0..5af7dd14 100644 --- a/src/db/parser/grammar_sql.pegjs +++ b/src/db/parser/grammar_sql.pegjs @@ -1252,7 +1252,7 @@ expr_rest_boolean_comparison codeInfo: getCodeInfo() }; } -/ _ o:('like'i / 'ilike'i / 'regexp'i / 'rlike'i) _ right:valueExprConstants +/ _ o:('like'i / 'ilike'i) _ right:valueExprConstants { if(right.datatype !== 'string'){ error(t('db.messages.parser.error-valueexpr-like-operand-no-string')); @@ -1338,7 +1338,6 @@ valueExprFunctionsNary = func:( ('coalesce'i { return ['coalesce', 'null']; }) / ('concat'i { return ['concat', 'string']; }) - / ('replace'i { return ['replace', 'string']; }) ) '(' _ arg0:valueExpr _ argn:(',' _ valueExpr _ )* ')' { @@ -1366,7 +1365,6 @@ valueExprFunctionsBinary / ('sub'i { return ['sub', 'number']; }) / ('mul'i { return ['mul', 'number']; }) / ('div'i { return ['div', 'number']; }) - / ('repeat'i { return ['repeat', 'string']; }) ) '(' _ arg0:valueExpr _ ',' _ arg1:valueExpr _ ')' { @@ -1386,7 +1384,6 @@ valueExprFunctionsUnary / ('ucase'i { return ['upper', 'string']; }) / ('lower'i { return ['lower', 'string']; }) / ('lcase'i { return ['lower', 'string']; }) - / ('reverse'i { return ['reverse', 'string']; }) / ('length'i { return ['strlen', 'number']; }) / ('abs'i { return ['abs', 'number']; }) / ('floor'i { return ['floor', 'number']; }) @@ -1543,7 +1540,7 @@ reference: https://dev.mysql.com/doc/refman/5.7/en/operator-precedence.html 2: - (unary minus) 3: *, /, % 4: -, + -5: = (comparison), >=, >, <=, <, <>, !=, IS, LIKE, REGEXP +5: = (comparison), >=, >, <=, <, <>, !=, IS, LIKE 6: CASE, WHEN, THEN, ELSE 7: AND 8: XOR diff --git a/src/db/tests/translate_tests_ra.ts b/src/db/tests/translate_tests_ra.ts index 38aca02a..f2116f60 100644 --- a/src/db/tests/translate_tests_ra.ts +++ b/src/db/tests/translate_tests_ra.ts @@ -1089,69 +1089,6 @@ QUnit.test('pi with eval: upper()', function (assert) { assert.deepEqual(result, reference); }); -QUnit.test('pi with eval: lower()', function (assert) { - const relations = getTestRelations(); - const result = exec_ra(" sigma y < 'd' (pi lower(x)->y (pi upper(S.b)->x S)) ", relations).getResult(); - result.eliminateDuplicateRows(); - - const reference = exec_ra(` - { - x:string - a - b - c - }`, {}).getResult(); - - assert.deepEqual(result, reference); -}); - -QUnit.test('pi with eval: repeat()', function (assert) { - const relations = getTestRelations(); - const result = exec_ra(" pi repeat(b, 3)->x (R)) ", relations).getResult(); - result.eliminateDuplicateRows(); - - const reference = exec_ra('{x:string\n' + - 'aaa\n' + - 'ccc\n' + - 'ddd\n' + - 'eee\n' + - '}', {}).getResult(); - - assert.deepEqual(result, reference); -}); - -QUnit.test('pi with eval: replace()', function (assert) { - const relations = getTestRelations(); - const result = exec_ra(" pi replace(x, 'c', 'C')->y (pi concat(a, b, c)->x (R)) ", relations).getResult(); - result.eliminateDuplicateRows(); - - const reference = exec_ra('{y:string\n' + - '1ad\n' + - '3CC\n' + - '4df\n' + - '5db\n' + - '6ef\n' + - '}', {}).getResult(); - - assert.deepEqual(result, reference); -}); - -QUnit.test('pi with eval: reverse()', function (assert) { - const relations = getTestRelations(); - const result = exec_ra(" pi reverse(x)->y (pi concat(a, b, c)->x (R)) ", relations).getResult(); - result.eliminateDuplicateRows(); - - const reference = exec_ra('{y:string\n' + - 'da1\n' + - 'cc3\n' + - 'fd4\n' + - 'bd5\n' + - 'fe6\n' + - '}', {}).getResult(); - - assert.deepEqual(result, reference); -}); - QUnit.test('pi with eval: add()', function (assert) { const relations = getTestRelations(); const result = exec_ra(' pi a, add(a, a) ->x R ', relations).getResult(); @@ -1274,26 +1211,6 @@ QUnit.test('test like operator', function (assert) { assert.deepEqual(result, reference); }); -QUnit.test('test regexp operator', function (assert) { - const result = exec_ra(`pi x, x regexp '^(a|e)'->starts_a_or_e, x regexp '(a|e)$'->ends_b_or_c, x rlike '(a|e)'->has_a_or_e { - x - - abb - bba - bab - ebe - }`, {}).getResult(); - - const reference = exec_ra(`{ - x, starts_a_or_e, ends_a_or_e, has_a_or_e - - abb, true, false, true - bba, false, true, true - eab, false, false, true - aba, true, true, true - }`, {}).getResult(); - assert.deepEqual(result, reference); -}); QUnit.test('groupby textgen', function (assert) { const ast = relalgjs.parseRelalg(`gamma a; sum(b)->c ({a, b