.. admonition:: Section Best Practices Summarized
keep the ``search_path`` variable set to its default of ``public``, without
- any other schema names. For other schema names, name these explicitly
+ any other schema names. Ensure the username used to connect **does not**
+ match remote schemas, or ensure the ``"$user"`` token is **removed** from
+ ``search_path``. For other schema names, name these explicitly
within :class:`_schema.Table` definitions. Alternatively, the
``postgresql_ignore_search_path`` option will cause all reflected
:class:`_schema.Table` objects to have a :attr:`_schema.Table.schema`
The PostgreSQL dialect can reflect tables from any schema, as outlined in
:ref:`metadata_reflection_schemas`.
+In all cases, the first thing SQLAlchemy does when reflecting tables is
+to **determine the default schema for the current database connection**.
+It does this using the PostgreSQL ``current_schema()``
+function, illustated below using a PostgreSQL client session (i.e. using
+the ``psql`` tool)::
+
+ test=> select current_schema();
+ current_schema
+ ----------------
+ public
+ (1 row)
+
+Above we see that on a plain install of PostgreSQL, the default schema name
+is the name ``public``.
+
+However, if your database username **matches the name of a schema**, PostgreSQL's
+default is to then **use that name as the default schema**. Below, we log in
+using the username ``scott``. When we create a schema named ``scott``, **it
+implicitly changes the default schema**::
+
+ test=> select current_schema();
+ current_schema
+ ----------------
+ public
+ (1 row)
+
+ test=> create schema scott;
+ CREATE SCHEMA
+ test=> select current_schema();
+ current_schema
+ ----------------
+ scott
+ (1 row)
+
+The behavior of ``current_schema()`` is derived from the
+`PostgreSQL search path
+<https://www.postgresql.org/docs/current/static/ddl-schemas.html#DDL-SCHEMAS-PATH>`_
+variable ``search_path``, which in modern PostgreSQL versions defaults to this::
+
+ test=> show search_path;
+ search_path
+ -----------------
+ "$user", public
+ (1 row)
+
+Where above, the ``"$user"`` variable will inject the current username as the
+default schema, if one exists. Otherwise, ``public`` is used.
+
+When a :class:`_schema.Table` object is reflected, if it is present in the
+schema indicated by the ``current_schema()`` function, **the schema name assigned
+to the table is the Python value ``None``**. Otherwise, the schema name
+will be assigned as the name of that schema.
+
With regards to tables which these :class:`_schema.Table`
objects refer to via foreign key constraint, a decision must be made as to how
the ``.schema`` is represented in those remote tables, in the case where that
-remote schema name is also a member of the current
-`PostgreSQL search path
-<https://www.postgresql.org/docs/current/static/ddl-schemas.html#DDL-SCHEMAS-PATH>`_.
+remote schema name is also a member of the current ``search_path``.
By default, the PostgreSQL dialect mimics the behavior encouraged by
PostgreSQL's own ``pg_get_constraintdef()`` builtin procedure. This function
described here are only for those users who can't, or prefer not to, stay
within these guidelines.
-Note that **in all cases**, the "default" schema is always reflected as
-``None``. The "default" schema on PostgreSQL is that which is returned by the
-PostgreSQL ``current_schema()`` function. On a typical PostgreSQL
-installation, this is the name ``public``. So a table that refers to another
-which is in the ``public`` (i.e. default) schema will always have the
-``.schema`` attribute set to ``None``.
-
.. seealso::
:ref:`reflection_schema_qualified_interaction` - discussion of the issue