]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Don't pre-calc inserted primary key if no getter
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 10 Feb 2021 15:36:52 +0000 (10:36 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 10 Feb 2021 15:36:52 +0000 (10:36 -0500)
the _setup_ins_pk_from_empty() method provides a placeholder
result for inserted_primary_key_rows that is not typically
going to be invoked.  For an executemany (or even execute)
that isn't already stating it wants primary key values
up front, defer this computation until explicitly requested.

Change-Id: I6295eafbccc96a0422b9cac34e79db7924c702ca
References: https://github.com/sqlalchemy/sqlalchemy/discussions/5893#discussioncomment-356155

lib/sqlalchemy/engine/default.py

index 0c48fcba3fa89e5615aab1ee04e52233553662e4..7391e7b01ac578e58fbdf349bb9e3aa78a6ad5ac 100644 (file)
@@ -1421,9 +1421,12 @@ class DefaultExecutionContext(interfaces.ExecutionContext):
     def _setup_dml_or_text_result(self):
         if self.isinsert:
             if self.compiled.postfetch_lastrowid:
-                self._setup_ins_pk_from_lastrowid()
-            elif not self._is_implicit_returning:
-                self._setup_ins_pk_from_empty()
+                self.inserted_primary_key_rows = (
+                    self._setup_ins_pk_from_lastrowid()
+                )
+            # else if not self._is_implicit_returning,
+            # the default inserted_primary_key_rows accessor will
+            # return an "empty" primary key collection when accessed.
 
         strategy = self.cursor_fetch_strategy
         if self._is_server_side and strategy is _cursor._DEFAULT_FETCH:
@@ -1449,7 +1452,9 @@ class DefaultExecutionContext(interfaces.ExecutionContext):
 
                 self.returned_default_rows = rows
 
-                self._setup_ins_pk_from_implicit_returning(result, rows)
+                self.inserted_primary_key_rows = (
+                    self._setup_ins_pk_from_implicit_returning(result, rows)
+                )
 
                 # test that it has a cursor metadata that is accurate. the
                 # first row will have been fetched and current assumptions
@@ -1483,33 +1488,34 @@ class DefaultExecutionContext(interfaces.ExecutionContext):
             result._soft_close()
         return result
 
+    @util.memoized_property
+    def inserted_primary_key_rows(self):
+        # if no specific "get primary key" strategy was set up
+        # during execution, return a "default" primary key based
+        # on what's in the compiled_parameters and nothing else.
+        return self._setup_ins_pk_from_empty()
+
     def _setup_ins_pk_from_lastrowid(self):
 
         getter = self.compiled._inserted_primary_key_from_lastrowid_getter
 
         lastrowid = self.get_lastrowid()
-        self.inserted_primary_key_rows = [
-            getter(lastrowid, self.compiled_parameters[0])
-        ]
+        return [getter(lastrowid, self.compiled_parameters[0])]
 
     def _setup_ins_pk_from_empty(self):
-
         getter = self.compiled._inserted_primary_key_from_lastrowid_getter
 
-        self.inserted_primary_key_rows = [
-            getter(None, param) for param in self.compiled_parameters
-        ]
+        return [getter(None, param) for param in self.compiled_parameters]
 
     def _setup_ins_pk_from_implicit_returning(self, result, rows):
 
         if not rows:
-            self.inserted_primary_key_rows = []
-            return
+            return []
 
         getter = self.compiled._inserted_primary_key_from_returning_getter
         compiled_params = self.compiled_parameters
 
-        self.inserted_primary_key_rows = [
+        return [
             getter(row, param) for row, param in zip(rows, compiled_params)
         ]