You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by al...@apache.org on 2026/09/24 18:21:09 UTC

(asterixdb) branch master updated: [ASTERIXDB-3779][RT] Hash -0.0 the same as 0.0

This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/asterixdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 84dcc19ed2 [ASTERIXDB-3779][RT] Hash -0.0 the same as 0.0
84dcc19ed2 is described below

commit 84dcc19ed235463d68abdc27a47f0cbd2647ef78
Author: Ali Alsuliman <al...@gmail.com>
AuthorDate: Tue Sep 22 20:39:47 2026 -0700

    [ASTERIXDB-3779][RT] Hash -0.0 the same as 0.0
    
    - user model changes: no
    - storage format changes: no
    - interface changes: no
    
    Details: the comparators find -0.0 equal to 0.0, but the generic hash
    hashed a double by its bits, so every hash-based operator told the two
    apart. The hash-based OR missed matches, hash joins dropped pairs,
    grouping, DISTINCT and window partitions counted the zeros separately,
    and an upsert of -0.0 over a stored 0.0 key added a second record
    because the two keys were routed to different partitions.
    
    -0.0 is now hashed as 0.0, whether it arrives as a double or as a float
    promoted to one. Every other value hashes exactly as before, so the only
    stored records whose partition changes are those keyed on -0.0.
    
    Ext-ref: MB-72205
    Co-Authored-By: Claude Opus 5.5 <no...@anthropic.com>
    Change-Id: I02434aa90004008bd2e2c76cbf506597626190de
    Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/21307
    Tested-by: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Reviewed-by: Ali Alsuliman <al...@gmail.com>
---
 .../hash-based-or/hash-based-or.1.ddl.sqlpp        |  6 +++
 ....update.sqlpp => hash-based-or.16.update.sqlpp} | 49 ++++------------------
 ...or.1.ddl.sqlpp => hash-based-or.17.query.sqlpp} | 17 +++-----
 ...or.1.ddl.sqlpp => hash-based-or.18.query.sqlpp} | 17 +++-----
 ...or.1.ddl.sqlpp => hash-based-or.19.query.sqlpp} | 18 +++-----
 .../hash-based-or/hash-based-or.2.update.sqlpp     | 11 +++++
 ...or.1.ddl.sqlpp => hash-based-or.20.query.sqlpp} | 18 +++-----
 ...or.1.ddl.sqlpp => hash-based-or.21.query.sqlpp} | 18 +++-----
 ...or.1.ddl.sqlpp => hash-based-or.22.query.sqlpp} | 18 +++-----
 .../signed-zero-hash.01.ddl.sqlpp}                 | 22 +++++-----
 .../signed-zero-hash.02.update.sqlpp}              | 23 +++++-----
 .../signed-zero-hash.03.update.sqlpp}              | 17 ++------
 .../signed-zero-hash.04.query.sqlpp}               | 17 ++------
 .../signed-zero-hash.05.query.sqlpp}               | 20 +++------
 .../signed-zero-hash.06.query.sqlpp}               | 20 +++------
 .../signed-zero-hash.07.query.sqlpp}               | 17 ++------
 .../signed-zero-hash.08.query.sqlpp}               | 17 ++------
 .../signed-zero-hash.09.query.sqlpp}               | 18 ++------
 .../signed-zero-hash.10.query.sqlpp}               | 18 ++------
 .../signed-zero-hash.11.query.sqlpp}               | 18 ++------
 .../signed-zero-hash.12.query.sqlpp}               | 16 +------
 .../signed-zero-hash.13.query.sqlpp}               | 16 +------
 .../signed-zero-hash.14.query.sqlpp}               | 16 +------
 .../signed-zero-hash.15.query.sqlpp}               | 16 +------
 .../hash-based-or/hash-based-or.17.adm             |  4 ++
 .../hash-based-or/hash-based-or.18.adm             |  4 ++
 .../hash-based-or/hash-based-or.19.adm             |  6 +++
 .../hash-based-or/hash-based-or.20.adm             |  6 +++
 .../hash-based-or/hash-based-or.21.adm             |  6 +++
 .../hash-based-or/hash-based-or.22.adm             |  6 +++
 .../misc/signed-zero-hash/signed-zero-hash.04.adm  |  1 +
 .../misc/signed-zero-hash/signed-zero-hash.05.adm  |  2 +
 .../misc/signed-zero-hash/signed-zero-hash.06.adm  |  2 +
 .../misc/signed-zero-hash/signed-zero-hash.07.adm  |  1 +
 .../misc/signed-zero-hash/signed-zero-hash.08.adm  |  1 +
 .../misc/signed-zero-hash/signed-zero-hash.09.adm  |  1 +
 .../misc/signed-zero-hash/signed-zero-hash.10.adm  |  1 +
 .../misc/signed-zero-hash/signed-zero-hash.11.adm  |  6 +++
 .../misc/signed-zero-hash/signed-zero-hash.12.adm  |  1 +
 .../misc/signed-zero-hash/signed-zero-hash.13.adm  |  1 +
 .../misc/signed-zero-hash/signed-zero-hash.14.adm  |  1 +
 .../misc/signed-zero-hash/signed-zero-hash.15.adm  |  1 +
 .../src/test/resources/runtimets/sqlpp_queries.xml |  5 +++
 .../hash/AMurmurHash3BinaryHashFunctionFamily.java | 22 ++++++++--
 44 files changed, 195 insertions(+), 326 deletions(-)

diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
index 76b4edbc49..80a185822b 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
@@ -32,3 +32,9 @@ CREATE DATASET Employee(EmpType) PRIMARY KEY id;
 
 CREATE DATASET Employee2(EmpType) PRIMARY KEY id;
 
+CREATE TYPE ZeroType AS {
+  id : int
+};
+
+CREATE DATASET Zeros(ZeroType) PRIMARY KEY id;
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.16.update.sqlpp
similarity index 71%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.2.update.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.16.update.sqlpp
index e67768690c..6f61389c4f 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.16.update.sqlpp
@@ -19,14 +19,14 @@
 
 USE gby;
 
-INSERT INTO Employee (
+upsert INTO Employee (
   [
    { 'name': 'Bill',
       'id' : 2,
      'deptno': 'K55',
      'salary': 2000,
      'age':20,
-     'level':2,
+     'level':0.0,
       'salary':234 },
 
    { 'name': 'Fred',
@@ -34,62 +34,27 @@ INSERT INTO Employee (
       'id' : 12,
      'salary': 3000,
      'age':42,
-     'level':"2" },
+     'level':0 },
 
    { 'name': 'Fred2',
      'deptno': 'K15',
       'id' : 13,
      'salary': 2500,
      'age':23,
-     'level':"2" },
+     'level':-0.0 },
 
    { 'name': 'Fred1',
      'deptno': null,
       'id' : 31,
      'salary': 2500,
      'age':42,
-     'level':"2" },
+     'level':2 },
    { 'name': 'Fred11',
      'deptno': null,
      'id' : 33,
      'salary': null,
      'age':0,
-     'level':"2" }
+     'level':4 }
 
   ]
-);
-
-
-INSERT INTO Employee2 (
-  [
-   {
-     'id' : 2,
-     'age':20,
-     'level':2.2 },
-
-   {
-   'id' : 112,
-   'age':20,
-   'level':2.0 },
-    {
-      'id' : 12,
-      'age':20,
-      'level':2.1 },
-    {
-     'id' : 21,
-     'age':20,
-     'level':2 },
-     {
-      'id' : 22,
-      'age':20,
-      'level':"2" },
-      {
-       'id' : 24,
-       'age':20,
-        'level':null },
-        {
-        'id' : 25,
-         'age':20 }
-
-
-  ]);
\ No newline at end of file
+);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.17.query.sqlpp
similarity index 79%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.17.query.sqlpp
index 76b4edbc49..fc9b5e2e62 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.17.query.sqlpp
@@ -17,18 +17,13 @@
  * under the License.
  */
 
-DROP DATAVERSE gby IF EXISTS;
-CREATE DATAVERSE gby;
-
 USE gby;
 
-CREATE TYPE EmpType AS {
-  age : int,
-  id : int
-
-};
-
-CREATE DATASET Employee(EmpType) PRIMARY KEY id;
+SET `rewrite_or_as_join` "false";
+SET `compiler.disjunction.hash.threshold` "-1";
 
-CREATE DATASET Employee2(EmpType) PRIMARY KEY id;
 
+Select *
+FROM Employee e
+WHERE e.level=0.0 or e.level=2.0
+order by e.id;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.18.query.sqlpp
similarity index 79%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.18.query.sqlpp
index 76b4edbc49..5896c7817e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.18.query.sqlpp
@@ -17,18 +17,11 @@
  * under the License.
  */
 
-DROP DATAVERSE gby IF EXISTS;
-CREATE DATAVERSE gby;
-
 USE gby;
 
