From 290db00de341af7cc17861b4e08e54c34b51b9d4 Mon Sep 17 00:00:00 2001 From: Denis Smirnov <sd@picodata.io> Date: Fri, 16 Jun 2023 18:23:52 +0700 Subject: [PATCH] test: add hash calculation tests Check that picodata SQL uses `key_def` module from Tarantool to calculate the tuple hash. --- Cargo.lock | 2 +- sbroad | 2 +- test/conftest.py | 30 ++++++++++++++++++++++++++++++ test/int/test_sql.py | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f6ceb42f8f..d685ac69d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1376,7 +1376,7 @@ dependencies = [ "pest", "pest_derive", "rand", - "rmp-serde 0.14.4", + "rmp-serde 1.0.0", "sbroad-proc", "serde", "serde_yaml", diff --git a/sbroad b/sbroad index ccbd6c822c..aafa4f7af8 160000 --- a/sbroad +++ b/sbroad @@ -1 +1 @@ -Subproject commit ccbd6c822c83b52e2563bb96e4424b6e102674b6 +Subproject commit aafa4f7af83f14f0db175f92bf6e66d56f97abb3 diff --git a/test/conftest.py b/test/conftest.py index b8232f3399..7fb8f82824 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -186,6 +186,27 @@ def normalize_net_box_result(func): return inner +@dataclass +class KeyPart: + fieldno: int + type: str + is_nullable: bool = False + + def __str__(self): + return """{{ fieldno = {}, type = "{}", is_nullable = {} }}""".format( + self.fieldno, self.type, self.is_nullable + ) + + +@dataclass +class KeyDef: + parts: list[KeyPart] + + def __str__(self): + parts = ", ".join(str(part) for part in self.parts) + return """{{ {} }}""".format(parts) + + @dataclass(frozen=True) class RaftStatus: id: int @@ -480,6 +501,15 @@ class Instance: eprint(f"{self} killed") self.process = None + def hash(self, tup: tuple, key_def: KeyDef) -> int: + tup_str = "{{ {} }}".format(", ".join(str(x) for x in tup)) + lua = """ + return require("key_def").new({kd}):hash(box.tuple.new({t})) + """.format( + t=tup_str, kd=str(key_def) + ) + return self.eval(lua) + def sql(self, sql: str, *params, timeout: int | float = 1) -> dict: """Run SQL query and return result""" return self.call("pico.sql", sql, params, timeout=timeout) diff --git a/test/int/test_sql.py b/test/int/test_sql.py index f1cf7de021..54533c7d85 100644 --- a/test/int/test_sql.py +++ b/test/int/test_sql.py @@ -3,6 +3,8 @@ import re from conftest import ( Cluster, + KeyDef, + KeyPart, ReturnError, ) @@ -87,3 +89,35 @@ def test_select(cluster: Cluster): 2, ) assert data["rows"] == [[2, 2]] + + +def test_hash(cluster: Cluster): + cluster.deploy(instance_count=1) + i1 = cluster.instances[0] + + space_id = 777 + index = i1.propose_create_space( + dict( + id=space_id, + name="T", + format=[ + dict(name="A", type="integer", is_nullable=True), + ], + primary_key=[dict(field="A")], + # sharding function is implicitly murmur3 + distribution=dict(kind="sharded_implicitly", sharding_key=["A"]), + ) + ) + i1.raft_wait_index(index, 3) + + # Calculate tuple hash with Lua + tup = (1,) + key_def = KeyDef([KeyPart(1, "integer", True)]) + lua_hash = i1.hash(tup, key_def) + bucket_count = 3000 + + # Compare SQL and Lua bucket_id + data = i1.sql("""insert into t values(?);""", 1) + assert data["row_count"] == 1 + data = i1.sql(""" select "bucket_id" from t where a = ?""", 1) + assert data["rows"] == [[lua_hash % bucket_count]] -- GitLab