]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
document missing ColumnCollection methods
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 14 Jun 2021 01:08:24 +0000 (21:08 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 14 Jun 2021 01:34:43 +0000 (21:34 -0400)
add additional notes regarding the methods that are on this
object.

Fixes: #6629
Change-Id: I68446cb16cbfcef9af9c2998687b3b536607cf0d

doc/build/core/metadata.rst
lib/sqlalchemy/dialects/mysql/dml.py
lib/sqlalchemy/dialects/postgresql/dml.py
lib/sqlalchemy/dialects/sqlite/dml.py
lib/sqlalchemy/sql/base.py

index 8f869c91c8e16e57b0683268b4bf4b222fdc4ec7..e37ada4c8d161f79cb95515643cb9afa691a22de 100644 (file)
@@ -47,6 +47,8 @@ to genericized types, such as :class:`~sqlalchemy.types.Integer` and
 varying levels of specificity as well as the ability to create custom types.
 Documentation on the type system can be found at :ref:`types_toplevel`.
 
+.. _metadata_tables_and_columns:
+
 Accessing Tables and Columns
 ----------------------------
 
@@ -82,7 +84,7 @@ this construct defines a reference to a remote table, and is fully described
 in :ref:`metadata_foreignkeys`. Methods of accessing information about this
 table include::
 
-    # access the column "EMPLOYEE_ID":
+    # access the column "employee_id":
     employees.columns.employee_id
 
     # or just
@@ -126,6 +128,20 @@ table include::
     # get the table related by a foreign key
     list(employees.c.employee_dept.foreign_keys)[0].column.table
 
+.. tip::
+
+  The :attr:`_sql.FromClause.c` collection, synonymous with the
+  :attr:`_sql.FromClause.columns` collection, is an instance of
+  :class:`_sql.ColumnCollection`, which provides a **dictionary-like interface**
+  to the collection of columns.   Names are ordinarily accessed like
+  attribute names, e.g. ``employees.c.employee_name``.  However for special names
+  with spaces or those that match the names of dictionary methods such as
+  :meth:`_sql.ColumnCollection.keys` or :meth:`_sql.ColumnCollection.values`,
+  indexed access must be used, such as ``employees.c['values']`` or
+  ``employees.c["some column"]``.  See :class:`_sql.ColumnCollection` for
+  further information.
+
+
 Creating and Dropping Database Tables
 -------------------------------------
 
index d57a8909087cb9ea0507d0ad2f1af6d26796fd1d..e2f78783c22fa25011472891f5415dc8e86a9a93 100644 (file)
@@ -38,6 +38,17 @@ class Insert(StandardInsert):
         so as not to conflict with the existing
         :meth:`_expression.Insert.values` method.
 
+        .. tip::  The :attr:`_mysql.Insert.inserted` attribute is an instance
+            of :class:`_expression.ColumnCollection`, which provides an
+            interface the same as that of the :attr:`_schema.Table.c`
+            collection described at :ref:`metadata_tables_and_columns`.
+            With this collection, ordinary names are accessible like attributes
+            (e.g. ``stmt.inserted.some_column``), but special names and
+            dictionary method names should be accessed using indexed access,
+            such as ``stmt.inserted["column name"]`` or
+            ``stmt.inserted["values"]``.  See the docstring for
+            :class:`_expression.ColumnCollection` for further examples.
+
         .. seealso::
 
             :ref:`mysql_insert_on_duplicate_key_update` - example of how
index b6f5cdf7e04156a5488a46feef110a983fefcabc..c98bc9f763ecc860c8e1e8493099c359606387ec 100644 (file)
@@ -44,6 +44,17 @@ class Insert(StandardInsert):
         be inserted, known as ``excluded``.  This attribute provides
         all columns in this row to be referenceable.
 
+        .. tip::  The :attr:`_postgresql.Insert.excluded` attribute is an
+            instance of :class:`_expression.ColumnCollection`, which provides
+            an interface the same as that of the :attr:`_schema.Table.c`
+            collection described at :ref:`metadata_tables_and_columns`.
+            With this collection, ordinary names are accessible like attributes
+            (e.g. ``stmt.excluded.some_column``), but special names and
+            dictionary method names should be accessed using indexed access,
+            such as ``stmt.excluded["column name"]`` or
+            ``stmt.excluded["values"]``.   See the docstring for
+            :class:`_expression.ColumnCollection` for further examples.
+
         .. seealso::
 
             :ref:`postgresql_insert_on_conflict` - example of how
index 4cb819960ad8b42a8ebadd62a635e4c4e480989b..a444c34c09dcf8a078b85a87145479165710d9cb 100644 (file)
@@ -45,6 +45,17 @@ class Insert(StandardInsert):
         be inserted, known as ``excluded``.  This attribute provides
         all columns in this row to be referenceable.
 
+        .. tip::  The :attr:`_sqlite.Insert.excluded` attribute is an instance
+            of :class:`_expression.ColumnCollection`, which provides an
+            interface the same as that of the :attr:`_schema.Table.c`
+            collection described at :ref:`metadata_tables_and_columns`.
+            With this collection, ordinary names are accessible like attributes
+            (e.g. ``stmt.excluded.some_column``), but special names and
+            dictionary method names should be accessed using indexed access,
+            such as ``stmt.excluded["column name"]`` or
+            ``stmt.excluded["values"]``.  See the docstring for
+            :class:`_expression.ColumnCollection` for further examples.
+
         """
         return alias(self.table, name="excluded").columns
 
index b7df927f150352aa4c268cf6cabab766dda1c302..d7f5e1c0e5c0eded3a0cfeb5dafd901f705c0dce 100644 (file)
@@ -1035,31 +1035,54 @@ class SchemaVisitor(ClauseVisitor):
 class ColumnCollection(object):
     """Collection of :class:`_expression.ColumnElement` instances,
     typically for
-    selectables.
-
-    The :class:`_expression.ColumnCollection`
-    has both mapping- and sequence- like
-    behaviors.   A :class:`_expression.ColumnCollection` usually stores
-    :class:`_schema.Column`
-    objects, which are then accessible both via mapping style access as well
-    as attribute access style.  The name for which a :class:`_schema.Column`
-    would
-    be present is normally that of the :paramref:`_schema.Column.key`
-    parameter,
-    however depending on the context, it may be stored under a special label
-    name::
-
-        >>> from sqlalchemy import Column, Integer
-        >>> from sqlalchemy.sql import ColumnCollection
-        >>> x, y = Column('x', Integer), Column('y', Integer)
-        >>> cc = ColumnCollection(columns=[(x.name, x), (y.name, y)])
-        >>> cc.x
-        Column('x', Integer(), table=None)
-        >>> cc.y
-        Column('y', Integer(), table=None)
-        >>> cc['x']
-        Column('x', Integer(), table=None)
-        >>> cc['y']
+    :class:`_sql.FromClause` objects.
+
+    The :class:`_sql.ColumnCollection` object is most commonly available
+    as the :attr:`_schema.Table.c` or :attr:`_schema.Table.columns` collection
+    on the :class:`_schema.Table` object, introduced at
+    :ref:`metadata_tables_and_columns`.
+
+    The :class:`_expression.ColumnCollection` has both mapping- and sequence-
+    like behaviors. A :class:`_expression.ColumnCollection` usually stores
+    :class:`_schema.Column` objects, which are then accessible both via mapping
+    style access as well as attribute access style.
+
+    To access :class:`_schema.Column` objects using ordinary attribute-style
+    access, specify the name like any other object attribute, such as below
+    a column named ``employee_name`` is accessed::
+
+        >>> employee_table.c.employee_name
+
+    To access columns that have names with special characters or spaces,
+    index-style access is used, such as below which illustrates a column named
+    ``employee ' payment`` is accessed::
+
+        >>> employee_table.c["employee ' payment"]
+
+    As the :class:`_sql.ColumnCollection` object provides a Python dictionary
+    interface, common dictionary method names like
+    :meth:`_sql.ColumnCollection.keys`, :meth:`_sql.ColumnCollection.values`,
+    and :meth:`_sql.ColumnCollection.items` are available, which means that
+    database columns that are keyed under these names also need to use indexed
+    access::
+
+        >>> employee_table.c["values"]
+
+
+    The name for which a :class:`_schema.Column` would be present is normally
+    that of the :paramref:`_schema.Column.key` parameter.  In some contexts,
+    such as a :class:`_sql.Select` object that uses a label style set
+    using the :meth:`_sql.Select.set_label_style` method, a column of a certain
+    key may instead be represented under a particular label name such
+    as ``tablename_columnname``::
+
+        >>> from sqlalchemy import select, column, table
+        >>> from sqlalchemy import LABEL_STYLE_TABLENAME_PLUS_COL
+        >>> t = table("t", column("c"))
+        >>> stmt = select(t).set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL)
+        >>> subq = stmt.subquery()
+        >>> subq.c.t_c
+        <sqlalchemy.sql.elements.ColumnClause at 0x7f59dcf04fa0; t_c>
 
     :class:`.ColumnCollection` also indexes the columns in order and allows
     them to be accessible by their integer position::
