Skip to content

Commit 5194dcd

Browse files
committed
chore(release): bump version to 2.1.1 and update changelog
* Moved table name validation to create_table method * Improved client initialization flexibility * Added tests for table name validation during table creation * Enhanced SQL injection prevention tests
1 parent 48deafc commit 5194dcd

File tree

6 files changed

+70
-14
lines changed

6 files changed

+70
-14
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [2.1.1] - 2025-01-31
9+
10+
### Changed
11+
- Moved table name validation from `__init__()` to `create_table()` method
12+
- Table name is now validated when creating the table schema, not during client initialization
13+
14+
### Improved
15+
- More flexible client initialization - validation happens at table creation time
16+
817
## [2.1.0] - 2025-01-31
918

1019
### Added

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "sqlite-vec-client"
7-
version = "2.1.0"
7+
version = "2.1.1"
88
description = "A tiny Python client around sqlite-vec for CRUD and similarity search."
99
readme = "README.md"
1010
requires-python = ">=3.9"

sqlite_vec_client/base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,9 @@ def __init__(
105105
pool: Optional connection pool for connection reuse
106106
107107
Raises:
108-
TableNameError: If table name is invalid
109108
VecConnectionError: If connection fails
110109
ValueError: If both db_path and pool are None
111110
"""
112-
validate_table_name(table)
113111
self.table = table
114112
self._in_transaction = False
115113
self._pool = pool
@@ -148,8 +146,10 @@ def create_table(
148146
distance: Distance metric for similarity search
149147
150148
Raises:
149+
TableNameError: If table name is invalid
151150
ValidationError: If dimension is invalid
152151
"""
152+
validate_table_name(self.table)
153153
validate_dimension(dim)
154154
logger.info(
155155
f"Creating table '{self.table}' with dim={dim}, distance={distance}"

tests/test_client.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,12 @@
1414
class TestClientInitialization:
1515
"""Tests for client initialization."""
1616

17-
def test_init_with_valid_table_name(self, temp_db):
18-
"""Test initialization with valid table name."""
17+
def test_init_with_table_name(self, temp_db):
18+
"""Test initialization with table name."""
1919
client = SQLiteVecClient(table="valid_table", db_path=temp_db)
2020
assert client.table == "valid_table"
2121
client.close()
2222

23-
def test_init_with_invalid_table_name(self, temp_db):
24-
"""Test initialization with invalid table name raises error."""
25-
with pytest.raises(TableNameError):
26-
SQLiteVecClient(table="invalid-table", db_path=temp_db)
27-
2823

2924
@pytest.mark.integration
3025
class TestCreateTable:
@@ -45,6 +40,13 @@ def test_create_table_invalid_dimension(self, client):
4540
with pytest.raises(ValidationError):
4641
client.create_table(dim=0)
4742

43+
def test_create_table_validates_table_name(self, temp_db):
44+
"""Test that create_table validates table name."""
45+
client = SQLiteVecClient(table="invalid-table", db_path=temp_db)
46+
with pytest.raises(TableNameError):
47+
client.create_table(dim=3)
48+
client.close()
49+
4850

4951
@pytest.mark.integration
5052
class TestAddRecords:

tests/test_security.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,26 @@ def test_table_name_with_sql_injection(self, temp_db):
2424
"table;DELETE FROM data",
2525
]
2626
for name in malicious_names:
27+
client = SQLiteVecClient(table=name, db_path=temp_db)
2728
with pytest.raises(TableNameError):
28-
SQLiteVecClient(table=name, db_path=temp_db)
29+
client.create_table(dim=3)
30+
client.close()
2931

3032
def test_table_name_with_special_chars(self, temp_db):
3133
"""Test that special characters in table names are rejected."""
3234
invalid_names = ["table-name", "table.name", "table name", "table@name"]
3335
for name in invalid_names:
36+
client = SQLiteVecClient(table=name, db_path=temp_db)
3437
with pytest.raises(TableNameError):
35-
SQLiteVecClient(table=name, db_path=temp_db)
38+
client.create_table(dim=3)
39+
client.close()
3640

3741
def test_table_name_starting_with_number(self, temp_db):
3842
"""Test that table names starting with numbers are rejected."""
43+
client = SQLiteVecClient(table="123table", db_path=temp_db)
3944
with pytest.raises(TableNameError):
40-
SQLiteVecClient(table="123table", db_path=temp_db)
45+
client.create_table(dim=3)
46+
client.close()
4147

4248

4349
@pytest.mark.unit
@@ -105,8 +111,10 @@ class TestTableNameValidation:
105111

106112
def test_empty_table_name(self, temp_db):
107113
"""Test that empty table name is rejected."""
114+
client = SQLiteVecClient(table="", db_path=temp_db)
108115
with pytest.raises(TableNameError, match="cannot be empty"):
109-
SQLiteVecClient(table="", db_path=temp_db)
116+
client.create_table(dim=3)
117+
client.close()
110118

111119
def test_valid_table_names(self, temp_db):
112120
"""Test that valid table names are accepted."""

tests/test_validation.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,43 @@ def test_starts_with_number(self):
4545
with pytest.raises(TableNameError):
4646
validate_table_name("123table")
4747

48+
def test_sql_injection_attempts(self):
49+
"""Test that SQL injection attempts are rejected."""
50+
injection_attempts = [
51+
"table'; DROP TABLE users--",
52+
"table OR 1=1",
53+
"table; DELETE FROM data",
54+
"table/*comment*/",
55+
]
56+
for name in injection_attempts:
57+
with pytest.raises(TableNameError):
58+
validate_table_name(name)
59+
60+
61+
@pytest.mark.unit
62+
class TestValidateTableNameInCreateTable:
63+
"""Tests for table name validation in create_table method."""
64+
65+
def test_create_table_with_invalid_name(self, tmp_path):
66+
"""Test that create_table validates table name."""
67+
from sqlite_vec_client import SQLiteVecClient
68+
69+
db_path = str(tmp_path / "test.db")
70+
client = SQLiteVecClient(table="invalid-table", db_path=db_path)
71+
with pytest.raises(TableNameError):
72+
client.create_table(dim=3)
73+
client.close()
74+
75+
def test_create_table_with_valid_name(self, tmp_path):
76+
"""Test that create_table accepts valid table name."""
77+
from sqlite_vec_client import SQLiteVecClient
78+
79+
db_path = str(tmp_path / "test.db")
80+
client = SQLiteVecClient(table="valid_table", db_path=db_path)
81+
client.create_table(dim=3)
82+
assert client.count() == 0
83+
client.close()
84+
4885

4986
@pytest.mark.unit
5087
class TestValidateDimension:

0 commit comments

Comments
 (0)