summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Anderson <seanga2@gmail.com>2020-11-07 19:52:04 -0500
committerGord Thompson <gord@gordthompson.com>2020-11-08 06:09:45 -0700
commit4b39b0f89dfd47dc9f5ba948e564c2afbbd44fef (patch)
treeebac6a900917013a65821d5deed9e6b2d8d5e39c
parent757a5b1858a742133e2197940a55f38823534365 (diff)
downloadsqlalchemy-4b39b0f89dfd47dc9f5ba948e564c2afbbd44fef.tar.gz
Support SQLite WITHOUT ROWID tables
This adds support for creating tables WITHOUT ROWID in the SQLite dialect. WITHOUT ROWID tables were introduced in SQLite version 3.8.2 (2013-12-06). They do not use an implicit rowid column as the primary key. This may result in space and performance savings for tables without INTEGER primary keys and tables with composite primary keys. For more information about this feature, see the sqlite documentation [1]. [1] https://www.sqlite.org/withoutrowid.html Fixes: #5685 ### Checklist This pull request is: - [x] A new feature implementation - please include the issue number, and create an issue if none exists, which must include a complete example of how the feature would look. - Please include: `Fixes: #<issue number>` in the commit message - please include tests. Closes: #5686 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/5686 Pull-request-sha: 2b44782d1b3d858e31ce1ff8e08e197af37344d8 Change-Id: Ifcf727b0c07c90e267b79828a8e3fd7a8260a074
-rw-r--r--doc/build/changelog/unreleased_13/5685.rst6
-rw-r--r--lib/sqlalchemy/dialects/sqlite/base.py28
-rw-r--r--test/dialect/test_sqlite.py10
3 files changed, 43 insertions, 1 deletions
diff --git a/doc/build/changelog/unreleased_13/5685.rst b/doc/build/changelog/unreleased_13/5685.rst
new file mode 100644
index 000000000..6f98cfa5d
--- /dev/null
+++ b/doc/build/changelog/unreleased_13/5685.rst
@@ -0,0 +1,6 @@
+.. change::
+ :tags: sqlite, usecase
+ :tickets: 5685
+
+ Added ``sqlite_with_rowid=False`` dialect keyword to enable creating
+ tables as ``CREATE TABLE … WITHOUT ROWID``. Patch courtesy Sean Anderson.
diff --git a/lib/sqlalchemy/dialects/sqlite/base.py b/lib/sqlalchemy/dialects/sqlite/base.py
index 5efd0d9c9..aead99147 100644
--- a/lib/sqlalchemy/dialects/sqlite/base.py
+++ b/lib/sqlalchemy/dialects/sqlite/base.py
@@ -583,6 +583,21 @@ or on a per-:class:`_engine.Engine` basis::
When using the per-:class:`_engine.Engine` execution option, note that
**Core and ORM queries that use UNION may not function properly**.
+SQLite-specific table options
+-----------------------------
+
+One option for CREATE TABLE is supported directly by the SQLite
+dialect in conjunction with the :class:`_schema.Table` construct:
+
+* ``WITHOUT ROWID``::
+
+ Table("some_table", metadata, ..., sqlite_with_rowid=False)
+
+.. seealso::
+
+ `SQLite CREATE TABLE options
+ <https://www.sqlite.org/lang_createtable.html>`_
+
""" # noqa
import datetime
@@ -1259,6 +1274,11 @@ class SQLiteDDLCompiler(compiler.DDLCompiler):
return text
+ def post_create_table(self, table):
+ if table.dialect_options["sqlite"]["with_rowid"] is False:
+ return "\n WITHOUT ROWID"
+ return ""
+
class SQLiteTypeCompiler(compiler.GenericTypeCompiler):
def visit_large_binary(self, type_, **kw):
@@ -1466,7 +1486,13 @@ class SQLiteDialect(default.DefaultDialect):
isolation_level = None
construct_arguments = [
- (sa_schema.Table, {"autoincrement": False}),
+ (
+ sa_schema.Table,
+ {
+ "autoincrement": False,
+ "with_rowid": True,
+ },
+ ),
(sa_schema.Index, {"where": None}),
(
sa_schema.Column,
diff --git a/test/dialect/test_sqlite.py b/test/dialect/test_sqlite.py
index d06cd48f5..57529aeb6 100644
--- a/test/dialect/test_sqlite.py
+++ b/test/dialect/test_sqlite.py
@@ -1161,6 +1161,16 @@ class SQLTest(fixtures.TestBase, AssertsCompiledSQL):
),
)
+ def test_create_table_without_rowid(self):
+ m = MetaData()
+ tbl = Table(
+ "atable", m, Column("id", Integer), sqlite_with_rowid=False
+ )
+ self.assert_compile(
+ schema.CreateTable(tbl),
+ "CREATE TABLE atable (id INTEGER) WITHOUT ROWID",
+ )
+
class OnConflictDDLTest(fixtures.TestBase, AssertsCompiledSQL):