-CREATE TYPE EmpType AS {
-  age : int,
-  id : int
-
-};
-
-CREATE DATASET Employee(EmpType) PRIMARY KEY id;
-
-CREATE DATASET Employee2(EmpType) PRIMARY KEY id;
+SET `rewrite_or_as_join` "true";
 
+Select *
+FROM Employee e
+WHERE e.level=0.0 or e.level=2.0
+order by e.id;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.19.query.sqlpp
similarity index 79%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.19.query.sqlpp
index 76b4edbc49..3846d27066 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.19.query.sqlpp
@@ -17,18 +17,12 @@
  * under the License.
  */
 
-DROP DATAVERSE gby IF EXISTS;
-CREATE DATAVERSE gby;
-
 USE gby;
 
-CREATE TYPE EmpType AS {
-  age : int,
-  id : int
-
-};
-
-CREATE DATASET Employee(EmpType) PRIMARY KEY id;
-
-CREATE DATASET Employee2(EmpType) PRIMARY KEY id;
+SET `rewrite_or_as_join` "false";
+SET `compiler.disjunction.hash.threshold` "2";
 
+SELECT z.id, z.v
+FROM Zeros z
+WHERE z.v = 0.0 OR z.v = 2 OR z.v = 4
+ORDER BY z.id;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.2.update.sqlpp
index e67768690c..fe3d437cb5 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.2.update.sqlpp
@@ -92,4 +92,15 @@ INSERT INTO Employee2 (
          'age':20 }
 
 
+  ]);
+
+INSERT INTO Zeros (
+  [
+    { 'id': 1, 'v': 0.0 },
+    { 'id': 2, 'v': -0.0 },
+    { 'id': 3, 'v': float('0.0') },
+    { 'id': 4, 'v': float('-0.0') },
+    { 'id': 5, 'v': 0 },
+    { 'id': 6, 'v': 2 },
+    { 'id': 7, 'v': 0.5 }
   ]);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.20.query.sqlpp
similarity index 79%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.20.query.sqlpp
index 76b4edbc49..2ca64cf7bd 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.20.query.sqlpp
@@ -17,18 +17,12 @@
  * under the License.
  */
 
-DROP DATAVERSE gby IF EXISTS;
-CREATE DATAVERSE gby;
-
 USE gby;
 
-CREATE TYPE EmpType AS {
-  age : int,
-  id : int
-
-};
-
-CREATE DATASET Employee(EmpType) PRIMARY KEY id;
-
-CREATE DATASET Employee2(EmpType) PRIMARY KEY id;
+SET `rewrite_or_as_join` "false";
+SET `compiler.disjunction.hash.threshold` "2";
 
+SELECT z.id, z.v
+FROM Zeros z
+WHERE z.v = -0.0 OR z.v = 2 OR z.v = 4
+ORDER BY z.id;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.21.query.sqlpp
similarity index 79%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.21.query.sqlpp
index 76b4edbc49..455443ceaa 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.21.query.sqlpp
@@ -17,18 +17,12 @@
  * under the License.
  */
 
-DROP DATAVERSE gby IF EXISTS;
-CREATE DATAVERSE gby;
-
 USE gby;
 
-CREATE TYPE EmpType AS {
-  age : int,
-  id : int
-
-};
-
-CREATE DATASET Employee(EmpType) PRIMARY KEY id;
-
-CREATE DATASET Employee2(EmpType) PRIMARY KEY id;
+SET `rewrite_or_as_join` "false";
+SET `compiler.disjunction.hash.threshold` "2";
 
+SELECT z.id, z.v
+FROM Zeros z
+WHERE z.v = float('-0.0') OR z.v = 2 OR z.v = 4
+ORDER BY z.id;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.22.query.sqlpp
similarity index 79%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.22.query.sqlpp
index 76b4edbc49..be10f14ce4 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.22.query.sqlpp
@@ -17,18 +17,12 @@
  * under the License.
  */
 
-DROP DATAVERSE gby IF EXISTS;
-CREATE DATAVERSE gby;
-
 USE gby;
 
-CREATE TYPE EmpType AS {
-  age : int,
-  id : int
-
-};
-
-CREATE DATASET Employee(EmpType) PRIMARY KEY id;
-
-CREATE DATASET Employee2(EmpType) PRIMARY KEY id;
+SET `rewrite_or_as_join` "false";
+SET `compiler.disjunction.hash.threshold` "2";
 
