]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Clarify INSERT/UPDATE defaults vs. data marshalling
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 10 Aug 2019 22:17:59 +0000 (18:17 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 10 Aug 2019 22:59:11 +0000 (18:59 -0400)
- Add a full introductory paragraph to INSERT/UPDATE defaults
stating what we mean when we talk about this concept.  Add a note
differentiating what a default does, vs. a rule that intercepts
data as it moves into the database, providing links

- Add a quick section referring to TypeDecorator in the ORM
section on modifying attribute behavior

- Add an "ORM tip", a new thing that we can use in Core to link
to ORM concepts when useful, in the TypeDecorator section which
mentions that for more open ended conversion of arbitrary user
data based on business rules, @validates might be useful
(although this still does not suit the case of full blown form
validation).

- add glossary entries for DML, data marshalling since we already
use these terms and I'd like to refer to them more often.

Fixes: #4796
Change-Id: Ic4cd5c1595fd51c00a9bf24c021d2e56d457d346
(cherry picked from commit cda0b4a2b909be55cef7a844a04689ec527041c0)

doc/build/core/custom_types.rst
doc/build/core/defaults.rst
doc/build/core/events.rst
doc/build/glossary.rst
doc/build/orm/events.rst
doc/build/orm/mapped_attributes.rst

index 6bbc8fbbc3a49a6fd83d45b151815b910414f326..01902420a75e0901572f6d28374a70906decfae7 100644 (file)
@@ -42,8 +42,8 @@ Augmenting Existing Types
 
 The :class:`.TypeDecorator` allows the creation of custom types which
 add bind-parameter and result-processing behavior to an existing
-type object.  It is used when additional in-Python marshaling of data
-to and from the database is required.
+type object.  It is used when additional in-Python :term:`marshalling` of data
+to and/or from the database is required.
 
 .. note::
 
@@ -53,6 +53,16 @@ to and from the database is required.
   processing specific to that DBAPI.  To change the DBAPI-level processing
   for an existing type, see the section :ref:`replacing_processors`.
 
+.. topic:: ORM Tip
+
+   The :class:`.TypeDecorator` can be used to provide a consistent means of
+   converting some type of value as it is passed into and out of the database.
+   When using the ORM, a similar technique exists for converting user data
+   from arbitrary formats which is to use the :func:`.validates` decorator.
+   This technique may be more appropriate when data coming into an ORM model
+   needs to be normalized in some way that is specific to the business case
+   and isn't as generic as a datatype.
+
 .. autoclass:: TypeDecorator
    :members:
    :inherited-members:
index 7240efac069a535410747dcfbb6f9f151187e72f..cbfe27c33d58f26f25943e9567e9fbe8e7c61cc1 100644 (file)
@@ -4,11 +4,44 @@
 
 .. _metadata_defaults:
 
-Column Insert/Update Defaults
+Column INSERT/UPDATE Defaults
 =============================
 
-SQLAlchemy provides a very rich featureset regarding column level events which
-take place during INSERT and UPDATE statements. Options include:
+Column INSERT and UPDATE defaults refer to functions that create a **default
+value** for a particular column in a row as an INSERT or UPDATE statement is
+proceeding against that row, in the case where **no value was provided to the
+INSERT or UPDATE statement for that column**.  That is, if a table has a column
+called "timestamp", and an INSERT statement proceeds which does not include a
+value for this column, an INSERT default would create a new value, such as
+the current time, that is used as the value to be INSERTed into the "timestamp"
+column.  If the statement *does* include a value  for this column, then the
+default does *not* take place.
+
+Column defaults can be server-side functions or constant values which are
+defined in the database along with the schema in :term:`DDL`, or as SQL
+expressions which are rendered directly within an INSERT or UPDATE statement
+emitted by SQLAlchemy; they may also be client-side Python functions or
+constant values which are invoked by SQLAlchemy before data is passed to the
+database.
+
+.. note::
+
+    A column default handler should not be confused with a construct that
+    intercepts and modifies incoming values for INSERT and UPDATE statements
+    which *are* provided to the statement as it is invoked.  This is known
+    as :term:`data marshalling`, where a column value is modified in some way
+    by the application before being sent to the database.  SQLAlchemy provides
+    a few means of achieving this which include using :ref:`custom datatypes
+    <types_typedecorator>`, :ref:`SQL execution events <core_sql_events>` and
+    in the ORM :ref:`custom  validators <simple_validators>` as well as
+    :ref:`attribute events <orm_attribute_events>`.    Column defaults are only
+    invoked when there is **no value present** for a column in a SQL
+    :term:`DML` statement.
+
+
+SQLAlchemy provides an array of features regarding default generation
+functions which take place for non-present values during INSERT and UPDATE
+statements. Options include:
 
 * Scalar values used as defaults during INSERT and UPDATE operations
 * Python functions which execute upon INSERT and UPDATE operations
index 1dc56b053b063b5527c2bbc295222e05e8645fd8..4452ae7f5839b700c5144e9c5e4a98409536b2c1 100644 (file)
@@ -17,6 +17,8 @@ Connection Pool Events
 .. autoclass:: sqlalchemy.events.PoolEvents
    :members:
 
+.. _core_sql_events:
+
 SQL Execution and Connection Events
 -----------------------------------
 
index 2187d626154c463ccf6f9fe6910ecfecb0903da4..1881a9e7a60f28beb45f3c532d40a0b0d800ead8 100644 (file)
@@ -36,6 +36,24 @@ Glossary
         also known as :term:`DML`, and typically refers to the ``INSERT``,
         ``UPDATE``, and ``DELETE`` statements.
 
+    marshalling
+    data marshalling
+         The process of transforming the memory representation of an object to
+         a data format suitable for storage or transmission to another part of
+         a system, when data must be moved between different parts of a
+         computer program or from one program to another.   In terms of
+         SQLAlchemy, we often need to "marshal" data into a format appropriate
+         for passing into the relational database.
+
+         .. seealso::
+
+            `Marshalling (via Wikipedia) <https://en.wikipedia.org/wiki/Marshalling_(computer_science)>`_
+
+            :ref:`types_typedecorator` - SQLAlchemy's :class:`.TypeDecorator`
+            is commonly used for data marshalling as data is sent into the
+            database for INSERT and UPDATE statements, and "unmarshalling"
+            data as it is retrieved using SELECT statements.
+
     descriptor
     descriptors
         In Python, a descriptor is an object attribute with “binding behavior”, one whose attribute access has been overridden by methods in the `descriptor protocol <http://docs.python.org/howto/descriptor.html>`_.
@@ -76,7 +94,7 @@ Glossary
             "some data"
 
     DDL
-        An acronym for *Data Definition Language*.  DDL is the subset
+        An acronym for **Data Definition Language**.  DDL is the subset
         of SQL that relational databases use to configure tables, constraints,
         and other permanent objects within a database schema.  SQLAlchemy
         provides a rich API for constructing and emitting DDL expressions.
@@ -87,6 +105,22 @@ Glossary
 
             `DDL (via Wikipedia) <http://en.wikipedia.org/wiki/Data_definition_language>`_
 
+            :term:`DML`
+
+
+    DML
+       An acronym for **Data Manipulation Language**.  DML is the subset of
+       SQL that relational databases use to *modify* the data in tables. DML
+       typically refers to the three widely familiar statements of INSERT,
+       UPDATE and  DELETE, otherwise known as :term:`CRUD` (acronoym for "CReate,
+       Update, Delete").
+
+        .. seealso::
+
+            `DML (via Wikipedia) <http://en.wikipedia.org/wiki/Data_manipulation_language>`_
+
+            :term:`DDL`
+
     discriminator
         A result-set column which is used during :term:`polymorphic` loading
         to determine what kind of mapped class should be applied to a particular
index d373f253ee1feda9e0c54ef2249b47faee7c0b4b..ecf0cc65bdf90602019879893d03c43109b196f1 100644 (file)
@@ -10,6 +10,8 @@ For an introduction to the most commonly used ORM events, see the section
 at :ref:`event_toplevel`.  Non-ORM events such as those regarding connections
 and low-level statement execution are described in :ref:`core_event_toplevel`.
 
+.. _orm_attribute_events:
+
 Attribute Events
 ----------------
 
index 8a451084934fcc2e1efed2d6b3ec4c3d837f7828..bce40bfb4910b86216f90f052e5604a31d140951 100644 (file)
@@ -101,6 +101,18 @@ described at :class:`~.AttributeEvents`.
 
 .. autofunction:: validates
 
+Using Custom Datatypes at the Core Level
+-----------------------------------------
+
+A non-ORM means of affecting the value of a column in a way that suits
+converting data between how it is represented in Python, vs. how it is
+represented in the database, can be achieved by using a custom datatype that is
+applied to the mapped :class:`.Table` metadata.     This is more common in the
+case of some style of encoding / decoding that occurs both as data goes to the
+database and as it is returned; read more about this in the Core documentation
+at :ref:`types_typedecorator`.
+
+
 .. _mapper_hybrids:
 
 Using Descriptors and Hybrids