fix: preserve duplicate take offsets

This commit is contained in:
Gatefixer
2026-08-21 22:50:46 +00:00
parent 29822306d2
commit 578253e892
6 changed files with 301 additions and 23 deletions
+6 -3
View File
@@ -1489,9 +1489,9 @@ class Table(ABC):
Offsets are mostly useful for sampling as the set of all valid offsets is easily
known in advance to be [0, len(table)).
No guarantees are made regarding the order in which results are returned. If
you desire an output order that matches the order of the given offsets, you will
need to add the row offset column to the output and align it yourself.
Results are returned in the same order as the given offsets. Repeated offsets
produce repeated rows, which makes this method suitable for sampling with
replacement.
Parameters
----------
@@ -6291,6 +6291,9 @@ class AsyncTable:
Offsets are mostly useful for sampling as the set of all valid offsets is easily
known in advance to be [0, len(table)).
Results are returned in the same order as the given offsets, including repeated
occurrences.
Parameters
----------
offsets: list[int]
+8
View File
@@ -1891,6 +1891,14 @@ def test_take_queries(tmp_path):
17,
]
# Duplicate offsets are occurrences, not set members, and preserve input order.
assert table.take_offsets([5, 2, 5, 17]).to_pandas()["idx"].to_list() == [
5,
2,
5,
17,
]
# Take by row id
assert list(
sorted(table.take_row_ids([5, 2, 17]).to_pandas()["idx"].to_list())
+30 -5
View File
@@ -480,24 +480,49 @@ def test_remote_permutation_is_picklable():
match = re.search(
r"_rowoffset\s+in\s+\((.*?)\)", body["filter"], re.IGNORECASE
)
offsets = [int(o.strip()) for o in match.group(1).split(",")]
offsets = list(
dict.fromkeys(int(o.strip()) for o in match.group(1).split(","))
)
else:
offsets = list(range(len(rows)))
table = pa.table({"a": [rows[offset] for offset in offsets]})
columns = body.get("columns") or ["a"]
table = pa.table(
{
column: (
[rows[offset] for offset in offsets]
if column == "a"
else offsets
)
for column in columns
}
)
request.send_response(200)
request.send_header("Content-Type", "application/vnd.apache.arrow.file")
request.end_headers()
with pa.ipc.new_file(request.wfile, schema=table.schema) as writer:
writer.write_table(table)
writer.write_table(table, max_chunksize=2)
else:
request.send_response(404)
request.end_headers()
with mock_lancedb_connection(handler) as db:
permutation = Permutation.identity(db.open_table("test"))
table = db.open_table("test")
assert table.take_offsets([0, 2, 0, 4]).to_list() == [
{"a": 0},
{"a": 2},
{"a": 0},
{"a": 4},
]
permutation = Permutation.identity(table)
restored = pickle.loads(pickle.dumps(permutation))
assert restored.__getitems__([0, 2, 4]) == [{"a": 0}, {"a": 2}, {"a": 4}]
assert restored.__getitems__([0, 2, 0, 4]) == [
{"a": 0},
{"a": 2},
{"a": 0},
{"a": 4},
]
def test_create_table_exist_ok():