+SELECT z.id, z.v
+FROM Zeros z
+WHERE z.v = 0 OR z.v = 2 OR z.v = 4
+ORDER BY z.id;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.01.ddl.sqlpp
similarity index 70%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.01.ddl.sqlpp
index 76b4edbc49..c8da6df630 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.01.ddl.sqlpp
@@ -17,18 +17,16 @@
  * under the License.
  */
 
-DROP DATAVERSE gby IF EXISTS;
-CREATE DATAVERSE gby;
-
-USE gby;
-
-CREATE TYPE EmpType AS {
-  age : int,
-  id : int
-
-};
+/*
+ * Description: -0.0 equals 0.0, so every hash-based operator must treat them as one value.
+ */
 
-CREATE DATASET Employee(EmpType) PRIMARY KEY id;
+DROP DATAVERSE test IF EXISTS;
+CREATE DATAVERSE test;
+USE test;
 
-CREATE DATASET Employee2(EmpType) PRIMARY KEY id;
+CREATE TYPE IdType AS { id: int };
+CREATE TYPE DoubleKeyType AS { k: double };
 
+CREATE DATASET Zeros(IdType) PRIMARY KEY id;
+CREATE DATASET DoubleKeys(DoubleKeyType) PRIMARY KEY k;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.02.update.sqlpp
similarity index 76%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.02.update.sqlpp
index 76b4edbc49..af962ae2e9 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.02.update.sqlpp
@@ -17,18 +17,15 @@
  * under the License.
  */
 
-DROP DATAVERSE gby IF EXISTS;
-CREATE DATAVERSE gby;
+USE test;
 
-USE gby;
-
-CREATE TYPE EmpType AS {
-  age : int,
-  id : int
-
-};
-
-CREATE DATASET Employee(EmpType) PRIMARY KEY id;
-
-CREATE DATASET Employee2(EmpType) PRIMARY KEY id;
+INSERT INTO Zeros ([
+  { 'id': 1, 'v': 0.0 },
+  { 'id': 2, 'v': -0.0 },
+  { 'id': 3, 'v': float('0.0') },
+  { 'id': 4, 'v': float('-0.0') },
+  { 'id': 5, 'v': 0 },
+  { 'id': 6, 'v': 2 }
+]);
 
+INSERT INTO DoubleKeys ({ 'k': 0.0, 'x': 1 });
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.03.update.sqlpp
similarity index 78%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.03.update.sqlpp
index 76b4edbc49..4c73e31e2c 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.03.update.sqlpp
@@ -17,18 +17,7 @@
  * under the License.
  */
 
-DROP DATAVERSE gby IF EXISTS;
-CREATE DATAVERSE gby;
-
-USE gby;
-
-CREATE TYPE EmpType AS {
-  age : int,
-  id : int
-
-};
-
-CREATE DATASET Employee(EmpType) PRIMARY KEY id;
-
-CREATE DATASET Employee2(EmpType) PRIMARY KEY id;
+/* -0.0 is the key already stored as 0.0, so this replaces that record */
+USE test;
 
+UPSERT INTO DoubleKeys ({ 'k': -0.0, 'x': 2 });
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.04.query.sqlpp
similarity index 78%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.04.query.sqlpp
index 76b4edbc49..9dba73ca15 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.04.query.sqlpp
@@ -17,18 +17,7 @@
  * under the License.
  */
 
-DROP DATAVERSE gby IF EXISTS;
-CREATE DATAVERSE gby;
-
-USE gby;
-
-CREATE TYPE EmpType AS {
-  age : int,
-  id : int
-
-};
-
-CREATE DATASET Employee(EmpType) PRIMARY KEY id;
-
-CREATE DATASET Employee2(EmpType) PRIMARY KEY id;
+USE test;
 
+SELECT VALUE d.x
+FROM DoubleKeys d;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.05.query.sqlpp
similarity index 78%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.05.query.sqlpp
index 76b4edbc49..81ca4c4a70 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.05.query.sqlpp
@@ -17,18 +17,10 @@
  * under the License.
  */
 
-DROP DATAVERSE gby IF EXISTS;
-CREATE DATAVERSE gby;
-
-USE gby;
-
-CREATE TYPE EmpType AS {
-  age : int,
-  id : int
-
-};
-
-CREATE DATASET Employee(EmpType) PRIMARY KEY id;
-
-CREATE DATASET Employee2(EmpType) PRIMARY KEY id;
+USE test;
 
