Skip to content

Commit 1d584f0

Browse files
committed
Add upgrading.rst with 4.0 breaking changes documentation
Documents all breaking changes in 4.0 for both the Python library and CLI: - db["name"] only returns tables, not views - Default float type changed to REAL - convert() no longer skips False values - Table schemas use double quotes - Upsert uses modern SQLite syntax - Type detection now default for CSV/TSV import - sqlite-utils tui moved to plugin - Python 3.10+ required
1 parent 147fd7e commit 1d584f0

File tree

2 files changed

+135
-0
lines changed

2 files changed

+135
-0
lines changed

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,4 @@ Contents
4141
cli-reference
4242
contributing
4343
changelog
44+
upgrading

docs/upgrading.rst

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
.. _upgrading:
2+
3+
=====================
4+
Upgrading to 4.0
5+
=====================
6+
7+
sqlite-utils 4.0 includes several breaking changes. This page describes what has changed and how to update your code.
8+
9+
Python library changes
10+
======================
11+
12+
db["name"] only returns tables
13+
------------------------------
14+
15+
In previous versions, ``db["table_or_view_name"]`` would return either a :ref:`Table <reference_db_table>` or :ref:`View <reference_db_view>` object depending on what existed in the database.
16+
17+
In 4.0, this syntax **only returns Table objects**. Attempting to use it with a view name will raise a ``sqlite_utils.db.NoTable`` exception.
18+
19+
**Before (3.x):**
20+
21+
.. code-block:: python
22+
23+
# This could return either a Table or View
24+
obj = db["my_view"]
25+
obj.drop()
26+
27+
**After (4.0):**
28+
29+
.. code-block:: python
30+
31+
# Use db.view() explicitly for views
32+
view = db.view("my_view")
33+
view.drop()
34+
35+
# db["name"] now only works with tables
36+
table = db["my_table"]
37+
38+
This change improves type safety since views lack methods like ``.insert()`` that are available on tables.
39+
40+
db.table() raises NoTable for views
41+
-----------------------------------
42+
43+
The ``db.table(name)`` method now raises ``sqlite_utils.db.NoTable`` if the name refers to a view. Use ``db.view(name)`` instead.
44+
45+
Default floating point type is REAL
46+
-----------------------------------
47+
48+
When inserting data with auto-detected column types, floating point values now create columns with type ``REAL`` instead of ``FLOAT``. ``REAL`` is the correct SQLite affinity for floating point values.
49+
50+
This affects the schema of newly created tables but does not change how data is stored or queried.
51+
52+
convert() no longer skips False values
53+
--------------------------------------
54+
55+
The ``table.convert()`` method previously skipped rows where the column value evaluated to ``False`` (including ``0``, empty strings, and ``None``). This behavior has been removed.
56+
57+
**Before (3.x):**
58+
59+
.. code-block:: python
60+
61+
# Rows with falsey values were skipped by default
62+
# --skip-false was needed to process all rows
63+
table.convert("column", lambda x: x.upper(), skip_false=False)
64+
65+
**After (4.0):**
66+
67+
.. code-block:: python
68+
69+
# All rows are now processed, including those with falsey values
70+
table.convert("column", lambda x: x.upper() if x else x)
71+
72+
Table schemas use double quotes
73+
-------------------------------
74+
75+
Tables created by sqlite-utils now use ``"double-quotes"`` for table and column names in the schema instead of ``[square-braces]``. Both are valid SQL, but double quotes are the SQL standard.
76+
77+
This only affects how the schema is written. Existing tables are not modified.
78+
79+
Upsert uses modern SQLite syntax
80+
--------------------------------
81+
82+
Upsert operations now use SQLite's ``INSERT ... ON CONFLICT SET`` syntax on SQLite versions 3.24.0 and later. The previous implementation used ``INSERT OR IGNORE`` followed by ``UPDATE``.
83+
84+
To use the old behavior, pass ``use_old_upsert=True`` to the ``Database()`` constructor:
85+
86+
.. code-block:: python
87+
88+
db = Database("my.db", use_old_upsert=True)
89+
90+
CLI changes
91+
===========
92+
93+
Type detection is now the default
94+
---------------------------------
95+
96+
When importing CSV or TSV data with the ``insert`` or ``upsert`` commands, sqlite-utils now automatically detects column types. Previously all columns were treated as ``TEXT`` unless ``--detect-types`` was passed.
97+
98+
**Before (3.x):**
99+
100+
.. code-block:: bash
101+
102+
# Types were detected only with --detect-types
103+
sqlite-utils insert data.db mytable data.csv --csv --detect-types
104+
105+
**After (4.0):**
106+
107+
.. code-block:: bash
108+
109+
# Types are detected by default
110+
sqlite-utils insert data.db mytable data.csv --csv
111+
112+
# Use --no-detect-types to treat all columns as TEXT
113+
sqlite-utils insert data.db mytable data.csv --csv --no-detect-types
114+
115+
The ``SQLITE_UTILS_DETECT_TYPES`` environment variable has been removed.
116+
117+
convert --skip-false removed
118+
----------------------------
119+
120+
The ``--skip-false`` option for ``sqlite-utils convert`` has been removed. All rows are now processed regardless of whether the column value is falsey.
121+
122+
sqlite-utils tui is now a plugin
123+
--------------------------------
124+
125+
The ``sqlite-utils tui`` command has been moved to a separate plugin. Install it with:
126+
127+
.. code-block:: bash
128+
129+
sqlite-utils install sqlite-utils-tui
130+
131+
Python version requirements
132+
===========================
133+
134+
sqlite-utils 4.0 requires Python 3.10 or higher. Python 3.8 and 3.9 are no longer supported.

0 commit comments

Comments
 (0)