cinchdb 0.1.10__py3-none-any.whl → 0.1.12__py3-none-any.whl
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.
- cinchdb/cli/commands/column.py +3 -4
- cinchdb/cli/commands/database.py +58 -60
- cinchdb/cli/commands/table.py +3 -3
- cinchdb/cli/main.py +1 -7
- cinchdb/cli/utils.py +23 -0
- cinchdb/core/database.py +138 -11
- cinchdb/core/initializer.py +188 -10
- cinchdb/core/path_utils.py +44 -27
- cinchdb/infrastructure/metadata_connection_pool.py +145 -0
- cinchdb/infrastructure/metadata_db.py +376 -0
- cinchdb/managers/branch.py +119 -23
- cinchdb/managers/change_applier.py +30 -13
- cinchdb/managers/column.py +4 -10
- cinchdb/managers/query.py +40 -4
- cinchdb/managers/table.py +8 -6
- cinchdb/managers/tenant.py +698 -167
- cinchdb/models/table.py +0 -4
- cinchdb/models/tenant.py +4 -2
- {cinchdb-0.1.10.dist-info → cinchdb-0.1.12.dist-info}/METADATA +10 -37
- {cinchdb-0.1.10.dist-info → cinchdb-0.1.12.dist-info}/RECORD +23 -21
- {cinchdb-0.1.10.dist-info → cinchdb-0.1.12.dist-info}/WHEEL +0 -0
- {cinchdb-0.1.10.dist-info → cinchdb-0.1.12.dist-info}/entry_points.txt +0 -0
- {cinchdb-0.1.10.dist-info → cinchdb-0.1.12.dist-info}/licenses/LICENSE +0 -0
cinchdb/managers/column.py
CHANGED
@@ -153,8 +153,7 @@ class ColumnManager:
|
|
153
153
|
col_defs = []
|
154
154
|
for col in new_columns:
|
155
155
|
col_def = f"{col.name} {col.type}"
|
156
|
-
|
157
|
-
col_def += " PRIMARY KEY"
|
156
|
+
# Primary keys are handled at table creation, not as a column attribute
|
158
157
|
if not col.nullable:
|
159
158
|
col_def += " NOT NULL"
|
160
159
|
if col.default is not None:
|
@@ -326,7 +325,6 @@ class ColumnManager:
|
|
326
325
|
type=col.type,
|
327
326
|
nullable=col.nullable,
|
328
327
|
default=col.default,
|
329
|
-
primary_key=col.primary_key,
|
330
328
|
unique=col.unique,
|
331
329
|
)
|
332
330
|
new_columns.append(new_col)
|
@@ -339,8 +337,7 @@ class ColumnManager:
|
|
339
337
|
col_defs = []
|
340
338
|
for col in new_columns:
|
341
339
|
col_def = f"{col.name} {col.type}"
|
342
|
-
|
343
|
-
col_def += " PRIMARY KEY"
|
340
|
+
# Primary keys are handled at table creation, not as a column attribute
|
344
341
|
if not col.nullable:
|
345
342
|
col_def += " NOT NULL"
|
346
343
|
if col.default is not None:
|
@@ -397,7 +394,6 @@ class ColumnManager:
|
|
397
394
|
type=col.type,
|
398
395
|
nullable=col.nullable,
|
399
396
|
default=col.default,
|
400
|
-
primary_key=col.primary_key,
|
401
397
|
unique=col.unique,
|
402
398
|
)
|
403
399
|
new_columns.append(new_col)
|
@@ -410,8 +406,7 @@ class ColumnManager:
|
|
410
406
|
col_defs = []
|
411
407
|
for col in new_columns:
|
412
408
|
col_def = f"{col.name} {col.type}"
|
413
|
-
|
414
|
-
col_def += " PRIMARY KEY"
|
409
|
+
# Primary keys are handled at table creation, not as a column attribute
|
415
410
|
if not col.nullable:
|
416
411
|
col_def += " NOT NULL"
|
417
412
|
if col.default is not None:
|
@@ -512,8 +507,7 @@ class ColumnManager:
|
|
512
507
|
col_defs = []
|
513
508
|
for col in existing_columns:
|
514
509
|
col_def = f"{col.name} {col.type}"
|
515
|
-
|
516
|
-
col_def += " PRIMARY KEY"
|
510
|
+
# Primary keys are handled at table creation, not as a column attribute
|
517
511
|
# Apply nullable change to target column
|
518
512
|
if col.name == column_name:
|
519
513
|
if not nullable:
|
cinchdb/managers/query.py
CHANGED
@@ -8,6 +8,7 @@ from pydantic import BaseModel, ValidationError
|
|
8
8
|
from cinchdb.core.connection import DatabaseConnection
|
9
9
|
from cinchdb.core.path_utils import get_tenant_db_path
|
10
10
|
from cinchdb.utils import validate_query_safe
|
11
|
+
from cinchdb.managers.tenant import TenantManager
|
11
12
|
|
12
13
|
T = TypeVar("T", bound=BaseModel)
|
13
14
|
|
@@ -30,7 +31,24 @@ class QueryManager:
|
|
30
31
|
self.database = database
|
31
32
|
self.branch = branch
|
32
33
|
self.tenant = tenant
|
33
|
-
|
34
|
+
# Initialize tenant manager for lazy tenant handling
|
35
|
+
self.tenant_manager = TenantManager(project_root, database, branch)
|
36
|
+
|
37
|
+
def _is_write_query(self, sql: str) -> bool:
|
38
|
+
"""Check if a SQL query is a write operation.
|
39
|
+
|
40
|
+
Args:
|
41
|
+
sql: SQL query string
|
42
|
+
|
43
|
+
Returns:
|
44
|
+
True if query performs writes, False otherwise
|
45
|
+
"""
|
46
|
+
sql_upper = sql.strip().upper()
|
47
|
+
write_keywords = [
|
48
|
+
"INSERT", "UPDATE", "DELETE", "CREATE", "ALTER", "DROP",
|
49
|
+
"TRUNCATE", "REPLACE", "MERGE"
|
50
|
+
]
|
51
|
+
return any(sql_upper.startswith(keyword) for keyword in write_keywords)
|
34
52
|
|
35
53
|
def execute(
|
36
54
|
self,
|
@@ -62,7 +80,12 @@ class QueryManager:
|
|
62
80
|
"execute() can only be used with SELECT queries. Use execute_non_query() for INSERT/UPDATE/DELETE operations."
|
63
81
|
)
|
64
82
|
|
65
|
-
|
83
|
+
# Get appropriate database path based on operation type (read for SELECT)
|
84
|
+
db_path = self.tenant_manager.get_tenant_db_path_for_operation(
|
85
|
+
self.tenant, is_write=False
|
86
|
+
)
|
87
|
+
|
88
|
+
with DatabaseConnection(db_path) as conn:
|
66
89
|
cursor = conn.execute(sql, params)
|
67
90
|
rows = cursor.fetchall()
|
68
91
|
return [dict(row) for row in rows]
|
@@ -187,7 +210,12 @@ class QueryManager:
|
|
187
210
|
if not skip_validation:
|
188
211
|
validate_query_safe(sql)
|
189
212
|
|
190
|
-
|
213
|
+
# Get appropriate database path based on operation type (write for non-SELECT)
|
214
|
+
db_path = self.tenant_manager.get_tenant_db_path_for_operation(
|
215
|
+
self.tenant, is_write=True
|
216
|
+
)
|
217
|
+
|
218
|
+
with DatabaseConnection(db_path) as conn:
|
191
219
|
cursor = conn.execute(sql, params)
|
192
220
|
affected_rows = cursor.rowcount
|
193
221
|
conn.commit()
|
@@ -208,7 +236,15 @@ class QueryManager:
|
|
208
236
|
"""
|
209
237
|
total_affected = 0
|
210
238
|
|
211
|
-
|
239
|
+
# Determine if this is a write operation
|
240
|
+
is_write = self._is_write_query(sql)
|
241
|
+
|
242
|
+
# Get appropriate database path
|
243
|
+
db_path = self.tenant_manager.get_tenant_db_path_for_operation(
|
244
|
+
self.tenant, is_write=is_write
|
245
|
+
)
|
246
|
+
|
247
|
+
with DatabaseConnection(db_path) as conn:
|
212
248
|
try:
|
213
249
|
for params in params_list:
|
214
250
|
cursor = conn.execute(sql, params)
|
cinchdb/managers/table.py
CHANGED
@@ -124,9 +124,9 @@ class TableManager:
|
|
124
124
|
fk_constraint += f" ON UPDATE {fk.on_update}"
|
125
125
|
foreign_key_constraints.append(fk_constraint)
|
126
126
|
|
127
|
-
# Build automatic columns
|
127
|
+
# Build automatic columns (id is always the primary key)
|
128
128
|
auto_columns = [
|
129
|
-
Column(name="id", type="TEXT",
|
129
|
+
Column(name="id", type="TEXT", nullable=False),
|
130
130
|
Column(name="created_at", type="TEXT", nullable=False),
|
131
131
|
Column(name="updated_at", type="TEXT", nullable=True),
|
132
132
|
]
|
@@ -139,13 +139,14 @@ class TableManager:
|
|
139
139
|
for col in all_columns:
|
140
140
|
col_def = f"{col.name} {col.type}"
|
141
141
|
|
142
|
-
|
142
|
+
# id column is always the primary key
|
143
|
+
if col.name == "id":
|
143
144
|
col_def += " PRIMARY KEY"
|
144
145
|
if not col.nullable:
|
145
146
|
col_def += " NOT NULL"
|
146
147
|
if col.default is not None:
|
147
148
|
col_def += f" DEFAULT {col.default}"
|
148
|
-
if col.unique and
|
149
|
+
if col.unique and col.name != "id": # id is already unique via PRIMARY KEY
|
149
150
|
col_def += " UNIQUE"
|
150
151
|
|
151
152
|
sql_parts.append(col_def)
|
@@ -261,7 +262,7 @@ class TableManager:
|
|
261
262
|
type=col_type,
|
262
263
|
nullable=(row["notnull"] == 0),
|
263
264
|
default=row["dflt_value"],
|
264
|
-
primary_key
|
265
|
+
# Note: primary_key info not needed - 'id' is always the primary key
|
265
266
|
foreign_key=foreign_key,
|
266
267
|
)
|
267
268
|
columns.append(column)
|
@@ -339,7 +340,8 @@ class TableManager:
|
|
339
340
|
for col in source.columns:
|
340
341
|
col_def = f"{col.name} {col.type}"
|
341
342
|
|
342
|
-
|
343
|
+
# id column is always the primary key
|
344
|
+
if col.name == "id":
|
343
345
|
col_def += " PRIMARY KEY"
|
344
346
|
if not col.nullable:
|
345
347
|
col_def += " NOT NULL"
|