+SELECT VALUE ids
+FROM Zeros z
+GROUP BY z.v /*+ hash */ GROUP AS g
+LET ids = (SELECT VALUE g.z.id FROM g ORDER BY g.z.id)
+ORDER BY ids[0];
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.06.query.sqlpp
similarity index 78%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.06.query.sqlpp
index 76b4edbc49..1094179a5e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.06.query.sqlpp
@@ -17,18 +17,10 @@
  * under the License.
  */
 
-DROP DATAVERSE gby IF EXISTS;
-CREATE DATAVERSE gby;
-
-USE gby;
-
-CREATE TYPE EmpType AS {
-  age : int,
-  id : int
-
-};
-
-CREATE DATASET Employee(EmpType) PRIMARY KEY id;
-
-CREATE DATASET Employee2(EmpType) PRIMARY KEY id;
+USE test;
 
+SELECT VALUE ids
+FROM Zeros z
+GROUP BY z.v GROUP AS g
+LET ids = (SELECT VALUE g.z.id FROM g ORDER BY g.z.id)
+ORDER BY ids[0];
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.07.query.sqlpp
similarity index 78%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.07.query.sqlpp
index 76b4edbc49..52549c80e1 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.07.query.sqlpp
@@ -17,18 +17,7 @@
  * under the License.
  */
 
-DROP DATAVERSE gby IF EXISTS;
-CREATE DATAVERSE gby;
-
-USE gby;
-
-CREATE TYPE EmpType AS {
-  age : int,
-  id : int
-
-};
-
-CREATE DATASET Employee(EmpType) PRIMARY KEY id;
-
-CREATE DATASET Employee2(EmpType) PRIMARY KEY id;
+USE test;
 
+SELECT VALUE COUNT(*)
+FROM (SELECT DISTINCT z.v FROM Zeros z) AS d;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.08.query.sqlpp
similarity index 78%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.08.query.sqlpp
index 76b4edbc49..05cc8de182 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.08.query.sqlpp
@@ -17,18 +17,9 @@
  * under the License.
  */
 
-DROP DATAVERSE gby IF EXISTS;
-CREATE DATAVERSE gby;
+USE test;
 
-USE gby;
-
-CREATE TYPE EmpType AS {
-  age : int,
-  id : int
-
-};
-
-CREATE DATASET Employee(EmpType) PRIMARY KEY id;
-
-CREATE DATASET Employee2(EmpType) PRIMARY KEY id;
+SET `compiler.aggregate.distinct.hash` "true";
 
+SELECT VALUE COUNT(DISTINCT z.v)
+FROM Zeros z;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.09.query.sqlpp
similarity index 78%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.09.query.sqlpp
index 76b4edbc49..c17d3670a8 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.09.query.sqlpp
@@ -17,18 +17,8 @@
  * under the License.
  */
 
-DROP DATAVERSE gby IF EXISTS;
-CREATE DATAVERSE gby;
-
-USE gby;
-
-CREATE TYPE EmpType AS {
-  age : int,
-  id : int
-
-};
-
-CREATE DATASET Employee(EmpType) PRIMARY KEY id;
-
-CREATE DATASET Employee2(EmpType) PRIMARY KEY id;
+USE test;
 
+SELECT VALUE COUNT(*)
+FROM Zeros a JOIN Zeros b ON a.v = b.v
+WHERE a.id <= 5 AND b.id <= 5;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.10.query.sqlpp
similarity index 78%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.10.query.sqlpp
index 76b4edbc49..9a6943ce45 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.10.query.sqlpp
@@ -17,18 +17,8 @@
  * under the License.
  */
 
-DROP DATAVERSE gby IF EXISTS;
-CREATE DATAVERSE gby;
-
-USE gby;
-
-CREATE TYPE EmpType AS {
-  age : int,
-  id : int
-
-};
-
-CREATE DATASET Employee(EmpType) PRIMARY KEY id;
-
-CREATE DATASET Employee2(EmpType) PRIMARY KEY id;
+USE test;
 
+SELECT VALUE COUNT(*)
+FROM Zeros a JOIN Zeros b ON a.v /*+ hash-bcast */ = b.v
+WHERE a.id <= 5 AND b.id <= 5;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.11.query.sqlpp
similarity index 78%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.11.query.sqlpp
index 76b4edbc49..08a2cad4d2 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.11.query.sqlpp
@@ -17,18 +17,8 @@
  * under the License.
  */
 
-DROP DATAVERSE gby IF EXISTS;
-CREATE DATAVERSE gby;
-
-USE gby;
-
-CREATE TYPE EmpType AS {
-  age : int,
-  id : int
-
-};
-
-CREATE DATASET Employee(EmpType) PRIMARY KEY id;
-
-CREATE DATASET Employee2(EmpType) PRIMARY KEY id;
+USE test;
 
