|
| 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