Skip to content

Commit fb56490

Browse files
committed
make sure all 3 backends hash the same
1 parent 0127fac commit fb56490

7 files changed

Lines changed: 68 additions & 28 deletions

File tree

meta/src/meta/templates/parser.jl.template

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,9 @@ end
228228
function relation_id_from_string(parser::ParserState, name::String)
229229
# Create RelationId from string and track mapping for debug info
230230
hash_bytes = sha256(name)
231-
# Match the convention in backir-to-lqp.jl
232-
id_low = reinterpret(UInt64, hash_bytes[1:8])[1]
233-
id_high = reinterpret(UInt64, hash_bytes[9:16])[1]
231+
# Use little-endian to match the Go and Python SDKs.
232+
id_low = htol(reinterpret(UInt64, hash_bytes[1:8])[1])
233+
id_high = htol(reinterpret(UInt64, hash_bytes[9:16])[1])
234234
relation_id = Proto.RelationId(id_low, id_high)
235235

236236
# Store the mapping for the current fragment if we're inside one

sdks/go/src/hash_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package lqp
2+
3+
import "testing"
4+
5+
// TestRelationIdFromString verifies that relation_id_from_string produces
6+
// the same id across all SDKs (Julia, Python, Go).
7+
func TestRelationIdFromString(t *testing.T) {
8+
p := NewParser([]Token{})
9+
rid := p.relationIdFromString("my_relation")
10+
if rid.IdLow != 0x5d33996702404f85 {
11+
t.Errorf("id_low: got 0x%016x, want 0x5d33996702404f85", rid.IdLow)
12+
}
13+
if rid.IdHigh != 0x3b9af8e72af633f8 {
14+
t.Errorf("id_high: got 0x%016x, want 0x3b9af8e72af633f8", rid.IdHigh)
15+
}
16+
}

sdks/julia/LogicalQueryProtocol.jl/src/parser.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -254,9 +254,9 @@ end
254254
function relation_id_from_string(parser::ParserState, name::String)
255255
# Create RelationId from string and track mapping for debug info
256256
hash_bytes = sha256(name)
257-
# Match the convention in backir-to-lqp.jl
258-
id_low = reinterpret(UInt64, hash_bytes[1:8])[1]
259-
id_high = reinterpret(UInt64, hash_bytes[9:16])[1]
257+
# Use little-endian to match the Go and Python SDKs.
258+
id_low = htol(reinterpret(UInt64, hash_bytes[1:8])[1])
259+
id_high = htol(reinterpret(UInt64, hash_bytes[9:16])[1])
260260
relation_id = Proto.RelationId(id_low, id_high)
261261

262262
# Store the mapping for the current fragment if we're inside one

sdks/julia/LogicalQueryProtocol.jl/test/parser_tests.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,16 @@ end
112112
@test r.scale == 1
113113
end
114114

115+
@testitem "Parser - relation_id_from_string" setup=[ParserSetup] begin
116+
using LogicalQueryProtocol.Parser: ParserState, Token, relation_id_from_string
117+
118+
# All SDKs must produce the same id for the same string.
119+
parser = ParserState(Token[])
120+
rid = relation_id_from_string(parser, "my_relation")
121+
@test rid.id_low == 0x5d33996702404f85
122+
@test rid.id_high == 0x3b9af8e72af633f8
123+
end
124+
115125
@testitem "Parser - Lexer tokenization" setup=[ParserSetup] begin
116126
lexer = Lexer("(transaction (epoch (writes) (reads)))")
117127
# Tokens: ( transaction ( epoch ( writes ) ( reads ) ) ) $

sdks/python/tests/test_parser.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,19 @@
33
import pytest
44
from pytest_snapshot.plugin import Snapshot
55

6-
from lqp.gen.parser import parse
6+
from lqp.gen.parser import Parser, parse
77

88
from .utils import BIN_SNAPSHOTS_DIR, get_lqp_input_files
99

1010

11+
def test_relation_id_from_string():
12+
"""All SDKs must produce the same id for the same string."""
13+
parser = Parser([])
14+
rid = parser.relation_id_from_string("my_relation")
15+
assert rid.id_low == 0x5D33996702404F85
16+
assert rid.id_high == 0x3B9AF8E72AF633F8
17+
18+
1119
@pytest.mark.parametrize("input_file", get_lqp_input_files())
1220
def test_parse_lqp(snapshot: Snapshot, input_file):
1321
"""Test that each input file can be parsed and matches its binary snapshot."""