+SELECT z.id, COUNT(*) OVER (PARTITION BY z.v) AS c
+FROM Zeros z
+ORDER BY z.id;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.12.query.sqlpp
similarity index 78%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.12.query.sqlpp
index 76b4edbc49..96fa98935b 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.12.query.sqlpp
@@ -17,18 +17,4 @@
  * under the License.
  */
 
-DROP DATAVERSE gby IF EXISTS;
-CREATE DATAVERSE gby;
-
-USE gby;
-
-CREATE TYPE EmpType AS {
-  age : int,
-  id : int
-
-};
-
-CREATE DATASET Employee(EmpType) PRIMARY KEY id;
-
-CREATE DATASET Employee2(EmpType) PRIMARY KEY id;
-
+SELECT VALUE array_intersect([0.0, 1], [-0.0, 2]);
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.13.query.sqlpp
similarity index 78%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.13.query.sqlpp
index 76b4edbc49..2d86966c6f 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.13.query.sqlpp
@@ -17,18 +17,4 @@
  * under the License.
  */
 
-DROP DATAVERSE gby IF EXISTS;
-CREATE DATAVERSE gby;
-
-USE gby;
-
-CREATE TYPE EmpType AS {
-  age : int,
-  id : int
-
-};
-
-CREATE DATASET Employee(EmpType) PRIMARY KEY id;
-
-CREATE DATASET Employee2(EmpType) PRIMARY KEY id;
-
+SELECT VALUE array_union([0.0], [-0.0]);
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.14.query.sqlpp
similarity index 78%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.14.query.sqlpp
index 76b4edbc49..52db213fb9 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.14.query.sqlpp
@@ -17,18 +17,4 @@
  * under the License.
  */
 
-DROP DATAVERSE gby IF EXISTS;
-CREATE DATAVERSE gby;
-
-USE gby;
-
-CREATE TYPE EmpType AS {
-  age : int,
-  id : int
-
-};
-
-CREATE DATASET Employee(EmpType) PRIMARY KEY id;
-
-CREATE DATASET Employee2(EmpType) PRIMARY KEY id;
-
+SELECT VALUE array_distinct([0.0, -0.0]);
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.15.query.sqlpp
similarity index 78%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.15.query.sqlpp
index 76b4edbc49..1a7cb32562 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/hash-based-or/hash-based-or/hash-based-or.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/signed-zero-hash/signed-zero-hash.15.query.sqlpp
@@ -17,18 +17,4 @@
  * under the License.
  */
 
