]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Reflect included columns as dialect_options
authorGord Thompson <gord@gordthompson.com>
Mon, 20 Dec 2021 21:37:13 +0000 (14:37 -0700)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 27 Dec 2021 18:26:42 +0000 (13:26 -0500)
Fixed reflection of covering indexes to report ``include_columns`` as part
of the ``dialect_options`` entry in the reflected index dictionary, thereby
enabling round trips from reflection->create to be complete. Included
columns continue to also be present under the ``include_columns`` key for
backwards compatibility.

Fixes: #7382
Change-Id: I4f16b65caed3a36d405481690a3a92432b5efd62
(cherry picked from commit 52e352a190af750c3c28a5390b2ad55b20d1b752)

doc/build/changelog/unreleased_14/7382.rst [new file with mode: 0644]
lib/sqlalchemy/dialects/mssql/base.py
lib/sqlalchemy/dialects/postgresql/base.py
lib/sqlalchemy/testing/suite/test_reflection.py
test/dialect/postgresql/test_reflection.py

diff --git a/doc/build/changelog/unreleased_14/7382.rst b/doc/build/changelog/unreleased_14/7382.rst
new file mode 100644 (file)
index 0000000..db6ae45
--- /dev/null
@@ -0,0 +1,9 @@
+.. change::
+    :tags: bug, reflection, postgresql, mssql
+    :tickets: 7382
+
+    Fixed reflection of covering indexes to report ``include_columns`` as part
+    of the ``dialect_options`` entry in the reflected index dictionary, thereby
+    enabling round trips from reflection->create to be complete. Included
+    columns continue to also be present under the ``include_columns`` key for
+    backwards compatibility.
index d6a35c93768d528e19ea8364f0e8cb44f4ff5095..defff295284de1c2a88cc6ab6eca4dd7ba34bb22 100644 (file)
@@ -3070,6 +3070,12 @@ class MSDialect(default.DefaultDialect):
                     indexes[row["index_id"]]["column_names"].append(
                         row["name"]
                     )
+        for index_info in indexes.values():
+            # NOTE: "root level" include_columns is legacy, now part of
+            #       dialect_options (issue #7382)
+            index_info.setdefault("dialect_options", {})[
+                "mssql_include"
+            ] = index_info["include_columns"]
 
         return list(indexes.values())
 
index e58e430e85dc134e27c10a66bfede36d48d5c0a5..4273ff474af290ed3657c55050bca13f08ca56d5 100644 (file)
@@ -4277,6 +4277,8 @@ class PGDialect(default.DefaultDialect):
                 "column_names": [idx["cols"][i] for i in idx["key"]],
             }
             if self.server_version_info >= (11, 0):
+                # NOTE: this is legacy, this is part of dialect_options now
+                # as of #7382
                 entry["include_columns"] = [idx["cols"][i] for i in idx["inc"]]
             if "duplicates_constraint" in idx:
                 entry["duplicates_constraint"] = idx["duplicates_constraint"]
@@ -4285,6 +4287,10 @@ class PGDialect(default.DefaultDialect):
                     (idx["cols"][idx["key"][i]], value)
                     for i, value in idx["sorting"].items()
                 )
+            if "include_columns" in entry:
+                entry.setdefault("dialect_options", {})[
+                    "postgresql_include"
+                ] = entry["include_columns"]
             if "options" in idx:
                 entry.setdefault("dialect_options", {})[
                     "postgresql_with"
index 6e6201de977e5443fb555647123266d792d99241..a1f2e3bc94b05a7748d9a26b8ed13cd074064ee6 100644 (file)
@@ -1206,6 +1206,9 @@ class ComponentReflectionTestExtra(fixtures.TestBase):
         ]
         if testing.requires.index_reflects_included_columns.enabled:
             expected[0]["include_columns"] = []
+            expected[0]["dialect_options"] = {
+                "%s_include" % connection.engine.name: []
+            }
 
         with expect_warnings(
             "Skipped unsupported reflection of expression-based index t_idx"
@@ -1238,10 +1241,21 @@ class ComponentReflectionTestExtra(fixtures.TestBase):
                     "column_names": ["x"],
                     "include_columns": ["y"],
                     "unique": False,
+                    "dialect_options": {
+                        "%s_include" % connection.engine.name: ["y"]
+                    },
                 }
             ],
         )
 
+        t2 = Table("t", MetaData(), autoload_with=connection)
+        eq_(
+            list(t2.indexes)[0].dialect_options[connection.engine.name][
+                "include"
+            ],
+            ["y"],
+        )
+
     def _type_round_trip(self, connection, metadata, *types):
         t = Table(
             "t",
index fa90ec212fcfaa03cd064aaa52df019f56eba48f..5ee11ccd8c93f2878bccb447f99ffbdca2f21f39 100644 (file)
@@ -183,6 +183,7 @@ class PartitionedReflectionTest(fixtures.TablesTest, AssertsExecutionResults):
                     "unique": False,
                     "column_names": ["q"],
                     "include_columns": [],
+                    "dialect_options": {"postgresql_include": []},
                 }
             ],
         )
@@ -198,6 +199,7 @@ class PartitionedReflectionTest(fixtures.TablesTest, AssertsExecutionResults):
                 {
                     "column_names": ["q"],
                     "include_columns": [],
+                    "dialect_options": {"postgresql_include": []},
                     "name": mock.ANY,
                     "unique": False,
                 }
@@ -1131,6 +1133,7 @@ class ReflectionTest(
         expected = [{"name": "idx1", "unique": False, "column_names": ["y"]}]
         if testing.requires.index_reflects_included_columns.enabled:
             expected[0]["include_columns"] = []
+            expected[0]["dialect_options"] = {"postgresql_include": []}
 
         eq_(ind, expected)
 
@@ -1163,6 +1166,7 @@ class ReflectionTest(
         ]
         if testing.requires.index_reflects_included_columns.enabled:
             expected[0]["include_columns"] = []
+            expected[0]["dialect_options"]["postgresql_include"] = []
         eq_(ind, expected)
 
         m = MetaData()
@@ -1195,6 +1199,7 @@ class ReflectionTest(
         ]
         if testing.requires.index_reflects_included_columns.enabled:
             expected[0]["include_columns"] = []
+            expected[0]["dialect_options"]["postgresql_include"] = []
         eq_(ind, expected)
         m = MetaData()
         t1 = Table("t", m, autoload_with=connection)
@@ -1229,6 +1234,7 @@ class ReflectionTest(
                     "unique": False,
                     "column_names": ["x"],
                     "include_columns": ["name"],
+                    "dialect_options": {"postgresql_include": ["name"]},
                     "name": "idx1",
                 }
             ],
@@ -1604,6 +1610,7 @@ class ReflectionTest(
         ]
         if testing.requires.index_reflects_included_columns.enabled:
             expected[0]["include_columns"] = []
+            expected[0]["dialect_options"]["postgresql_include"] = []
 
         eq_(insp.get_indexes("t"), expected)