tests/bin/cdc.bin

189 Bytes
Binary file not shown.

tests/pretty_debug/cdc.lqp

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,30 +19,36 @@
1919
:csv_skip 0})
2020
(columns
2121
(column "raw_data" [])
22-
(column ["append" "METADATA$KEY"] 0xb7219c9b1f7d843d [UINT128])
23-
(column ["delete" "METADATA$KEY"] 0xc45b4cf618eed32f [UINT128])
24-
(column ["append" "user_id"] 0x7982cff88800e869 [INT])
25-
(column ["append" "name"] 0x8cb6c4889f2f67c7 [STRING])
26-
(column "id" 0x5364bf081a053f95 [INT])
27-
(column ["append" "id"] 0x22d32663113e8a7d [INT])
28-
(column ["delete" "id"] 0x337b9038b6bf2f6a [INT]))
22+
(column
23+
["append" "METADATA$KEY"]
24+
0x8dfeb4bd8f6d8c353d847d1f9b9c21b7
25+
[UINT128])
26+
(column
27+
["delete" "METADATA$KEY"]
28+
0xa91fbfb76393ae562fd3ee18f64c5bc4
29+
[UINT128])
30+
(column ["append" "user_id"] 0xf68f290595d54fb669e80088f8cf8279 [INT])
31+
(column ["append" "name"] 0x2756fdf898b5a25ac7672f9f88c4b68c [STRING])
32+
(column "id" 0xc0c8b0135d8dee07953f051a08bf6453 [INT])
33+
(column ["append" "id"] 0xd21b8166f6243157d8a3e116326d322 [INT])
34+
(column ["delete" "id"] 0xe870ce327bf8f16e6a2fbfb638907b33 [INT]))
2935
(asof "2025-06-01T00:00:00Z")))))
3036
(reads
31-
(output :mk_ins 0xb7219c9b1f7d843d)
32-
(output :mk_del 0xc45b4cf618eed32f)
33-
(output :uid_ins 0x7982cff88800e869)
34-
(output :name_ins 0x8cb6c4889f2f67c7)
35-
(output :entity_id 0x5364bf081a053f95)
36-
(output :eid_ins 0x22d32663113e8a7d)
37-
(output :eid_del 0x337b9038b6bf2f6a))))
37+
(output :mk_ins 0x8dfeb4bd8f6d8c353d847d1f9b9c21b7)
38+
(output :mk_del 0xa91fbfb76393ae562fd3ee18f64c5bc4)
39+
(output :uid_ins 0xf68f290595d54fb669e80088f8cf8279)
40+
(output :name_ins 0x2756fdf898b5a25ac7672f9f88c4b68c)
41+
(output :entity_id 0xc0c8b0135d8dee07953f051a08bf6453)
42+
(output :eid_ins 0xd21b8166f6243157d8a3e116326d322)
43+
(output :eid_del 0xe870ce327bf8f16e6a2fbfb638907b33))))
3844

3945
;; Debug information
4046
;; -----------------------
4147
;; Original names
42-
;; ID `0x337b9038b6bf2f6a` -> `eid_del`
43-
;; ID `0x22d32663113e8a7d` -> `eid_ins`
44-
;; ID `0x5364bf081a053f95` -> `entity_id`
45-
;; ID `0xc45b4cf618eed32f` -> `mk_del`
46-
;; ID `0xb7219c9b1f7d843d` -> `mk_ins`
47-
;; ID `0x8cb6c4889f2f67c7` -> `name_ins`
48-
;; ID `0x7982cff88800e869` -> `uid_ins`
48+
;; ID `0xe870ce327bf8f16e6a2fbfb638907b33` -> `eid_del`
49+
;; ID `0xd21b8166f6243157d8a3e116326d322` -> `eid_ins`
50+
;; ID `0xc0c8b0135d8dee07953f051a08bf6453` -> `entity_id`
51+
;; ID `0xa91fbfb76393ae562fd3ee18f64c5bc4` -> `mk_del`
52+
;; ID `0x8dfeb4bd8f6d8c353d847d1f9b9c21b7` -> `mk_ins`
53+
;; ID `0x2756fdf898b5a25ac7672f9f88c4b68c` -> `name_ins`
54+
;; ID `0xf68f290595d54fb669e80088f8cf8279` -> `uid_ins`

0 commit comments

Comments
 (0)