@@ -1135,12 +1158,23 @@ class ColumnCollection(object):
         return [col for (k, col) in self._collection]
 
     def keys(self):
+        """Return a sequence of string key names for all columns in this
+        collection."""
         return [k for (k, col) in self._collection]
 
     def values(self):
+        """Return a sequence of :class:`_sql.ColumnClause` or
+        :class:`_schema.Column` objects for all columns in this
+        collection."""
         return [col for (k, col) in self._collection]
 
     def items(self):
+        """Return a sequence of (key, column) tuples for all columns in this
+        collection each consisting of a string key name and a
+        :class:`_sql.ColumnClause` or
+        :class:`_schema.Column` object.
+        """
+
         return list(self._collection)
 
     def __bool__(self):
@@ -1179,6 +1213,9 @@ class ColumnCollection(object):
             return True
 
     def compare(self, other):
+        """Compare this :class:`_expression.ColumnCollection` to another
+        based on the names of the keys"""
+
         for l, r in util.zip_longest(self, other):
             if l is not r:
                 return False
@@ -1189,6 +1226,10 @@ class ColumnCollection(object):
         return self.compare(other)
 
     def get(self, key, default=None):
+        """Get a :class:`_sql.ColumnClause` or :class:`_schema.Column` object
+        based on a string key name from this
+        :class:`_expression.ColumnCollection`."""
+
         if key in self._index:
             return self._index[key]
         else:
