Skip to content
Permalink
Browse files
Implement XOR Operator
Implemented XOR in the grammar using logical and, or and not.

This is ticket AGE2-478

Added regression tests.
  • Loading branch information
dehowef committed Oct 23, 2021
1 parent bf35db2 commit 163e064086eac52eb68dbc55a77897a74df01ce6
Showing 4 changed files with 74 additions and 3 deletions.
@@ -492,7 +492,7 @@ $$) AS r(result boolean);
(1 row)

--
-- Test transform logic for AND, OR, and NOT
-- Test transform logic for AND, OR, NOT and XOR
--
SELECT * FROM cypher('expr', $$
RETURN NOT false
@@ -582,6 +582,38 @@ $$) AS r(result boolean);
f
(1 row)

SELECT * FROM cypher('expr', $$
RETURN true XOR true
$$) AS r(result boolean);
result
--------
f
(1 row)

SELECT * FROM cypher('expr', $$
RETURN true XOR false
$$) AS r(result boolean);
result
--------
t
(1 row)

SELECT * FROM cypher('expr', $$
RETURN false XOR true
$$) AS r(result boolean);
result
--------
t
(1 row)

SELECT * FROM cypher('expr', $$
RETURN false XOR false
$$) AS r(result boolean);
result
--------
f
(1 row)

--
-- Test indirection transform logic for object.property, object["property"],
-- and array[element]
@@ -256,7 +256,7 @@ RETURN null IS NOT NULL
$$) AS r(result boolean);

--
-- Test transform logic for AND, OR, and NOT
-- Test transform logic for AND, OR, NOT and XOR
--

SELECT * FROM cypher('expr', $$
@@ -303,6 +303,22 @@ SELECT * FROM cypher('expr', $$
RETURN NOT ((true OR false) AND (false OR true))
$$) AS r(result boolean);

SELECT * FROM cypher('expr', $$
RETURN true XOR true
$$) AS r(result boolean);

SELECT * FROM cypher('expr', $$
RETURN true XOR false
$$) AS r(result boolean);

SELECT * FROM cypher('expr', $$
RETURN false XOR true
$$) AS r(result boolean);

SELECT * FROM cypher('expr', $$
RETURN false XOR false
$$) AS r(result boolean);

--
-- Test indirection transform logic for object.property, object["property"],
-- and array[element]
@@ -93,6 +93,7 @@
THEN TRUE_P
VERBOSE
WHEN WHERE WITH
XOR

/* query */
%type <list> single_query query_part_init query_part_last
@@ -148,6 +149,7 @@
/* precedence: lowest to highest */
%left OR
%left AND
%left XOR
%right NOT
%nonassoc '=' NOT_EQ '<' LT_EQ '>' GT_EQ
%left '+' '-'
@@ -164,6 +166,7 @@
// logical operators
static Node *make_or_expr(Node *lexpr, Node *rexpr, int location);
static Node *make_and_expr(Node *lexpr, Node *rexpr, int location);
static Node *make_xor_expr(Node *lexpr, Node *rexpr, int location);
static Node *make_not_expr(Node *expr, int location);

// arithmetic operators
@@ -1010,6 +1013,10 @@ expr:
{
$$ = make_and_expr($1, $3, @2);
}
| expr XOR expr
{
$$ = make_xor_expr($1, $3, @2);
}
| NOT expr
{
$$ = make_not_expr($2, @1);
@@ -1607,6 +1614,7 @@ safe_keywords:
| VERBOSE { $$ = pnstrdup($1, 7); }
| WHERE { $$ = pnstrdup($1, 5); }
| WITH { $$ = pnstrdup($1, 4); }
| XOR { $$ = pnstrdup($1, 3); }
;

conflicted_keywords:
@@ -1658,6 +1666,20 @@ static Node *make_and_expr(Node *lexpr, Node *rexpr, int location)
return (Node *)makeBoolExpr(AND_EXPR, list_make2(lexpr, rexpr), location);
}

static Node *make_xor_expr(Node *lexpr, Node *rexpr, int location)
{
Expr *aorb;
Expr *notaandb;

// XOR is (A OR B) AND (NOT (A AND B))
aorb = makeBoolExpr(OR_EXPR, list_make2(lexpr, rexpr), location);

notaandb = makeBoolExpr(AND_EXPR, list_make2(lexpr, rexpr), location);
notaandb = makeBoolExpr(NOT_EXPR, list_make1(notaandb), location);

return (Node *)makeBoolExpr(AND_EXPR, list_make2(aorb, notaandb), location);
}

static Node *make_not_expr(Node *expr, int location)
{
return (Node *)makeBoolExpr(NOT_EXPR, list_make1(expr), location);
@@ -73,7 +73,8 @@ const ScanKeyword cypher_keywords[] = {
{"verbose", VERBOSE, RESERVED_KEYWORD},
{"when", WHEN, RESERVED_KEYWORD},
{"where", WHERE, RESERVED_KEYWORD},
{"with", WITH, RESERVED_KEYWORD}
{"with", WITH, RESERVED_KEYWORD},
{"xor", XOR, RESERVED_KEYWORD}
};

const int num_cypher_keywords = lengthof(cypher_keywords);

0 comments on commit 163e064

Please sign in to comment.