fix hstore_hash() - now it uses correct hashing for numeric value
authorTeodor Sigaev <[email protected]>
Thu, 6 Mar 2014 12:23:57 +0000 (16:23 +0400)
committerTeodor Sigaev <[email protected]>
Thu, 6 Mar 2014 12:23:57 +0000 (16:23 +0400)
contrib/hstore/expected/hstore.out
contrib/hstore/hstore_op.c

index 6e96ff2a19b202e5b6b9929889d53a2e5007f503..82d0d8f6865e136e4ae75b509b065aba6b4a84a8 100644 (file)
@@ -1502,7 +1502,7 @@ set enable_sort = false;
 select count(*) from (select h from (select * from testhstore union all select * from testhstore) hs group by h) hs2;
  count 
 -------
-   887
+   886
 (1 row)
 
 select distinct * from (values (hstore '' || ''),('')) v(h);
index 1b00c966294229ecd087a3784e0b2ae21d352204..08e91ba3a6f0304ecd94995010a64e113ab8d2bc 100644 (file)
@@ -9,6 +9,7 @@
 #include "funcapi.h"
 #include "utils/builtins.h"
 #include "utils/memutils.h"
+#include "utils/pg_crc.h"
 
 #include "hstore.h"
 
@@ -3018,12 +3019,70 @@ Datum       hstore_hash(PG_FUNCTION_ARGS);
 Datum
 hstore_hash(PG_FUNCTION_ARGS)
 {
-   HStore     *hs = PG_GETARG_HS(0);
-   Datum       hval = hash_any((unsigned char *) VARDATA(hs),
-                               VARSIZE(hs) - VARHDRSZ);
+   HStore          *hs = PG_GETARG_HS(0);
+   HStoreIterator  *it;
+   int32           r;
+   HStoreValue     v;
+   int             crc;
+
+   if (HS_ROOT_COUNT(hs) == 0)
+       PG_RETURN_INT32(0x1EEE);
+
+   it = HStoreIteratorInit(VARDATA(hs));
+   INIT_CRC32(crc);
+
+   while((r = HStoreIteratorGet(&it, &v, false)) != 0)
+   {
+       switch(r)
+       {
+           case WHS_BEGIN_ARRAY:
+               COMP_CRC32(crc, "ab", 3);
+               COMP_CRC32(crc, &v.array.nelems, sizeof(v.array.nelems));
+               COMP_CRC32(crc, &v.array.scalar, sizeof(v.array.scalar));
+               break;
+           case WHS_BEGIN_HASH:
+               COMP_CRC32(crc, "hb", 3);
+               COMP_CRC32(crc, &v.hash.npairs, sizeof(v.hash.npairs));
+               break;
+           case WHS_KEY:
+               COMP_CRC32(crc, "k", 2);
+           case WHS_VALUE:
+           case WHS_ELEM:
+               switch(v.type)
+               {
+                   case hsvString:
+                       COMP_CRC32(crc, v.string.val, v.string.len);
+                       break;
+                   case hsvNull:
+                       COMP_CRC32(crc, "N", 2);
+                       break;
+                   case hsvBool:
+                       COMP_CRC32(crc, &v.boolean, sizeof(v.boolean));
+                       break;
+                   case hsvNumeric:
+                       crc ^= DatumGetInt32(DirectFunctionCall1(hash_numeric,
+                                            NumericGetDatum(v.numeric)));
+                       break;
+                   default:
+                       elog(ERROR, "unexpected state of hstore iterator");
+               }
+
+               break;
+           case WHS_END_ARRAY:
+               COMP_CRC32(crc, "ae", 3);
+               break;
+           case WHS_END_HASH:
+               COMP_CRC32(crc, "he", 3);
+               break;
+           default:
+               elog(ERROR, "unexpected state of hstore iterator");
+       }
+   }
+
+   FIN_CRC32(crc);
 
    PG_FREE_IF_COPY(hs, 0);
-   PG_RETURN_DATUM(hval);
+   PG_RETURN_INT32(crc);
 }
 
 PG_FUNCTION_INFO_V1(hstore_typeof);