@@ -1210,12 +1251,18 @@ class ColumnCollection(object):
         raise NotImplementedError()
 
     def clear(self):
+        """Dictionary clear() is not implemented for
+        :class:`_sql.ColumnCollection`."""
         raise NotImplementedError()
 
     def remove(self, column):
+        """Dictionary remove() is not implemented for
+        :class:`_sql.ColumnCollection`."""
         raise NotImplementedError()
 
     def update(self, iter_):
+        """Dictionary update() is not implemented for
+        :class:`_sql.ColumnCollection`."""
         raise NotImplementedError()
 
     __hash__ = None
@@ -1231,6 +1278,17 @@ class ColumnCollection(object):
         self._index.update({k: col for k, col in reversed(self._collection)})
 
     def add(self, column, key=None):
+        """Add a column to this :class:`_sql.ColumnCollection`.
+
+        .. note::
+
+            This method is **not normally used by user-facing code**, as the
+            :class:`_sql.ColumnCollection` is usually part of an existing
+            object such as a :class:`_schema.Table`. To add a
+            :class:`_schema.Column` to an existing :class:`_schema.Table`
+            object, use the :meth:`_schema.Table.append_column` method.
+
+        """
         if key is None:
             key = column.key
 
@@ -1264,6 +1322,9 @@ class ColumnCollection(object):
             return True
 
     def as_immutable(self):
+        """Return an "immutable" form of this
+        :class:`_sql.ColumnCollection`."""
+
         return ImmutableColumnCollection(self)
 
     def corresponding_column(self, column, require_embedded=False):