django-libsql-backend 0.1.0__tar.gz → 0.1.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.
Files changed (22) hide show
  1. {django_libsql_backend-0.1.0 → django_libsql_backend-0.1.1}/PKG-INFO +30 -11
  2. {django_libsql_backend-0.1.0 → django_libsql_backend-0.1.1}/README.md +29 -10
  3. {django_libsql_backend-0.1.0 → django_libsql_backend-0.1.1}/django_libsql/__init__.py +1 -1
  4. django_libsql_backend-0.1.1/django_libsql/base.py +1009 -0
  5. django_libsql_backend-0.1.1/django_libsql/creation.py +138 -0
  6. {django_libsql_backend-0.1.0 → django_libsql_backend-0.1.1}/django_libsql/features.py +65 -10
  7. django_libsql_backend-0.1.1/django_libsql/functions.py +15 -0
  8. {django_libsql_backend-0.1.0 → django_libsql_backend-0.1.1}/django_libsql/operations.py +307 -8
  9. django_libsql_backend-0.1.1/django_libsql/schema.py +50 -0
  10. {django_libsql_backend-0.1.0 → django_libsql_backend-0.1.1}/django_libsql_backend.egg-info/PKG-INFO +30 -11
  11. {django_libsql_backend-0.1.0 → django_libsql_backend-0.1.1}/django_libsql_backend.egg-info/SOURCES.txt +1 -0
  12. {django_libsql_backend-0.1.0 → django_libsql_backend-0.1.1}/pyproject.toml +1 -1
  13. django_libsql_backend-0.1.0/django_libsql/base.py +0 -528
  14. django_libsql_backend-0.1.0/django_libsql/creation.py +0 -39
  15. django_libsql_backend-0.1.0/django_libsql/schema.py +0 -42
  16. {django_libsql_backend-0.1.0 → django_libsql_backend-0.1.1}/LICENSE +0 -0
  17. {django_libsql_backend-0.1.0 → django_libsql_backend-0.1.1}/django_libsql/client.py +0 -0
  18. {django_libsql_backend-0.1.0 → django_libsql_backend-0.1.1}/django_libsql/introspection.py +0 -0
  19. {django_libsql_backend-0.1.0 → django_libsql_backend-0.1.1}/django_libsql_backend.egg-info/dependency_links.txt +0 -0
  20. {django_libsql_backend-0.1.0 → django_libsql_backend-0.1.1}/django_libsql_backend.egg-info/requires.txt +0 -0
  21. {django_libsql_backend-0.1.0 → django_libsql_backend-0.1.1}/django_libsql_backend.egg-info/top_level.txt +0 -0
  22. {django_libsql_backend-0.1.0 → django_libsql_backend-0.1.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-libsql-backend
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: Django database backend for libSQL/Turso — SQLite-compatible remote databases over HTTP
5
5
  Author-email: CyberCalculus <cybercalculus@example.com>
6
6
  License-Expression: MIT
@@ -180,8 +180,11 @@ DATABASES = {
180
180
  |---|---|---|---|---|
181
181
  | **Transport** | Local file I/O | Local file I/O | HTTP REST API |
182
182
  | **Connection** | Persistent `sqlite3.Connection` | Persistent `sqlite3.Connection` | Stateless — each request = new connection |
183
- | **Transactions** | Real SQLite transactions | Real SQLite transactions | Each statement auto-commits independently |
184
- | **Savepoints** | Supported | Supported | Not supported |
183
+ | **Transactions** | Real SQLite transactions | Real SQLite transactions | Buffered writes flushed as batch on commit; rollback may not recover flushed writes |
184
+ | **Savepoints** | Supported | Supported | Client-side buffer snapshots only (no server-side SAVEPOINT) |
185
+ | **DDL rollback** | Supported | Supported | Not supported — each DDL auto-commits |
186
+ | **FK deferral** | Supported | Supported | Not supported — needs persistent PRAGMA state |
187
+ | **INSERT...RETURNING** | Supported (3.35+) | Supported (3.35+) | Not used — would bypass write buffering; `lastrowid` used instead |
185
188
  | **PRAGMAs** | Persistent per connection | Persistent per connection | Reset every HTTP request |
186
189
  | **File locking** | Yes | Yes | None — Turso handles concurrency |
187
190
  | **Schema changes** | `_remake_table` | `_remake_table` | Same, each DDL is its own HTTP call |
@@ -237,20 +240,36 @@ These apply only to **remote** (Turso HTTP) mode. Local mode has full SQLite tra
237
240
 
238
241
  Each Turso HTTP request creates a new SQLite connection. This means:
239
242
 
240
- - **`PRAGMA` settings do not persist** between requests. `PRAGMA foreign_keys = OFF` in request A does not affect request B.
241
- - **`SET` / transaction state** is not shared across calls.
243
+ - **`PRAGMA` settings do not persist** between requests.
244
+ - **DDL cannot be rolled back** each schema change auto-commits immediately.
245
+ - **FK constraint checks cannot be deferred** — needs persistent connection state.
242
246
 
243
247
  ### Transactions
244
248
 
245
- `commit()`, `rollback()`, `savepoints`, and `atomic()` blocks are **no-ops** each SQL statement is its own auto-committed transaction over HTTP. For most web applications this is acceptable because Django's default autocommit mode already wraps each request in a single implicit transaction.
249
+ Remote mode uses **client-side write buffering** for best-effort atomicity:
250
+ - Writes inside `atomic()` blocks are buffered in memory
251
+ - On commit (outermost `atomic` exit), all buffered writes are flushed as a single batch request
252
+ - Reading inside a transaction auto-flushes buffered writes first (read-your-writes)
253
+ - Accessing `cursor.lastrowid` also triggers a flush
254
+ - Once flushed, writes cannot be rolled back — rollback raises `DatabaseError`
246
255
 
247
- If you need multi-statement atomicity, consider:
248
- - Using Turso's batch API (the backend uses it automatically for `executemany()`)
249
- - Calling a server-side function that groups statements
256
+ Savepoints are client-side buffer snapshots — they track buffer length but don't send `SAVEPOINT` SQL to the server. Rolling back to a savepoint truncates the buffer; releasing is a no-op.
250
257
 
251
- ### Foreign key constraints
258
+ ### SQL function availability
252
259
 
253
- Since FK pragmas don't persist, the schema editor bypasses Django's FK-disabling requirement. This works for **creating new tables** (the common path during initial `migrate`). If you later use `ALTER TABLE` operations that rebuild tables, Turso handles the DDL isolation server-side.
260
+ These Django ORM functions use Python-registered SQL functions that are **not available** on remote servers:
261
+ - **Hash**: `MD5`, `SHA1`, `SHA224`, `SHA256`, `SHA384`, `SHA512`
262
+ - **String**: `LPad`, `RPad`, `Repeat`, `Reverse`
263
+ - **Math**: `Cot`, `Sign`, `BitXor` (raises `NotSupportedError`)
264
+ - **Aggregate**: `StdDev`, `Variance` (raise `NotSupportedError`)
265
+
266
+ ### Timezone handling
267
+
268
+ SQLite has no native timezone support. In remote mode, all date/time SQL is generated using `strftime`/`date`/`time` without timezone conversion. Results are correct when the database stores UTC (Django's default). Queries involving non-UTC timezone conversion may produce incorrect results.
269
+
270
+ ### Schema migrations
271
+
272
+ `_remake_table` (used by `ALTER TABLE` operations) may fail for tables referenced by foreign keys due to the stateless PRAGMA issue. Most `makemigrations`/`migrate` operations work correctly for the common path of creating new tables and adding columns.
254
273
 
255
274
  ---
256
275
 
@@ -149,8 +149,11 @@ DATABASES = {
149
149
  |---|---|---|---|---|
150
150
  | **Transport** | Local file I/O | Local file I/O | HTTP REST API |
151
151
  | **Connection** | Persistent `sqlite3.Connection` | Persistent `sqlite3.Connection` | Stateless — each request = new connection |
152
- | **Transactions** | Real SQLite transactions | Real SQLite transactions | Each statement auto-commits independently |
153
- | **Savepoints** | Supported | Supported | Not supported |
152
+ | **Transactions** | Real SQLite transactions | Real SQLite transactions | Buffered writes flushed as batch on commit; rollback may not recover flushed writes |
153
+ | **Savepoints** | Supported | Supported | Client-side buffer snapshots only (no server-side SAVEPOINT) |
154
+ | **DDL rollback** | Supported | Supported | Not supported — each DDL auto-commits |
155
+ | **FK deferral** | Supported | Supported | Not supported — needs persistent PRAGMA state |
156
+ | **INSERT...RETURNING** | Supported (3.35+) | Supported (3.35+) | Not used — would bypass write buffering; `lastrowid` used instead |
154
157
  | **PRAGMAs** | Persistent per connection | Persistent per connection | Reset every HTTP request |
155
158
  | **File locking** | Yes | Yes | None — Turso handles concurrency |
156
159
  | **Schema changes** | `_remake_table` | `_remake_table` | Same, each DDL is its own HTTP call |
@@ -206,20 +209,36 @@ These apply only to **remote** (Turso HTTP) mode. Local mode has full SQLite tra
206
209
 
207
210
  Each Turso HTTP request creates a new SQLite connection. This means:
208
211
 
209
- - **`PRAGMA` settings do not persist** between requests. `PRAGMA foreign_keys = OFF` in request A does not affect request B.
210
- - **`SET` / transaction state** is not shared across calls.
212
+ - **`PRAGMA` settings do not persist** between requests.
213
+ - **DDL cannot be rolled back** each schema change auto-commits immediately.
214
+ - **FK constraint checks cannot be deferred** — needs persistent connection state.
211
215
 
212
216
  ### Transactions
213
217
 
214
- `commit()`, `rollback()`, `savepoints`, and `atomic()` blocks are **no-ops** each SQL statement is its own auto-committed transaction over HTTP. For most web applications this is acceptable because Django's default autocommit mode already wraps each request in a single implicit transaction.
218
+ Remote mode uses **client-side write buffering** for best-effort atomicity:
219
+ - Writes inside `atomic()` blocks are buffered in memory
220
+ - On commit (outermost `atomic` exit), all buffered writes are flushed as a single batch request
221
+ - Reading inside a transaction auto-flushes buffered writes first (read-your-writes)
222
+ - Accessing `cursor.lastrowid` also triggers a flush
223
+ - Once flushed, writes cannot be rolled back — rollback raises `DatabaseError`
215
224
 
216
- If you need multi-statement atomicity, consider:
217
- - Using Turso's batch API (the backend uses it automatically for `executemany()`)
218
- - Calling a server-side function that groups statements
225
+ Savepoints are client-side buffer snapshots — they track buffer length but don't send `SAVEPOINT` SQL to the server. Rolling back to a savepoint truncates the buffer; releasing is a no-op.
219
226
 
220
- ### Foreign key constraints
227
+ ### SQL function availability
221
228
 
222
- Since FK pragmas don't persist, the schema editor bypasses Django's FK-disabling requirement. This works for **creating new tables** (the common path during initial `migrate`). If you later use `ALTER TABLE` operations that rebuild tables, Turso handles the DDL isolation server-side.
229
+ These Django ORM functions use Python-registered SQL functions that are **not available** on remote servers:
230
+ - **Hash**: `MD5`, `SHA1`, `SHA224`, `SHA256`, `SHA384`, `SHA512`
231
+ - **String**: `LPad`, `RPad`, `Repeat`, `Reverse`
232
+ - **Math**: `Cot`, `Sign`, `BitXor` (raises `NotSupportedError`)
233
+ - **Aggregate**: `StdDev`, `Variance` (raise `NotSupportedError`)
234
+
235
+ ### Timezone handling
236
+
237
+ SQLite has no native timezone support. In remote mode, all date/time SQL is generated using `strftime`/`date`/`time` without timezone conversion. Results are correct when the database stores UTC (Django's default). Queries involving non-UTC timezone conversion may produce incorrect results.
238
+
239
+ ### Schema migrations
240
+
241
+ `_remake_table` (used by `ALTER TABLE` operations) may fail for tables referenced by foreign keys due to the stateless PRAGMA issue. Most `makemigrations`/`migrate` operations work correctly for the common path of creating new tables and adding columns.
223
242
 
224
243
  ---
225
244
 
@@ -21,7 +21,7 @@ The ``NAME`` can be a full URL (``https://db-name.turso.io``) or a bare
21
21
  hostname (``db-name.turso.io``) — ``https://`` is prepended automatically.
22
22
  """
23
23
 
24
- __version__ = "0.1.0"
24
+ __version__ = "0.1.1"
25
25
 
26
26
  from .base import DatabaseWrapper
27
27