Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "tidesdb"
version = "0.7.0"
version = "0.8.0"
description = "Official Python bindings for TidesDB - A high-performance embedded key-value storage engine"
readme = "README.md"
requires-python = ">=3.10"
Expand Down
18 changes: 18 additions & 0 deletions src/tidesdb/tidesdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
c_int,
c_size_t,
c_uint8,
c_uint32,
c_uint64,
c_void_p,
)
Expand Down Expand Up @@ -194,6 +195,7 @@ class _CColumnFamilyConfig(Structure):
("min_disk_space", c_uint64),
("l1_file_count_trigger", c_int),
("l0_queue_stall_threshold", c_int),
("use_btree", c_int),
]


Expand Down Expand Up @@ -228,6 +230,10 @@ class _CStats(Structure):
("level_key_counts", POINTER(c_uint64)),
("read_amp", c_double),
("hit_rate", c_double),
("use_btree", c_int),
("btree_total_nodes", c_uint64),
("btree_max_height", c_uint32),
("btree_avg_height", c_double),
]


Expand Down Expand Up @@ -429,6 +435,7 @@ class ColumnFamilyConfig:
min_disk_space: int = 100 * 1024 * 1024
l1_file_count_trigger: int = 4
l0_queue_stall_threshold: int = 20
use_btree: bool = False

def _to_c_struct(self) -> _CColumnFamilyConfig:
"""Convert to C structure."""
Expand All @@ -452,6 +459,7 @@ def _to_c_struct(self) -> _CColumnFamilyConfig:
c_config.min_disk_space = self.min_disk_space
c_config.l1_file_count_trigger = self.l1_file_count_trigger
c_config.l0_queue_stall_threshold = self.l0_queue_stall_threshold
c_config.use_btree = 1 if self.use_btree else 0

name_bytes = self.comparator_name.encode("utf-8")[:TDB_MAX_COMPARATOR_NAME - 1]
name_bytes = name_bytes + b"\x00" * (TDB_MAX_COMPARATOR_NAME - len(name_bytes))
Expand All @@ -475,6 +483,10 @@ class Stats:
level_key_counts: list[int]
read_amp: float
hit_rate: float
use_btree: bool = False
btree_total_nodes: int = 0
btree_max_height: int = 0
btree_avg_height: float = 0.0
config: ColumnFamilyConfig | None = None


Expand Down Expand Up @@ -520,6 +532,7 @@ def default_column_family_config() -> ColumnFamilyConfig:
min_disk_space=c_config.min_disk_space,
l1_file_count_trigger=c_config.l1_file_count_trigger,
l0_queue_stall_threshold=c_config.l0_queue_stall_threshold,
use_btree=bool(c_config.use_btree),
)


Expand Down Expand Up @@ -760,6 +773,7 @@ def get_stats(self) -> Stats:
min_disk_space=c_cfg.min_disk_space,
l1_file_count_trigger=c_cfg.l1_file_count_trigger,
l0_queue_stall_threshold=c_cfg.l0_queue_stall_threshold,
use_btree=bool(c_cfg.use_btree),
)

stats = Stats(
Expand All @@ -774,6 +788,10 @@ def get_stats(self) -> Stats:
level_key_counts=level_key_counts,
read_amp=c_stats.read_amp,
hit_rate=c_stats.hit_rate,
use_btree=bool(c_stats.use_btree),
btree_total_nodes=c_stats.btree_total_nodes,
btree_max_height=c_stats.btree_max_height,
btree_avg_height=c_stats.btree_avg_height,
config=config,
)

Expand Down
37 changes: 37 additions & 0 deletions tests/test_tidesdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,27 @@ def test_create_with_config(self, db):

db.drop_column_family("custom_cf")

def test_create_with_btree_config(self, db):
"""Test creating column family with B+tree format enabled."""
config = tidesdb.default_column_family_config()
config.use_btree = True

db.create_column_family("btree_cf", config)
cf = db.get_column_family("btree_cf")
assert cf is not None

stats = cf.get_stats()
assert stats.config is not None
assert stats.config.use_btree is True
assert stats.use_btree is True

db.drop_column_family("btree_cf")

def test_default_config_use_btree(self, db):
"""Test that default config has use_btree=False."""
config = tidesdb.default_column_family_config()
assert config.use_btree is False

def test_list_column_families(self, db):
"""Test listing column families."""
db.create_column_family("cf1")
Expand Down Expand Up @@ -312,6 +333,22 @@ def test_column_family_stats(self, db, cf):
assert stats.num_levels >= 0
assert stats.memtable_size >= 0

def test_column_family_stats_btree_fields(self, db, cf):
"""Test that B+tree stats fields are present."""
with db.begin_txn() as txn:
txn.put(cf, b"key1", b"value1")
txn.commit()

stats = cf.get_stats()
# B+tree stats should be present (even if 0 for non-btree CF)
assert isinstance(stats.use_btree, bool)
assert isinstance(stats.btree_total_nodes, int)
assert isinstance(stats.btree_max_height, int)
assert isinstance(stats.btree_avg_height, float)
assert stats.btree_total_nodes >= 0
assert stats.btree_max_height >= 0
assert stats.btree_avg_height >= 0.0

def test_cache_stats(self, db):
"""Test getting cache statistics."""
stats = db.get_cache_stats()
Expand Down
Loading