commitdb 2.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,277 @@
1
+ Metadata-Version: 2.4
2
+ Name: commitdb
3
+ Version: 2.2.1
4
+ Summary: Python driver for CommitDB SQL Server
5
+ Author: CommitDB Contributors
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/nickyhof/CommitDB
8
+ Project-URL: Documentation, https://github.com/nickyhof/CommitDB#readme
9
+ Project-URL: Repository, https://github.com/nickyhof/CommitDB
10
+ Keywords: database,sql,git,commitdb
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: Apache Software License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ Provides-Extra: dev
21
+ Requires-Dist: pytest>=7.0; extra == "dev"
22
+ Provides-Extra: ibis
23
+ Requires-Dist: ibis-framework>=9.0; extra == "ibis"
24
+ Requires-Dist: pandas>=2.0; extra == "ibis"
25
+
26
+ # CommitDB Python Driver
27
+
28
+ [![PyPI version](https://badge.fury.io/py/commitdb.svg)](https://badge.fury.io/py/commitdb)
29
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
30
+
31
+ Python client for CommitDB - a Git-backed SQL database engine.
32
+
33
+ **[📚 Full Documentation](https://nickyhof.github.io/CommitDB/python-driver/)**
34
+
35
+ > ⚠️ **Experimental Project** - This is a hobby project and should not be used in any production environment.
36
+
37
+ ## Installation
38
+
39
+ ```bash
40
+ pip install commitdb
41
+ ```
42
+
43
+ ## Quick Start
44
+
45
+ ### Remote Mode (connect to server)
46
+
47
+ ```python
48
+ from commitdb import CommitDB
49
+
50
+ with CommitDB('localhost', 3306) as db:
51
+ db.execute('CREATE DATABASE mydb')
52
+ db.execute('CREATE TABLE mydb.users (id INT PRIMARY KEY, name STRING)')
53
+ db.execute("INSERT INTO mydb.users VALUES (1, 'Alice')")
54
+
55
+ result = db.query('SELECT * FROM mydb.users')
56
+ for row in result:
57
+ print(f"{row['id']}: {row['name']}")
58
+ ```
59
+
60
+ ### Embedded Mode (no server required)
61
+
62
+ ```python
63
+ from commitdb import CommitDBLocal
64
+
65
+ with CommitDBLocal() as db: # In-memory
66
+ db.execute('CREATE DATABASE mydb')
67
+ db.execute('CREATE TABLE mydb.users (id INT PRIMARY KEY, name STRING)')
68
+
69
+ with CommitDBLocal('/path/to/data') as db: # File-based (persistent)
70
+ db.execute('CREATE DATABASE mydb')
71
+ ```
72
+
73
+ ### Ibis Mode (pandas DataFrame support)
74
+
75
+ ```bash
76
+ pip install commitdb[ibis]
77
+ ```
78
+
79
+ ```python
80
+ import ibis
81
+
82
+ con = ibis.commitdb.connect('localhost', 3306, database='mydb')
83
+
84
+ # Or use URL-based connection:
85
+ con = ibis.connect('commitdb://localhost:3306/mydb')
86
+
87
+ # Query with Ibis expressions
88
+ users = con.table('users')
89
+ result = users.filter(users.age > 30).select('name', 'city').execute() # → pandas DataFrame
90
+ print(result)
91
+
92
+ # Insert from DataFrame
93
+ import pandas as pd
94
+ df = pd.DataFrame({'id': [1, 2], 'name': ['Alice', 'Bob']})
95
+ con.insert('users', df)
96
+ ```
97
+
98
+ ---
99
+
100
+ ## API Reference
101
+
102
+ ### CommitDB (Remote)
103
+
104
+ ```python
105
+ CommitDB(host='localhost', port=3306, use_ssl=False, ssl_verify=True,
106
+ ssl_ca_cert=None, jwt_token=None)
107
+ ```
108
+
109
+ | Method | Description |
110
+ |--------|-------------|
111
+ | `connect(timeout=10.0)` | Connect to server |
112
+ | `close()` | Close connection |
113
+ | `execute(sql)` | Execute SQL (INSERT, UPDATE, CREATE, etc.) |
114
+ | `query(sql)` | Execute SELECT, returns QueryResult |
115
+ | `authenticate_jwt(token)` | Authenticate with JWT |
116
+
117
+ ### CommitDBLocal (Embedded)
118
+
119
+ ```python
120
+ CommitDBLocal(path=None, lib_path=None)
121
+ ```
122
+
123
+ - `path` - Directory for persistence (`None` = in-memory)
124
+ - `lib_path` - Path to `libcommitdb` shared library
125
+
126
+ | Method | Description |
127
+ |--------|-------------|
128
+ | `open()` / `close()` | Open/close database |
129
+ | `execute(sql)` | Execute SQL |
130
+ | `query(sql)` | Execute SELECT |
131
+
132
+ ### QueryResult
133
+
134
+ ```python
135
+ result = db.query('SELECT * FROM mydb.users')
136
+ result.columns # ['id', 'name']
137
+ len(result) # Row count
138
+ result[0] # {'id': '1', 'name': 'Alice'}
139
+
140
+ for row in result:
141
+ print(row)
142
+ ```
143
+
144
+ ### Error Handling
145
+
146
+ ```python
147
+ from commitdb import CommitDB, CommitDBError
148
+
149
+ try:
150
+ with CommitDB('localhost', 3306) as db:
151
+ db.execute('SELECT * FROM nonexistent.table')
152
+ except CommitDBError as e:
153
+ print(f"Database error: {e}")
154
+ ```
155
+
156
+ ---
157
+
158
+ ## Security
159
+
160
+ ### SSL/TLS Encryption
161
+
162
+ ```python
163
+ # Production (with certificate verification)
164
+ db = CommitDB('localhost', 3306, use_ssl=True, ssl_ca_cert='cert.pem')
165
+
166
+ # Development (skip verification)
167
+ db = CommitDB('localhost', 3306, use_ssl=True, ssl_verify=False)
168
+ ```
169
+
170
+ ### JWT Authentication
171
+
172
+ ```python
173
+ # Auto-authenticate on connect
174
+ db = CommitDB('localhost', 3306, jwt_token='eyJhbG...')
175
+ db.connect()
176
+ print(f"Authenticated as: {db.identity}")
177
+
178
+ # Or authenticate after connect
179
+ db.connect()
180
+ db.authenticate_jwt('eyJhbG...')
181
+ ```
182
+
183
+ ---
184
+
185
+ ## Version Control
186
+
187
+ ### Branching & Merging
188
+
189
+ ```python
190
+ with CommitDBLocal() as db:
191
+ db.execute('CREATE DATABASE mydb')
192
+ db.execute('CREATE TABLE mydb.users (id INT, name STRING)')
193
+ db.execute("INSERT INTO mydb.users VALUES (1, 'Alice')")
194
+
195
+ # Create and switch to branch
196
+ db.execute('CREATE BRANCH feature')
197
+ db.execute('CHECKOUT feature')
198
+
199
+ # Make changes (isolated to this branch)
200
+ db.execute("INSERT INTO mydb.users VALUES (2, 'Bob')")
201
+
202
+ # Switch back and merge
203
+ db.execute('CHECKOUT master')
204
+ db.execute('MERGE feature')
205
+ ```
206
+
207
+ **Branch Commands:**
208
+
209
+ | Command | Description |
210
+ |---------|-------------|
211
+ | `CREATE BRANCH name` | Create new branch |
212
+ | `CHECKOUT name` | Switch to branch |
213
+ | `MERGE name` | Merge branch (auto-resolve) |
214
+ | `MERGE name WITH MANUAL RESOLUTION` | Merge with manual conflict resolution |
215
+ | `SHOW BRANCHES` | List branches |
216
+ | `SHOW MERGE CONFLICTS` | View pending conflicts |
217
+ | `RESOLVE CONFLICT path USING HEAD\|SOURCE` | Resolve conflict |
218
+ | `COMMIT MERGE` / `ABORT MERGE` | Finalize or cancel merge |
219
+
220
+ ### Remote Sync (Git)
221
+
222
+ ```python
223
+ # Add remote
224
+ db.execute("CREATE REMOTE origin 'https://github.com/user/repo.git'")
225
+
226
+ # Push/Pull with authentication
227
+ db.execute("PUSH WITH TOKEN 'ghp_xxxxxxxxxxxx'")
228
+ db.execute("PUSH WITH SSH KEY '/path/to/id_rsa'")
229
+ db.execute("PULL FROM origin")
230
+ ```
231
+
232
+ ---
233
+
234
+ ## Bulk Import/Export
235
+
236
+ ### Local Files
237
+
238
+ ```python
239
+ # Export to CSV
240
+ db.execute("COPY INTO '/path/to/users.csv' FROM mydb.users WITH (HEADER = TRUE)")
241
+
242
+ # Import from CSV
243
+ db.execute("COPY INTO mydb.users FROM '/path/to/users.csv' WITH (HEADER = TRUE)")
244
+ ```
245
+
246
+ ### S3 & HTTPS
247
+
248
+ ```python
249
+ # Import from HTTPS
250
+ db.execute("COPY INTO mydb.users FROM 'https://example.com/data.csv'")
251
+
252
+ # Import from S3 (uses AWS env vars)
253
+ db.execute("COPY INTO mydb.users FROM 's3://bucket/users.csv'")
254
+
255
+ # Import from S3 with explicit credentials
256
+ db.execute("""
257
+ COPY INTO mydb.users FROM 's3://bucket/users.csv' WITH (
258
+ AWS_KEY = 'AKIAIOSFODNN7EXAMPLE',
259
+ AWS_SECRET = 'your-secret-key',
260
+ AWS_REGION = 'us-east-1'
261
+ )
262
+ """)
263
+
264
+ # Export to S3
265
+ db.execute("COPY INTO 's3://bucket/export.csv' FROM mydb.users WITH (HEADER = TRUE)")
266
+ ```
267
+
268
+ ---
269
+
270
+ ## Building the Shared Library
271
+
272
+ For embedded mode, if the library isn't bundled:
273
+
274
+ ```bash
275
+ # From CommitDB root
276
+ make lib # Creates lib/libcommitdb.dylib (macOS) or .so (Linux)
277
+ ```
@@ -0,0 +1,252 @@
1
+ # CommitDB Python Driver
2
+
3
+ [![PyPI version](https://badge.fury.io/py/commitdb.svg)](https://badge.fury.io/py/commitdb)
4
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
5
+
6
+ Python client for CommitDB - a Git-backed SQL database engine.
7
+
8
+ **[📚 Full Documentation](https://nickyhof.github.io/CommitDB/python-driver/)**
9
+
10
+ > ⚠️ **Experimental Project** - This is a hobby project and should not be used in any production environment.
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ pip install commitdb
16
+ ```
17
+
18
+ ## Quick Start
19
+
20
+ ### Remote Mode (connect to server)
21
+
22
+ ```python
23
+ from commitdb import CommitDB
24
+
25
+ with CommitDB('localhost', 3306) as db:
26
+ db.execute('CREATE DATABASE mydb')
27
+ db.execute('CREATE TABLE mydb.users (id INT PRIMARY KEY, name STRING)')
28
+ db.execute("INSERT INTO mydb.users VALUES (1, 'Alice')")
29
+
30
+ result = db.query('SELECT * FROM mydb.users')
31
+ for row in result:
32
+ print(f"{row['id']}: {row['name']}")
33
+ ```
34
+
35
+ ### Embedded Mode (no server required)
36
+
37
+ ```python
38
+ from commitdb import CommitDBLocal
39
+
40
+ with CommitDBLocal() as db: # In-memory
41
+ db.execute('CREATE DATABASE mydb')
42
+ db.execute('CREATE TABLE mydb.users (id INT PRIMARY KEY, name STRING)')
43
+
44
+ with CommitDBLocal('/path/to/data') as db: # File-based (persistent)
45
+ db.execute('CREATE DATABASE mydb')
46
+ ```
47
+
48
+ ### Ibis Mode (pandas DataFrame support)
49
+
50
+ ```bash
51
+ pip install commitdb[ibis]
52
+ ```
53
+
54
+ ```python
55
+ import ibis
56
+
57
+ con = ibis.commitdb.connect('localhost', 3306, database='mydb')
58
+
59
+ # Or use URL-based connection:
60
+ con = ibis.connect('commitdb://localhost:3306/mydb')
61
+
62
+ # Query with Ibis expressions
63
+ users = con.table('users')
64
+ result = users.filter(users.age > 30).select('name', 'city').execute() # → pandas DataFrame
65
+ print(result)
66
+
67
+ # Insert from DataFrame
68
+ import pandas as pd
69
+ df = pd.DataFrame({'id': [1, 2], 'name': ['Alice', 'Bob']})
70
+ con.insert('users', df)
71
+ ```
72
+
73
+ ---
74
+
75
+ ## API Reference
76
+
77
+ ### CommitDB (Remote)
78
+
79
+ ```python
80
+ CommitDB(host='localhost', port=3306, use_ssl=False, ssl_verify=True,
81
+ ssl_ca_cert=None, jwt_token=None)
82
+ ```
83
+
84
+ | Method | Description |
85
+ |--------|-------------|
86
+ | `connect(timeout=10.0)` | Connect to server |
87
+ | `close()` | Close connection |
88
+ | `execute(sql)` | Execute SQL (INSERT, UPDATE, CREATE, etc.) |
89
+ | `query(sql)` | Execute SELECT, returns QueryResult |
90
+ | `authenticate_jwt(token)` | Authenticate with JWT |
91
+
92
+ ### CommitDBLocal (Embedded)
93
+
94
+ ```python
95
+ CommitDBLocal(path=None, lib_path=None)
96
+ ```
97
+
98
+ - `path` - Directory for persistence (`None` = in-memory)
99
+ - `lib_path` - Path to `libcommitdb` shared library
100
+
101
+ | Method | Description |
102
+ |--------|-------------|
103
+ | `open()` / `close()` | Open/close database |
104
+ | `execute(sql)` | Execute SQL |
105
+ | `query(sql)` | Execute SELECT |
106
+
107
+ ### QueryResult
108
+
109
+ ```python
110
+ result = db.query('SELECT * FROM mydb.users')
111
+ result.columns # ['id', 'name']
112
+ len(result) # Row count
113
+ result[0] # {'id': '1', 'name': 'Alice'}
114
+
115
+ for row in result:
116
+ print(row)
117
+ ```
118
+
119
+ ### Error Handling
120
+
121
+ ```python
122
+ from commitdb import CommitDB, CommitDBError
123
+
124
+ try:
125
+ with CommitDB('localhost', 3306) as db:
126
+ db.execute('SELECT * FROM nonexistent.table')
127
+ except CommitDBError as e:
128
+ print(f"Database error: {e}")
129
+ ```
130
+
131
+ ---
132
+
133
+ ## Security
134
+
135
+ ### SSL/TLS Encryption
136
+
137
+ ```python
138
+ # Production (with certificate verification)
139
+ db = CommitDB('localhost', 3306, use_ssl=True, ssl_ca_cert='cert.pem')
140
+
141
+ # Development (skip verification)
142
+ db = CommitDB('localhost', 3306, use_ssl=True, ssl_verify=False)
143
+ ```
144
+
145
+ ### JWT Authentication
146
+
147
+ ```python
148
+ # Auto-authenticate on connect
149
+ db = CommitDB('localhost', 3306, jwt_token='eyJhbG...')
150
+ db.connect()
151
+ print(f"Authenticated as: {db.identity}")
152
+
153
+ # Or authenticate after connect
154
+ db.connect()
155
+ db.authenticate_jwt('eyJhbG...')
156
+ ```
157
+
158
+ ---
159
+
160
+ ## Version Control
161
+
162
+ ### Branching & Merging
163
+
164
+ ```python
165
+ with CommitDBLocal() as db:
166
+ db.execute('CREATE DATABASE mydb')
167
+ db.execute('CREATE TABLE mydb.users (id INT, name STRING)')
168
+ db.execute("INSERT INTO mydb.users VALUES (1, 'Alice')")
169
+
170
+ # Create and switch to branch
171
+ db.execute('CREATE BRANCH feature')
172
+ db.execute('CHECKOUT feature')
173
+
174
+ # Make changes (isolated to this branch)
175
+ db.execute("INSERT INTO mydb.users VALUES (2, 'Bob')")
176
+
177
+ # Switch back and merge
178
+ db.execute('CHECKOUT master')
179
+ db.execute('MERGE feature')
180
+ ```
181
+
182
+ **Branch Commands:**
183
+
184
+ | Command | Description |
185
+ |---------|-------------|
186
+ | `CREATE BRANCH name` | Create new branch |
187
+ | `CHECKOUT name` | Switch to branch |
188
+ | `MERGE name` | Merge branch (auto-resolve) |
189
+ | `MERGE name WITH MANUAL RESOLUTION` | Merge with manual conflict resolution |
190
+ | `SHOW BRANCHES` | List branches |
191
+ | `SHOW MERGE CONFLICTS` | View pending conflicts |
192
+ | `RESOLVE CONFLICT path USING HEAD\|SOURCE` | Resolve conflict |
193
+ | `COMMIT MERGE` / `ABORT MERGE` | Finalize or cancel merge |
194
+
195
+ ### Remote Sync (Git)
196
+
197
+ ```python
198
+ # Add remote
199
+ db.execute("CREATE REMOTE origin 'https://github.com/user/repo.git'")
200
+
201
+ # Push/Pull with authentication
202
+ db.execute("PUSH WITH TOKEN 'ghp_xxxxxxxxxxxx'")
203
+ db.execute("PUSH WITH SSH KEY '/path/to/id_rsa'")
204
+ db.execute("PULL FROM origin")
205
+ ```
206
+
207
+ ---
208
+
209
+ ## Bulk Import/Export
210
+
211
+ ### Local Files
212
+
213
+ ```python
214
+ # Export to CSV
215
+ db.execute("COPY INTO '/path/to/users.csv' FROM mydb.users WITH (HEADER = TRUE)")
216
+
217
+ # Import from CSV
218
+ db.execute("COPY INTO mydb.users FROM '/path/to/users.csv' WITH (HEADER = TRUE)")
219
+ ```
220
+
221
+ ### S3 & HTTPS
222
+
223
+ ```python
224
+ # Import from HTTPS
225
+ db.execute("COPY INTO mydb.users FROM 'https://example.com/data.csv'")
226
+
227
+ # Import from S3 (uses AWS env vars)
228
+ db.execute("COPY INTO mydb.users FROM 's3://bucket/users.csv'")
229
+
230
+ # Import from S3 with explicit credentials
231
+ db.execute("""
232
+ COPY INTO mydb.users FROM 's3://bucket/users.csv' WITH (
233
+ AWS_KEY = 'AKIAIOSFODNN7EXAMPLE',
234
+ AWS_SECRET = 'your-secret-key',
235
+ AWS_REGION = 'us-east-1'
236
+ )
237
+ """)
238
+
239
+ # Export to S3
240
+ db.execute("COPY INTO 's3://bucket/export.csv' FROM mydb.users WITH (HEADER = TRUE)")
241
+ ```
242
+
243
+ ---
244
+
245
+ ## Building the Shared Library
246
+
247
+ For embedded mode, if the library isn't bundled:
248
+
249
+ ```bash
250
+ # From CommitDB root
251
+ make lib # Creates lib/libcommitdb.dylib (macOS) or .so (Linux)
252
+ ```
@@ -0,0 +1,43 @@
1
+ """
2
+ CommitDB Python Driver
3
+
4
+ A Python client for connecting to CommitDB SQL Server.
5
+
6
+ Usage:
7
+ from commitdb import CommitDB
8
+
9
+ db = CommitDB('localhost', 3306)
10
+ db.connect()
11
+
12
+ # Create database and table
13
+ db.execute('CREATE DATABASE mydb')
14
+ db.execute('CREATE TABLE mydb.users (id INT PRIMARY KEY, name STRING)')
15
+
16
+ # Insert data
17
+ db.execute("INSERT INTO mydb.users (id, name) VALUES (1, 'Alice')")
18
+
19
+ # Query data
20
+ result = db.query('SELECT * FROM mydb.users')
21
+ for row in result:
22
+ print(row)
23
+
24
+ db.close()
25
+
26
+ Embedded mode (requires libcommitdb):
27
+ from commitdb import CommitDBLocal
28
+
29
+ with CommitDBLocal('/path/to/data') as db:
30
+ db.execute('CREATE DATABASE mydb')
31
+ """
32
+
33
+ from importlib.metadata import version, PackageNotFoundError
34
+
35
+ from .client import CommitDB, CommitDBLocal, QueryResult, CommitResult, CommitDBError
36
+
37
+ try:
38
+ __version__ = version("commitdb")
39
+ except PackageNotFoundError:
40
+ __version__ = "0.0.0" # Fallback for development/editable installs
41
+
42
+ __all__ = ['CommitDB', 'CommitDBLocal', 'QueryResult', 'CommitResult', 'CommitDBError', '__version__']
43
+
@@ -0,0 +1,135 @@
1
+ """
2
+ Python ctypes bindings for libcommitdb shared library.
3
+ """
4
+
5
+ import ctypes
6
+ import json
7
+ import os
8
+ import platform
9
+ from pathlib import Path
10
+ from typing import Optional
11
+
12
+
13
+ def _find_library() -> Optional[str]:
14
+ """Find the libcommitdb shared library."""
15
+ system = platform.system()
16
+
17
+ if system == 'Darwin':
18
+ lib_names = ['libcommitdb.dylib', 'libcommitdb-darwin-arm64.dylib', 'libcommitdb-darwin-amd64.dylib']
19
+ elif system == 'Linux':
20
+ lib_names = ['libcommitdb.so', 'libcommitdb-linux-amd64.so', 'libcommitdb-linux-arm64.so']
21
+ elif system == 'Windows':
22
+ lib_names = ['libcommitdb.dll']
23
+ else:
24
+ lib_names = ['libcommitdb.so', 'libcommitdb.dylib']
25
+
26
+ # Search paths
27
+ search_paths = [
28
+ Path(__file__).parent / 'lib', # Package lib directory (for pip installed)
29
+ Path(__file__).parent, # Same directory as this file
30
+ Path(__file__).parent.parent / 'lib', # drivers/python/lib
31
+ Path(__file__).parent.parent.parent.parent / 'lib', # CommitDB/lib
32
+ Path.cwd() / 'lib', # ./lib
33
+ Path.cwd(), # Current directory
34
+ ]
35
+
36
+ for path in search_paths:
37
+ for lib_name in lib_names:
38
+ lib_path = path / lib_name
39
+ if lib_path.exists():
40
+ return str(lib_path)
41
+
42
+ return None
43
+
44
+
45
+ class CommitDBBinding:
46
+ """Low-level ctypes bindings for libcommitdb."""
47
+
48
+ _lib: Optional[ctypes.CDLL] = None
49
+ _lib_path: Optional[str] = None
50
+
51
+ @classmethod
52
+ def load(cls, lib_path: Optional[str] = None) -> 'CommitDBBinding':
53
+ """Load the shared library."""
54
+ if lib_path is None:
55
+ lib_path = _find_library()
56
+
57
+ if lib_path is None:
58
+ raise RuntimeError(
59
+ "Could not find libcommitdb shared library. "
60
+ "Build it with: make lib"
61
+ )
62
+
63
+ cls._lib_path = lib_path
64
+ cls._lib = ctypes.CDLL(lib_path)
65
+
66
+ # Define function signatures
67
+ cls._lib.commitdb_open_memory.argtypes = []
68
+ cls._lib.commitdb_open_memory.restype = ctypes.c_int
69
+
70
+ cls._lib.commitdb_open_file.argtypes = [ctypes.c_char_p]
71
+ cls._lib.commitdb_open_file.restype = ctypes.c_int
72
+
73
+ cls._lib.commitdb_close.argtypes = [ctypes.c_int]
74
+ cls._lib.commitdb_close.restype = None
75
+
76
+ # Use c_void_p for the result pointer to avoid automatic conversion
77
+ cls._lib.commitdb_execute.argtypes = [ctypes.c_int, ctypes.c_char_p]
78
+ cls._lib.commitdb_execute.restype = ctypes.c_void_p
79
+
80
+ cls._lib.commitdb_free.argtypes = [ctypes.c_void_p]
81
+ cls._lib.commitdb_free.restype = None
82
+
83
+ return cls()
84
+
85
+ @classmethod
86
+ def is_loaded(cls) -> bool:
87
+ """Check if the library is loaded."""
88
+ return cls._lib is not None
89
+
90
+ @classmethod
91
+ def open_memory(cls) -> int:
92
+ """Open an in-memory database."""
93
+ if not cls.is_loaded():
94
+ cls.load()
95
+ handle = cls._lib.commitdb_open_memory()
96
+ if handle < 0:
97
+ raise RuntimeError("Failed to open in-memory database")
98
+ return handle
99
+
100
+ @classmethod
101
+ def open_file(cls, path: str) -> int:
102
+ """Open a file-based database."""
103
+ if not cls.is_loaded():
104
+ cls.load()
105
+ handle = cls._lib.commitdb_open_file(path.encode('utf-8'))
106
+ if handle < 0:
107
+ raise RuntimeError(f"Failed to open database at {path}")
108
+ return handle
109
+
110
+ @classmethod
111
+ def close(cls, handle: int) -> None:
112
+ """Close a database handle."""
113
+ if cls.is_loaded():
114
+ cls._lib.commitdb_close(handle)
115
+
116
+ @classmethod
117
+ def execute(cls, handle: int, query: str) -> dict:
118
+ """Execute a query and return the JSON response."""
119
+ if not cls.is_loaded():
120
+ raise RuntimeError("Library not loaded")
121
+
122
+ result_ptr = cls._lib.commitdb_execute(handle, query.encode('utf-8'))
123
+ if result_ptr is None or result_ptr == 0:
124
+ raise RuntimeError("Query execution failed")
125
+
126
+ try:
127
+ # Cast void pointer to char pointer and read the string
128
+ result_str = ctypes.cast(result_ptr, ctypes.c_char_p).value
129
+ if result_str is None:
130
+ raise RuntimeError("Empty response from query")
131
+ result_json = result_str.decode('utf-8')
132
+ return json.loads(result_json)
133
+ finally:
134
+ # Free the allocated memory using the void pointer
135
+ cls._lib.commitdb_free(result_ptr)