-DROP DATAVERSE gby IF EXISTS;
-CREATE DATAVERSE gby;
-
-USE gby;
-
-CREATE TYPE EmpType AS {
-  age : int,
-  id : int
-
-};
-
-CREATE DATASET Employee(EmpType) PRIMARY KEY id;
-
-CREATE DATASET Employee2(EmpType) PRIMARY KEY id;
-
+SELECT VALUE array_symdiff([0.0, 1], [-0.0]);
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/hash-based-or/hash-based-or/hash-based-or.17.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/hash-based-or/hash-based-or/hash-based-or.17.adm
new file mode 100644
index 0000000000..1a7b8f776f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/hash-based-or/hash-based-or/hash-based-or.17.adm
@@ -0,0 +1,4 @@
+{ "e": { "age": 20, "id": 2, "name": "Bill", "deptno": "K55", "salary": 2000, "level": 0.0 } }
+{ "e": { "age": 42, "id": 12, "name": "Fred", "deptno": "K55", "salary": 3000, "level": 0 } }
+{ "e": { "age": 23, "id": 13, "name": "Fred2", "deptno": "K15", "salary": 2500, "level": -0.0 } }
+{ "e": { "age": 42, "id": 31, "name": "Fred1", "deptno": null, "salary": 2500, "level": 2 } }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/hash-based-or/hash-based-or/hash-based-or.18.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/hash-based-or/hash-based-or/hash-based-or.18.adm
new file mode 100644
index 0000000000..1a7b8f776f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/hash-based-or/hash-based-or/hash-based-or.18.adm
@@ -0,0 +1,4 @@
+{ "e": { "age": 20, "id": 2, "name": "Bill", "deptno": "K55", "salary": 2000, "level": 0.0 } }
+{ "e": { "age": 42, "id": 12, "name": "Fred", "deptno": "K55", "salary": 3000, "level": 0 } }
+{ "e": { "age": 23, "id": 13, "name": "Fred2", "deptno": "K15", "salary": 2500, "level": -0.0 } }
+{ "e": { "age": 42, "id": 31, "name": "Fred1", "deptno": null, "salary": 2500, "level": 2 } }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/hash-based-or/hash-based-or/hash-based-or.19.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/hash-based-or/hash-based-or/hash-based-or.19.adm
new file mode 100644
index 0000000000..33519991b6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/hash-based-or/hash-based-or/hash-based-or.19.adm
@@ -0,0 +1,6 @@
+{ "id": 1, "v": 0.0 }
+{ "id": 2, "v": -0.0 }
+{ "id": 3, "v": 0.0 }
+{ "id": 4, "v": -0.0 }
+{ "id": 5, "v": 0 }
+{ "id": 6, "v": 2 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/hash-based-or/hash-based-or/hash-based-or.20.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/hash-based-or/hash-based-or/hash-based-or.20.adm
new file mode 100644
index 0000000000..33519991b6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/hash-based-or/hash-based-or/hash-based-or.20.adm
@@ -0,0 +1,6 @@
+{ "id": 1, "v": 0.0 }
+{ "id": 2, "v": -0.0 }
+{ "id": 3, "v": 0.0 }
+{ "id": 4, "v": -0.0 }
+{ "id": 5, "v": 0 }
+{ "id": 6, "v": 2 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/hash-based-or/hash-based-or/hash-based-or.21.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/hash-based-or/hash-based-or/hash-based-or.21.adm
new file mode 100644
index 0000000000..33519991b6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/hash-based-or/hash-based-or/hash-based-or.21.adm
@@ -0,0 +1,6 @@
+{ "id": 1, "v": 0.0 }
+{ "id": 2, "v": -0.0 }
+{ "id": 3, "v": 0.0 }
+{ "id": 4, "v": -0.0 }
+{ "id": 5, "v": 0 }
+{ "id": 6, "v": 2 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/hash-based-or/hash-based-or/hash-based-or.22.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/hash-based-or/hash-based-or/hash-based-or.22.adm
new file mode 100644
index 0000000000..33519991b6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/hash-based-or/hash-based-or/hash-based-or.22.adm
@@ -0,0 +1,6 @@
+{ "id": 1, "v": 0.0 }
+{ "id": 2, "v": -0.0 }
+{ "id": 3, "v": 0.0 }
+{ "id": 4, "v": -0.0 }
+{ "id": 5, "v": 0 }
+{ "id": 6, "v": 2 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.04.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.04.adm
new file mode 100644
index 0000000000..0cfbf08886
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.04.adm
@@ -0,0 +1 @@
+2
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.05.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.05.adm
new file mode 100644
index 0000000000..81bdee5fa4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.05.adm
@@ -0,0 +1,2 @@
+[ 1, 2, 3, 4, 5 ]
+[ 6 ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.06.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.06.adm
new file mode 100644
index 0000000000..81bdee5fa4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.06.adm
@@ -0,0 +1,2 @@
+[ 1, 2, 3, 4, 5 ]
+[ 6 ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.07.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.07.adm
new file mode 100644
index 0000000000..0cfbf08886
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.07.adm
@@ -0,0 +1 @@
+2
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.08.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.08.adm
new file mode 100644
index 0000000000..0cfbf08886
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.08.adm
@@ -0,0 +1 @@
+2
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.09.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.09.adm
new file mode 100644
index 0000000000..7273c0fa8c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.09.adm
@@ -0,0 +1 @@
+25
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.10.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.10.adm
new file mode 100644
index 0000000000..7273c0fa8c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.10.adm
@@ -0,0 +1 @@
+25
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.11.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.11.adm
new file mode 100644
index 0000000000..2a9971832e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.11.adm
@@ -0,0 +1,6 @@
+{ "id": 1, "c": 5 }
+{ "id": 2, "c": 5 }
+{ "id": 3, "c": 5 }
+{ "id": 4, "c": 5 }
+{ "id": 5, "c": 5 }
+{ "id": 6, "c": 1 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.12.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.12.adm
new file mode 100644
index 0000000000..cef50a904b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.12.adm
@@ -0,0 +1 @@
+[ 0.0 ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.13.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.13.adm
new file mode 100644
index 0000000000..cef50a904b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.13.adm
@@ -0,0 +1 @@
+[ 0.0 ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.14.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.14.adm
new file mode 100644
index 0000000000..cef50a904b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.14.adm
@@ -0,0 +1 @@
+[ 0.0 ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.15.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.15.adm
new file mode 100644
index 0000000000..dd264421e9
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/signed-zero-hash/signed-zero-hash.15.adm
@@ -0,0 +1 @@
+[ 1 ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml b/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml
index fc3c976f1f..95b3baaee1 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml
@@ -7672,6 +7672,11 @@
         <output-dir compare="Text">query-ASTERIXDB-3418</output-dir>
       </compilation-unit>
     </test-case>
+    <test-case FilePath="misc">
+      <compilation-unit name="signed-zero-hash">
+        <output-dir compare="Text">signed-zero-hash</output-dir>
+      </compilation-unit>
+    </test-case>
     <test-case FilePath="misc">
       <compilation-unit name="query-ASTERIXDB-3403">
         <output-dir compare="Text">query-ASTERIXDB-3403</output-dir>
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/hash/AMurmurHash3BinaryHashFunctionFamily.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/hash/AMurmurHash3BinaryHashFunctionFamily.java
index caab273b00..c7b95effdf 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/hash/AMurmurHash3BinaryHashFunctionFamily.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/hash/AMurmurHash3BinaryHashFunctionFamily.java
@@ -26,6 +26,7 @@ import java.io.DataOutput;
 import java.io.IOException;
 
 import org.apache.asterix.dataflow.data.common.ListAccessorUtil;
+import org.apache.asterix.dataflow.data.nontagged.serde.ADoubleSerializerDeserializer;
 import org.apache.asterix.dataflow.data.nontagged.serde.AOrderedListSerializerDeserializer;
 import org.apache.asterix.om.pointables.nonvisitor.RecordField;
 import org.apache.asterix.om.pointables.nonvisitor.SortedRecord;
@@ -76,6 +77,10 @@ public class AMurmurHash3BinaryHashFunctionFamily implements IBinaryHashFunction
 
     private static final class GenericHashFunction implements IBinaryHashFunction {
 
+        private static final long NEGATIVE_ZERO_BITS = Double.doubleToRawLongBits(-0.0d);
+        private static final byte[] POSITIVE_ZERO =
+                new byte[] { ATypeTag.SERIALIZED_DOUBLE_TYPE_TAG, 0, 0, 0, 0, 0, 0, 0, 0 };
+
         private final ArrayBackedValueStorage valueBuffer = new ArrayBackedValueStorage();
         private final DataOutput valueOut = valueBuffer.getDataOutput();
         private final IObjectPool<IPointable, Void> voidPointableAllocator = new ListObjectPool<>(VOID_FACTORY);
@@ -119,8 +124,10 @@ public class AMurmurHash3BinaryHashFunctionFamily implements IBinaryHashFunction
                     } catch (IOException e) {
                         throw HyracksDataException.create(ErrorCode.NUMERIC_PROMOTION_ERROR, e.getMessage());
                     }
-                    return MurmurHash3BinaryHash.hash(valueBuffer.getByteArray(), valueBuffer.getStartOffset(),
-                            valueBuffer.getLength(), seed);
+                    return hashDouble(valueBuffer.getByteArray(), valueBuffer.getStartOffset(),
+                            valueBuffer.getLength());
+                case DOUBLE:
+                    return hashDouble(bytes, offset, length);
                 case ARRAY:
                     try {
                         return hashArray(type, bytes, offset);
@@ -129,12 +136,21 @@ public class AMurmurHash3BinaryHashFunctionFamily implements IBinaryHashFunction
                     }
                 case OBJECT:
                     return hashRecord(type, bytes, offset);
-                case DOUBLE:
                 default:
                     return MurmurHash3BinaryHash.hash(bytes, offset, length, seed);
             }
         }
 
+        /**
+         * Comparators find -0.0 equal to 0.0, so it must hash as 0.0 rather than by its own bits.
+         */
+        private int hashDouble(byte[] bytes, int offset, int length) {
+            if (ADoubleSerializerDeserializer.getLongBits(bytes, offset + 1) == NEGATIVE_ZERO_BITS) {
+                return MurmurHash3BinaryHash.hash(POSITIVE_ZERO, 0, POSITIVE_ZERO.length, seed);
+            }
+            return MurmurHash3BinaryHash.hash(bytes, offset, length, seed);
+        }
+
         private int hashArray(IAType type, byte[] bytes, int offset) throws IOException {
             IAType arrayType = TypeComputeUtils.getActualTypeOrOpen(type, ATypeTag.ARRAY);
             IAType itemType = ((AbstractCollectionType) arrayType).getItemType();