]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Add proper code block formatting
authorFederico Caselli <cfederico87@gmail.com>
Sat, 1 Oct 2022 21:49:55 +0000 (23:49 +0200)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 2 Oct 2022 15:51:02 +0000 (11:51 -0400)
Change-Id: I63585eeae0b0bc78109da64520696928dfb3982c

40 files changed:
doc/build/changelog/changelog_07.rst
doc/build/changelog/changelog_08.rst
doc/build/changelog/migration_04.rst
doc/build/changelog/migration_05.rst
doc/build/changelog/migration_06.rst
doc/build/changelog/migration_07.rst
doc/build/changelog/migration_08.rst
doc/build/changelog/migration_09.rst
doc/build/changelog/migration_10.rst
doc/build/changelog/migration_11.rst
doc/build/changelog/migration_12.rst
doc/build/changelog/migration_13.rst
doc/build/changelog/migration_14.rst
doc/build/changelog/migration_20.rst
doc/build/changelog/whatsnew_20.rst
doc/build/core/connections.rst
doc/build/core/constraints.rst
doc/build/core/custom_types.rst
doc/build/core/ddl.rst
doc/build/core/defaults.rst
doc/build/core/engines.rst
doc/build/core/reflection.rst
doc/build/errors.rst
doc/build/faq/ormconfiguration.rst
doc/build/faq/performance.rst
doc/build/faq/sessions.rst
doc/build/faq/sqlexpressions.rst
doc/build/glossary.rst
doc/build/intro.rst
doc/build/orm/cascades.rst
doc/build/orm/composites.rst
doc/build/orm/join_conditions.rst
doc/build/orm/persistence_techniques.rst
doc/build/orm/queryguide/relationships.rst
doc/build/orm/session_state_management.rst
doc/build/orm/versioning.rst
doc/build/requirements.txt
doc/build/tutorial/data_select.rst
doc/build/tutorial/orm_data_manipulation.rst
tools/format_docs_code.py

index 77757317f2a2bed875fac7277a6f309490314e17..300985f02155036d139f1216e7f0717215ab07a6 100644 (file)
       to Engine, Connection::
 
           with engine.begin() as conn:
-              <work with conn in a transaction>
+              # <work with conn in a transaction>
+              ...
 
       and::
 
           with engine.connect() as conn:
-              <work with conn>
+              # <work with conn>
+              ...
 
       Both close out the connection when done,
       commit or rollback transaction with errors
index 4164e3f5877f065a1cc949e73c9a2f41aada6a50..363f5aeb1b8937abbe1c360a102c68366680bab1 100644 (file)
 
       Will maintain the columns clause of the SELECT as coming from the
       unaliased "user", as specified; the select_from only takes place in the
-      FROM clause::
+      FROM clause:
+
+      .. sourcecode:: sql
 
         SELECT users.name AS users_name FROM users AS users_1
         JOIN users ON users.name < users_1.name
 
         session.query(User.name).select_from(user_table.select().where(user_table.c.id > 5))
 
-      Which produces::
+      Which produces:
+
+      .. sourcecode:: sql
 
         SELECT anon_1.name AS anon_1_name FROM (SELECT users.id AS id,
         users.name AS name FROM users WHERE users.id > :id_1) AS anon_1
index f68c449084adc4e51fe5a50545f136516c5d7ef5..2618c77e3a31af95c9a65894235ac2b44d441fd1 100644 (file)
@@ -168,14 +168,15 @@ We've had join() and outerjoin() for a while now:
 
 ::
 
-    session.query(Order).join('items')...
+    session.query(Order).join("items")
 
 Now you can alias them:
 
 ::
 
-    session.query(Order).join('items', aliased=True).
-       filter(Item.name='item 1').join('items', aliased=True).filter(Item.name=='item 3')
+    session.query(Order).join("items", aliased=True).filter(Item.name="item 1").join(
+        "items", aliased=True
+    ).filter(Item.name == "item 3")
 
 The above will create two joins from orders->items using
 aliases.  the ``filter()`` call subsequent to each will
@@ -185,9 +186,13 @@ join with an ``id``:
 
 ::
 
-    session.query(Order).join('items', id='j1', aliased=True).
-    filter(Item.name == 'item 1').join('items', aliased=True, id='j2').
-    filter(Item.name == 'item 3').add_entity(Item, id='j1').add_entity(Item, id='j2')
+    session.query(Order).join("items", id="j1", aliased=True).filter(
+        Item.name == "item 1"
+    ).join("items", aliased=True, id="j2").filter(Item.name == "item 3").add_entity(
+        Item, id="j1"
+    ).add_entity(
+        Item, id="j2"
+    )
 
 Returns tuples in the form: ``(Order, Item, Item)``.
 
@@ -308,7 +313,7 @@ So what happens when we say:
 
 ?  A join along aliases, three levels deep off the parent:
 
-::
+.. sourcecode:: sql
 
     SELECT
     nodes_3.id AS nodes_3_id, nodes_3.parent_id AS nodes_3_parent_id, nodes_3.name AS nodes_3_name,
@@ -545,7 +550,7 @@ columns or subqueries:
 
 a typical query looks like:
 
-::
+.. sourcecode:: sql
 
     SELECT (SELECT count(1) FROM posts WHERE users.id = posts.user_id) AS count,
     users.firstname || users.lastname AS fullname,
@@ -818,7 +823,7 @@ In the 0.3.x series, ``BoundMetaData`` and
 and ``ThreadLocalMetaData``.  The older names have been
 removed in 0.4.  Updating is simple:
 
-::
+.. sourcecode:: text
 
     +-------------------------------------+-------------------------+
     |If You Had                           | Now Use                 |
index b8f6c0d5f8b2175d4fbeb31bc6a7db59d8217fc0..d26a22c0d0023e65d8ef8245912c830f1b0d52b5 100644 (file)
@@ -444,7 +444,7 @@ Schema/Types
   ::
 
       class MyType(AdaptOldConvertMethods, TypeEngine):
-        ..
+          ...
 
 * The ``quote`` flag on ``Column`` and ``Table`` as well as
   the ``quote_schema`` flag on ``Table`` now control quoting
@@ -492,7 +492,7 @@ Schema/Types
   datetime columns to store the new format (NOTE: please
   test this, I'm pretty sure its correct):
 
-  ::
+  .. sourcecode:: sql
 
        UPDATE mytable SET somedatecol =
          substr(somedatecol, 0, 19) || '.' || substr((substr(somedatecol, 21, -1) / 1000000), 3, -1);
index 73c57bd9311a42a9f0b5a6118cc35f88dbb1c9b2..81263dade855859d5bccdb0885899534be0fed8d 100644 (file)
@@ -1037,7 +1037,7 @@ Many-to-one Enhancements
 
   would produce SQL like:
 
-  ::
+  .. sourcecode:: sql
 
       SELECT * FROM
         (SELECT * FROM addresses LIMIT 10) AS anon_1
@@ -1053,7 +1053,7 @@ Many-to-one Enhancements
   eager loaders represent many-to-ones, in which case the
   eager joins don't affect the rowcount:
 
-  ::
+  .. sourcecode:: sql
 
       SELECT * FROM addresses LEFT OUTER JOIN users AS users_1 ON users_1.id = addresses.user_id LIMIT 10
 
index 590da6812522fe7c7f34befcdcb3cae30f35c00e..19716ad3c4c39fffe2cebefa0ac0d10d282844f1 100644 (file)
@@ -404,7 +404,7 @@ tutorial:
 
 SQL:
 
-::
+.. sourcecode:: sql
 
     SELECT empsalary.depname, empsalary.empno, empsalary.salary,
     avg(empsalary.salary) OVER (PARTITION BY empsalary.depname) AS avg
@@ -513,7 +513,7 @@ call.
 The SQL emitted by ``query.count()`` is now always of the
 form:
 
-::
+.. sourcecode:: sql
 
     SELECT count(1) AS count_1 FROM (
         SELECT user.id AS user_id, user.name AS user_name from user
@@ -984,7 +984,7 @@ behavior:
 
 In 0.6, this would render:
 
-::
+.. sourcecode:: sql
 
     SELECT parent.id AS parent_id
     FROM parent
@@ -992,7 +992,7 @@ In 0.6, this would render:
 
 in 0.7, you get:
 
-::
+.. sourcecode:: sql
 
     SELECT parent.id AS parent_id
     FROM parent, child
@@ -1012,7 +1012,7 @@ same manner as that of 0.5 and 0.6:
 
 Which on both 0.6 and 0.7 renders:
 
-::
+.. sourcecode:: sql
 
     SELECT parent.id AS parent_id, child.id AS child_id
     FROM parent LEFT OUTER JOIN child ON parent.id = child.id
index 4a07518539b8aa3ac9ddf0369c2f1216958f8be2..3faecf08f33d1007b1788652b2938d17520e752d 100644 (file)
@@ -120,7 +120,7 @@ entities.  The new system includes these features:
   statement.  Note the join condition within a basic eager
   load:
 
-  ::
+  .. sourcecode:: sql
 
         SELECT
             folder.account_id AS folder_account_id,
@@ -566,7 +566,7 @@ given ``Engineer`` as a joined subclass of ``Person``:
 
 would produce:
 
-::
+.. sourcecode:: sql
 
     UPDATE engineer SET engineer_data='java' FROM person
     WHERE person.id=engineer.id AND person.name='dilbert'
@@ -597,7 +597,9 @@ as well as support for distributed locking.
 
 Note that the SQLAlchemy APIs used by the Dogpile example as well
 as the previous Beaker example have changed slightly, in particular
-this change is needed as illustrated in the Beaker example::
+this change is needed as illustrated in the Beaker example:
+
+.. sourcecode:: diff
 
     --- examples/beaker_caching/caching_query.py
     +++ examples/beaker_caching/caching_query.py
@@ -614,7 +616,7 @@ this change is needed as illustrated in the Beaker example::
 
 .. seealso::
 
-    :mod:`dogpile_caching`
+    :ref:`examples_caching`
 
 :ticket:`2589`
 
@@ -1199,22 +1201,29 @@ objects relative to what's being selected::
 
     print(s)
 
-Prior to this change, the above would return::
+Prior to this change, the above would return:
+
+.. sourcecode:: sql
 
     SELECT t1.x, t2.y FROM t2
 
 which is invalid SQL as "t1" is not referred to in any FROM clause.
 
-Now, in the absence of an enclosing SELECT, it returns::
+Now, in the absence of an enclosing SELECT, it returns:
+
+.. sourcecode:: sql
 
     SELECT t1.x, t2.y FROM t1, t2
 
-Within a SELECT, the correlation takes effect as expected::
+Within a SELECT, the correlation takes effect as expected:
 
-    s2 = select([t1, t2]).where(t1.c.x == t2.c.y).where(t1.c.x == s)
+.. sourcecode:: python
 
+    s2 = select([t1, t2]).where(t1.c.x == t2.c.y).where(t1.c.x == s)
     print(s2)
 
+.. sourcecode:: sql
+
     SELECT t1.x, t2.y FROM t1, t2
     WHERE t1.x = t2.y AND t1.x =
         (SELECT t1.x, t2.y FROM t2)
@@ -1376,13 +1385,11 @@ that the event gave no way to get at the current
 reflection, in the case that additional information from the
 database is needed.   As this is a new event not widely used
 yet, we'll be adding the ``inspector`` argument into it
-directly:
-
-::
+directly::
 
     @event.listens_for(Table, "column_reflect")
     def listen_for_col(inspector, table, column_info):
-        ...
+        ...
 
 :ticket:`2418`
 
index 93fb8f1e58e0f838af79db275d19a02b6981a7bc..37f619c9de24307a7e36c442805e2e9f90a39bd7 100644 (file)
@@ -99,7 +99,9 @@ Consider the following example against the usual ``User`` mapping::
         .filter(User.name == "ed")
     )
 
-The above statement predictably renders SQL like the following::
+The above statement predictably renders SQL like the following:
+
+.. sourcecode:: sql
 
     SELECT "user".id AS user_id, "user".name AS user_name
     FROM "user" JOIN (SELECT "user".id AS id, "user".name AS name
@@ -120,7 +122,9 @@ JOIN, the documentation would lead us to believe we could use
 
 However, in version 0.8 and earlier, the above use of :meth:`_query.Query.select_from`
 would apply the ``select_stmt`` to **replace** the ``User`` entity, as it
-selects from the ``user`` table which is compatible with ``User``::
+selects from the ``user`` table which is compatible with ``User``:
+
+.. sourcecode:: sql
 
     -- SQLAlchemy 0.8 and earlier...
     SELECT anon_1.id AS anon_1_id, anon_1.name AS anon_1_name
@@ -144,7 +148,9 @@ to selecting from a customized :func:`.aliased` construct::
     q = session.query(user_from_stmt).filter(user_from_stmt.name == "ed")
 
 So with SQLAlchemy 0.9, our query that selects from ``select_stmt`` produces
-the SQL we expect::
+the SQL we expect:
+
+.. sourcecode:: sql
 
     -- SQLAlchemy 0.9
     SELECT "user".id AS user_id, "user".name AS user_name
@@ -254,7 +260,9 @@ Up through 0.8, a query like the following::
 
     s.query(A).filter(A.b_value == None).all()
 
-would produce::
+would produce:
+
+.. sourcecode:: sql
 
     SELECT a.id AS a_id, a.b_id AS a_b_id
     FROM a
@@ -262,7 +270,9 @@ would produce::
     FROM b
     WHERE b.id = a.b_id AND b.value IS NULL)
 
-In 0.9, it now produces::
+In 0.9, it now produces:
+
+.. sourcecode:: sql
 
     SELECT a.id AS a_id, a.b_id AS a_b_id
     FROM a
@@ -276,7 +286,9 @@ results versus prior versions, for a system that uses this type of
 comparison where some parent rows have no association row.
 
 More critically, a correct expression is emitted for ``A.b_value != None``.
-In 0.8, this would return ``True`` for ``A`` rows that had no ``b``::
+In 0.8, this would return ``True`` for ``A`` rows that had no ``b``:
+
+.. sourcecode:: sql
 
     SELECT a.id AS a_id, a.b_id AS a_b_id
     FROM a
@@ -286,7 +298,9 @@ In 0.8, this would return ``True`` for ``A`` rows that had no ``b``::
 
 Now in 0.9, the check has been reworked so that it ensures
 the A.b_id row is present, in addition to ``B.value`` being
-non-NULL::
+non-NULL:
+
+.. sourcecode:: sql
 
     SELECT a.id AS a_id, a.b_id AS a_b_id
     FROM a
@@ -301,7 +315,9 @@ being present or not::
 
     s.query(A).filter(A.b_value.has()).all()
 
-output::
+output:
+
+.. sourcecode:: sql
 
     SELECT a.id AS a_id, a.b_id AS a_b_id
     FROM a
@@ -444,8 +460,9 @@ arguments which were silently ignored::
 
 This was a very old bug for which a deprecation warning was added to the
 0.8 series, but because nobody ever runs Python with the "-W" flag, it
-was mostly never seen::
+was mostly never seen:
 
+.. sourcecode:: text
 
     $ python -W always::DeprecationWarning ~/dev/sqlalchemy/test.py
     /Users/classic/dev/sqlalchemy/test.py:5: SADeprecationWarning: Passing arguments to
@@ -546,7 +563,9 @@ in that it escaped spaces as plus signs.  The stringification of a URL
 now only encodes ":", "@", or "/" and nothing else, and is now applied to both the
 ``username`` and ``password`` fields (previously it only applied to the
 password).   On parsing, encoded characters are converted, but plus signs and
-spaces are passed through as is::
+spaces are passed through as is:
+
+.. sourcecode:: text
 
     # password: "pass word + other:words"
     dbtype://user:pass word + other%3Awords@host/dbname
@@ -572,14 +591,18 @@ Previously, an expression like the following::
 
     print((column("x") == "somevalue").collate("en_EN"))
 
-would produce an expression like this::
+would produce an expression like this:
+
+.. sourcecode:: sql
 
     -- 0.8 behavior
     (x = :x_1) COLLATE en_EN
 
 The above is misunderstood by MSSQL and is generally not the syntax suggested
 for any database.  The expression will now produce the syntax illustrated
-by that of most database documentation::
+by that of most database documentation:
+
+.. sourcecode:: sql
 
     -- 0.9 behavior
     x = :x_1 COLLATE en_EN
@@ -590,12 +613,16 @@ column, as follows::
 
     print(column("x") == literal("somevalue").collate("en_EN"))
 
-In 0.8, this produces::
+In 0.8, this produces:
+
+.. sourcecode:: sql
 
     x = :param_1 COLLATE en_EN
 
 However in 0.9, will now produce the more accurate, but probably not what you
-want, form of::
+want, form of:
+
+.. sourcecode:: sql
 
     x = (:param_1 COLLATE en_EN)
 
@@ -878,7 +905,9 @@ and :class:`_query.Query` objects::
     q = s.query(User.id, User.name).filter_by(name="ed")
     ins = insert(Address).from_select((Address.id, Address.email_address), q)
 
-rendering::
+rendering:
+
+.. sourcecode:: sql
 
     INSERT INTO addresses (id, email_address)
     SELECT users.id AS users_id, users.name AS users_name
@@ -901,7 +930,9 @@ string codes::
 
     stmt = select([table]).with_for_update(read=True, nowait=True, of=table)
 
-On Posgtresql the above statement might render like::
+On Posgtresql the above statement might render like:
+
+.. sourcecode:: sql
 
     SELECT table.a, table.b FROM table FOR SHARE OF table NOWAIT
 
@@ -1137,11 +1168,15 @@ Many JOIN and LEFT OUTER JOIN expressions will no longer be wrapped in (SELECT *
 
 For many years, the SQLAlchemy ORM has been held back from being able to nest
 a JOIN inside the right side of an existing JOIN (typically a LEFT OUTER JOIN,
-as INNER JOINs could always be flattened)::
+as INNER JOINs could always be flattened):
+
+.. sourcecode:: sql
 
     SELECT a.*, b.*, c.* FROM a LEFT OUTER JOIN (b JOIN c ON b.id = c.id) ON a.id
 
-This was due to the fact that SQLite up until version **3.7.16** cannot parse a statement of the above format::
+This was due to the fact that SQLite up until version **3.7.16** cannot parse a statement of the above format:
+
+.. sourcecode:: text
 
     SQLite version 3.7.15.2 2013-01-09 11:53:05
     Enter ".help" for instructions
@@ -1154,7 +1189,9 @@ This was due to the fact that SQLite up until version **3.7.16** cannot parse a
 
 Right-outer-joins are of course another way to work around right-side
 parenthesization; this would be significantly complicated and visually unpleasant
-to implement, but fortunately SQLite doesn't support RIGHT OUTER JOIN either :)::
+to implement, but fortunately SQLite doesn't support RIGHT OUTER JOIN either :):
+
+.. sourcecode:: sql
 
     sqlite> select a.id, b.id, c.id from b join c on b.id=c.id
        ...> right outer join a on b.id=a.id;
@@ -1165,7 +1202,9 @@ but today it seems clear every database tested except SQLite now supports it
 (Oracle 8, a very old database, doesn't support the JOIN keyword at all,
 but SQLAlchemy has always had a simple rewriting scheme in place for Oracle's syntax).
 To make matters worse, SQLAlchemy's usual workaround of applying a
-SELECT often degrades performance on platforms like PostgreSQL and MySQL::
+SELECT often degrades performance on platforms like PostgreSQL and MySQL:
+
+.. sourcecode:: sql
 
     SELECT a.*, anon_1.* FROM a LEFT OUTER JOIN (
                     SELECT b.id AS b_id, c.id AS c_id
@@ -1184,7 +1223,9 @@ where special criteria is present in the ON clause. Consider an eager load join
     session.query(Order).outerjoin(Order.items)
 
 Assuming a many-to-many from ``Order`` to ``Item`` which actually refers to a subclass
-like ``Subitem``, the SQL for the above would look like::
+like ``Subitem``, the SQL for the above would look like:
+
+.. sourcecode:: sql
 
     SELECT order.id, order.name
     FROM order LEFT OUTER JOIN order_item ON order.id = order_item.order_id
@@ -1202,7 +1243,9 @@ JOIN (which currently is only SQLite - if other backends have this issue please
 let us know!).
 
 So a regular ``query(Parent).join(Subclass)`` will now usually produce a simpler
-expression::
+expression:
+
+.. sourcecode:: sql
 
     SELECT parent.id AS parent_id
     FROM parent JOIN (
@@ -1210,7 +1253,9 @@ expression::
             ON base_table.id = subclass_table.id) ON parent.id = base_table.parent_id
 
 Joined eager loads like ``query(Parent).options(joinedload(Parent.subclasses))``
-will alias the individual tables instead of wrapping in an ``ANON_1``::
+will alias the individual tables instead of wrapping in an ``ANON_1``:
+
+.. sourcecode:: sql
 
     SELECT parent.*, base_table_1.*, subclass_table_1.* FROM parent
         LEFT OUTER JOIN (
@@ -1218,7 +1263,9 @@ will alias the individual tables instead of wrapping in an ``ANON_1``::
             ON base_table_1.id = subclass_table_1.id)
             ON parent.id = base_table_1.parent_id
 
-Many-to-many joins and eagerloads will right nest the "secondary" and "right" tables::
+Many-to-many joins and eagerloads will right nest the "secondary" and "right" tables:
+
+.. sourcecode:: sql
 
     SELECT order.id, order.name
     FROM order LEFT OUTER JOIN
@@ -1231,7 +1278,9 @@ are candidates for "join rewriting", which is the process of rewriting all those
 joins into nested SELECT statements, while maintaining the identical labeling used by
 the :class:`_expression.Select`.  So SQLite, the one database that won't support this very
 common SQL syntax even in 2013, shoulders the extra complexity itself,
-with the above queries rewritten as::
+with the above queries rewritten as:
+
+.. sourcecode:: sql
 
     -- sqlite only!
     SELECT parent.id AS parent_id
@@ -1282,7 +1331,9 @@ without any subqueries generated::
         or_(Engineer.primary_language == "python", Manager.manager_name == "dilbert")
     )
 
-Generates (everywhere except SQLite)::
+Generates (everywhere except SQLite):
+
+.. sourcecode:: sql
 
     SELECT companies.company_id AS companies_company_id, companies.name AS companies_name
     FROM companies JOIN (
@@ -1313,11 +1364,15 @@ Normally, a joined eager load chain like the following::
 Would not produce an inner join; because of the LEFT OUTER JOIN from user->order,
 joined eager loading could not use an INNER join from order->items without changing
 the user rows that are returned, and would instead ignore the "chained" ``innerjoin=True``
-directive.  How 0.9.0 should have delivered this would be that instead of::
+directive.  How 0.9.0 should have delivered this would be that instead of:
+
+.. sourcecode:: sql
 
     FROM users LEFT OUTER JOIN orders ON <onclause> LEFT OUTER JOIN items ON <onclause>
 
-the new "right-nested joins are OK" logic would kick in, and we'd get::
+the new "right-nested joins are OK" logic would kick in, and we'd get:
+
+.. sourcecode:: sql
 
     FROM users LEFT OUTER JOIN (orders JOIN items ON <onclause>) ON <onclause>
 
@@ -1366,7 +1421,9 @@ DISTINCT keyword will be applied to the innermost SELECT when the join is
 targeting columns that do not comprise the primary key, as in when loading
 along a many to one.
 
-That is, when subquery loading on a many-to-one from A->B::
+That is, when subquery loading on a many-to-one from A->B:
+
+.. sourcecode:: sql
 
     SELECT b.id AS b_id, b.name AS b_name, anon_1.b_id AS a_b_id
     FROM (SELECT DISTINCT a_b_id FROM a) AS anon_1
@@ -1605,12 +1662,16 @@ E.g. an example like::
 
     print(stmt)
 
-Prior to 0.9 would render as::
+Prior to 0.9 would render as:
+
+.. sourcecode:: sql
 
     SELECT foo(t.c1) + t.c2 AS expr
     FROM t ORDER BY foo(t.c1) + t.c2
 
-And now renders as::
+And now renders as:
+
+.. sourcecode:: sql
 
     SELECT foo(t.c1) + t.c2 AS expr
     FROM t ORDER BY expr
index ee77e5a6b92cbb846bd410c004be65c74aaf662e..c7988b3cd551bc55e46155b2602b4a9728ac0530 100644 (file)
@@ -304,7 +304,9 @@ all three types for "size" (number of rows returned) and "num"
 outperforms both, or lags very slightly behind the faster object, based on
 which scenario.  In the "sweet spot", where we are both creating a good number
 of new types as well as fetching a good number of rows, the lightweight
-object totally smokes both namedtuple and KeyedTuple::
+object totally smokes both namedtuple and KeyedTuple:
+
+.. sourcecode:: text
 
     -----------------
     size=10 num=10000                 # few rows, lots of queries
@@ -346,7 +348,9 @@ loader strategy system.
 A bench that makes use of heapy measure the startup size of Nova
 illustrates a difference of about 3.7 fewer megs, or 46%,
 taken up by SQLAlchemy's objects, associated dictionaries, as
-well as weakrefs, within a basic import of "nova.db.sqlalchemy.models"::
+well as weakrefs, within a basic import of "nova.db.sqlalchemy.models":
+
+.. sourcecode:: text
 
     # reported by heapy, summation of SQLAlchemy objects +
     # associated dicts + weakref-related objects with core of Nova imported:
@@ -538,7 +542,9 @@ correctly::
 
     print(sess.query(A, a1).order_by(a1.b))
 
-This would order by the wrong column::
+This would order by the wrong column:
+
+.. sourcecode:: sql
 
     SELECT a.id AS a_id, (SELECT max(b.id) AS max_1 FROM b
     WHERE b.a_id = a.id) AS anon_1, a_1.id AS a_1_id,
@@ -546,7 +552,9 @@ This would order by the wrong column::
     FROM b WHERE b.a_id = a_1.id) AS anon_2
     FROM a, a AS a_1 ORDER BY anon_1
 
-New output::
+New output:
+
+.. sourcecode:: sql
 
     SELECT a.id AS a_id, (SELECT max(b.id) AS max_1
     FROM b WHERE b.a_id = a.id) AS anon_1, a_1.id AS a_1_id,
@@ -566,14 +574,18 @@ to order by label, for example if the mapping were "polymorphic"::
         __mapper_args__ = {"polymorphic_on": type, "with_polymorphic": "*"}
 
 The order_by would fail to use the label, as it would be anonymized due
-to the polymorphic loading::
+to the polymorphic loading:
+
+.. sourcecode:: sql
 
     SELECT a.id AS a_id, a.type AS a_type, (SELECT max(b.id) AS max_1
     FROM b WHERE b.a_id = a.id) AS anon_1
     FROM a ORDER BY (SELECT max(b.id) AS max_2
     FROM b WHERE b.a_id = a.id)
 
-Now that the order by label tracks the anonymized label, this now works::
+Now that the order by label tracks the anonymized label, this now works:
+
+.. sourcecode:: sql
 
     SELECT a.id AS a_id, a.type AS a_type, (SELECT max(b.id) AS max_1
     FROM b WHERE b.a_id = a.id) AS anon_1
@@ -716,7 +728,9 @@ expression of a :class:`.CheckConstraint`::
 
     CheckConstraint(foo.c.value > 5)
 
-Will render::
+Will render:
+
+.. sourcecode:: sql
 
     CREATE TABLE foo (
         value INTEGER,
@@ -844,7 +858,9 @@ expressions are rendered as constants into the SELECT statement::
     stmt = select([t.c.x])
     print(t.insert().from_select(["x"], stmt))
 
-Will render::
+Will render:
+
+.. sourcecode:: sql
 
     INSERT INTO t (x, y) SELECT t.x, somefunction() AS somefunction_1
     FROM t
@@ -877,7 +893,9 @@ embedded in SQL to render correctly, such as::
 
     print(CreateTable(tbl).compile(dialect=postgresql.dialect()))
 
-Now renders::
+Now renders:
+
+.. sourcecode:: sql
 
     CREATE TABLE derp (
         arr TEXT[] DEFAULT ARRAY['foo', 'bar', 'baz']
@@ -985,7 +1003,9 @@ emitted for ten of the parameter sets, out of a total of 1000::
             select([cast(("foo_%d" % random.randint(0, 1000000)).encode("ascii"), Unicode)])
         )
 
-The format of the warning here is::
+The format of the warning here is:
+
+.. sourcecode:: text
 
     /path/lib/sqlalchemy/sql/sqltypes.py:186: SAWarning: Unicode type received
       non-unicode bind param value 'foo_4852'. (this warning may be
@@ -1065,7 +1085,9 @@ queries that are essentially of this form::
     session.query(Address).filter(Address.user == User(id=None))
 
 This pattern is not currently supported in SQLAlchemy.  For all versions,
-it emits SQL resembling::
+it emits SQL resembling:
+
+.. sourcecode:: sql
 
     SELECT address.id AS address_id, address.user_id AS address_user_id,
     address.email_address AS address_email_address
@@ -1075,7 +1097,9 @@ it emits SQL resembling::
 Note above, there is a comparison ``WHERE ? = address.user_id`` where the
 bound value ``?`` is receiving ``None``, or ``NULL`` in SQL.  **This will
 always return False in SQL**.  The comparison here would in theory
-generate SQL as follows::
+generate SQL as follows:
+
+.. sourcecode:: sql
 
     SELECT address.id AS address_id, address.user_id AS address_user_id,
     address.email_address AS address_email_address
@@ -1085,7 +1109,9 @@ But right now, **it does not**.   Applications which are relying upon the
 fact that "NULL = NULL" produces False in all cases run the risk that
 someday, SQLAlchemy might fix this issue to generate "IS NULL", and the queries
 will then produce different results.  Therefore with this kind of operation,
-you will see a warning::
+you will see a warning:
+
+.. sourcecode:: text
 
     SAWarning: Got None for value of column user.id; this is unsupported
     for a relationship comparison and will not currently produce an
@@ -1135,7 +1161,9 @@ will use the value 10 in the bound parameters::
 
     s.query(B).filter(B.a == a1)
 
-Produces::
+Produces:
+
+.. sourcecode:: sql
 
     SELECT b.id AS b_id, b.a_id AS b_a_id
     FROM b
@@ -1147,19 +1175,23 @@ However, before this change, the negation of this criteria would **not** use
 
     s.query(B).filter(B.a != a1)
 
-Produces (in 0.9 and all versions prior to 1.0.1)::
+Produces (in 0.9 and all versions prior to 1.0.1):
+
+.. sourcecode:: sql
 
     SELECT b.id AS b_id, b.a_id AS b_a_id
     FROM b
     WHERE b.a_id != ? OR b.a_id IS NULL
     (7,)
 
-For a transient object, it would produce a broken query::
+For a transient object, it would produce a broken query:
+
+.. sourcecode:: sql
 
     SELECT b.id, b.a_id
     FROM b
     WHERE b.a_id != :a_id_1 OR b.a_id IS NULL
-    {u'a_id_1': symbol('NEVER_SET')}
+    -- {u'a_id_1': symbol('NEVER_SET')}
 
 This inconsistency has been repaired, and in all queries the current attribute
 value, in this example ``10``, will now be used.
@@ -1393,7 +1425,9 @@ A query that joins to ``A.bs`` twice::
 
     print(s.query(A).join(A.bs).join(A.bs))
 
-Will render::
+Will render:
+
+.. sourcecode:: sql
 
     SELECT a.id AS a_id
     FROM a JOIN b ON a.id = b.a_id
@@ -1407,7 +1441,9 @@ to support a case like the following::
 
 That is, the ``A.bs`` is part of a "path".  As part of :ticket:`3367`,
 arriving at the same endpoint twice without it being part of a
-larger path will now emit a warning::
+larger path will now emit a warning:
+
+.. sourcecode:: text
 
     SAWarning: Pathed join target A.bs has already been joined to; skipping
 
@@ -1416,7 +1452,9 @@ relationship-bound path.  If we join to ``B`` twice::
 
     print(s.query(A).join(B, B.a_id == A.id).join(B, B.a_id == A.id))
 
-In 0.9, this would render as follows::
+In 0.9, this would render as follows:
+
+.. sourcecode:: sql
 
     SELECT a.id AS a_id
     FROM a JOIN b ON b.a_id = a.id JOIN b AS b_1 ON b_1.a_id = a.id
@@ -1424,7 +1462,9 @@ In 0.9, this would render as follows::
 This is problematic since the aliasing is implicit and in the case of different
 ON clauses can lead to unpredictable results.
 
-In 1.0, no automatic aliasing is applied and we get::
+In 1.0, no automatic aliasing is applied and we get:
+
+.. sourcecode:: sql
 
     SELECT a.id AS a_id
     FROM a JOIN b ON b.a_id = a.id JOIN b ON b.a_id = a.id
@@ -1481,7 +1521,9 @@ a mapping as follows::
     print(s.query(ASub1).join(B, ASub1.b).join(ASub2, ASub2.id == B.a_id))
 
 The two queries at the bottom are equivalent, and should both render
-the identical SQL::
+the identical SQL:
+
+.. sourcecode:: sql
 
     SELECT a.id AS a_id, a.type AS a_type
     FROM a JOIN b ON b.a_id = a.id JOIN a ON b.a_id = a.id AND a.type IN (:type_1)
@@ -1489,7 +1531,9 @@ the identical SQL::
 
 The above SQL is invalid, as it renders "a" within the FROM list twice.
 However, the implicit aliasing bug would occur with the second query only
-and render this instead::
+and render this instead:
+
+.. sourcecode:: sql
 
     SELECT a.id AS a_id, a.type AS a_type
     FROM a JOIN b ON b.a_id = a.id JOIN a AS a_1
@@ -1603,7 +1647,9 @@ when using ``innerjoin=True``::
         joinedload("orders", innerjoin=False).joinedload("items", innerjoin=True)
     )
 
-With the new default, this will render the FROM clause in the form::
+With the new default, this will render the FROM clause in the form:\
+
+.. sourcecode:: text
 
     FROM users LEFT OUTER JOIN (orders JOIN items ON <onclause>) ON <onclause>
 
@@ -1619,7 +1665,9 @@ To get the older behavior, use ``innerjoin="unnested"``::
     )
 
 This will avoid right-nested joins and chain the joins together using all
-OUTER joins despite the innerjoin directive::
+OUTER joins despite the innerjoin directive:
+
+.. sourcecode:: text
 
     FROM users LEFT OUTER JOIN orders ON <onclause> LEFT OUTER JOIN items ON <onclause>
 
@@ -1660,7 +1708,9 @@ loaded as a single value", which is essentially a "one to one"
 relationship.  However, joined eager loading has always treated the
 above as a situation where the main query needs to be inside a
 subquery, as would normally be needed for a collection of B objects
-where the main query has a LIMIT applied::
+where the main query has a LIMIT applied:
+
+.. sourcecode:: sql
 
     SELECT anon_1.a_id AS anon_1_a_id, b_1.id AS b_1_id, b_1.a_id AS b_1_a_id
     FROM (SELECT a.id AS a_id
@@ -1670,7 +1720,9 @@ where the main query has a LIMIT applied::
 However, since the relationship of the inner query to the outer one is
 that at most only one row is shared in the case of ``uselist=False``
 (in the same way as a many-to-one), the "subquery" used with LIMIT +
-joined eager loading is now dropped in this case::
+joined eager loading is now dropped in this case:
+
+.. sourcecode:: sql
 
     SELECT a.id AS a_id, b_1.id AS b_1_id, b_1.a_id AS b_1_a_id
     FROM a LEFT OUTER JOIN b AS b_1 ON a.id = b_1.a_id
@@ -1737,7 +1789,9 @@ to the outside::
 
     sess.query(FooWidget).from_self().all()
 
-rendering::
+rendering:
+
+.. sourcecode:: sql
 
     SELECT
         anon_1.widgets_id AS anon_1_widgets_id,
@@ -1751,7 +1805,9 @@ columns, then we can't add the WHERE clause on the outside (it actually tries,
 and produces a bad query).  This decision
 apparently goes way back to 0.6.5 with the note "may need to make more
 adjustments to this".   Well, those adjustments have arrived!  So now the
-above query will render::
+above query will render:
+
+.. sourcecode:: sql
 
     SELECT
         anon_1.widgets_id AS anon_1_widgets_id,
@@ -1764,7 +1820,9 @@ So that queries that don't include "type" will still work!::
 
     sess.query(FooWidget.id).count()
 
-Renders::
+Renders:
+
+.. sourcecode:: sql
 
     SELECT count(*) AS count_1
     FROM (SELECT widgets.id AS widgets_id
@@ -1807,7 +1865,9 @@ will render a "single inheritance" clause for the type::
 
     s.query(Related).join(FooWidget, Related.widget).all()
 
-SQL output::
+SQL output:
+
+.. sourcecode:: sql
 
     SELECT related.id AS related_id
     FROM related JOIN widget ON related.id = widget.related_id AND widget.type IN (:type_1)
@@ -1884,7 +1944,9 @@ When composing a select as below::
     stmt = select(["a", "b"]).where("a = b").select_from("sometable")
 
 The statement is built up normally, with all the same coercions as before.
-However, one will see the following warnings emitted::
+However, one will see the following warnings emitted:
+
+.. sourcecode:: text
 
     SAWarning: Textual column expression 'a' should be explicitly declared
     with text('a'), or use column('a') for more specificity
@@ -1958,7 +2020,9 @@ In the above statement we expect to see "ORDER BY id_count", as opposed to a
 re-statement of the function.   The string argument given is actively
 matched to an entry in the columns clause during compilation, so the above
 statement would produce as we expect, without warnings (though note that
-the ``"name"`` expression has been resolved to ``users.name``!)::
+the ``"name"`` expression has been resolved to ``users.name``!):
+
+.. sourcecode:: sql
 
     SELECT users.name, count(users.id) AS id_count
     FROM users GROUP BY users.name ORDER BY id_count
@@ -1970,11 +2034,15 @@ the warning again, as below::
         "some_label"
     )
 
-The output does what we say, but again it warns us::
+The output does what we say, but again it warns us:
+
+.. sourcecode:: text
 
     SAWarning: Can't resolve label reference 'some_label'; converting to
     text() (this warning may be suppressed after 10 occurrences)
 
+.. sourcecode:: sql
+
     SELECT users.name, count(users.id) AS id_count
     FROM users ORDER BY some_label
 
@@ -2033,13 +2101,17 @@ that of an "executemany" style of invocation::
     )
 
 The above example will invoke ``next(counter)`` for each row individually
-as would be expected::
+as would be expected:
+
+.. sourcecode:: sql
 
     INSERT INTO my_table (id, data) VALUES (?, ?), (?, ?), (?, ?)
     (1, 'd1', 2, 'd2', 3, 'd3')
 
 Previously, a positional dialect would fail as a bind would not be generated
-for additional positions::
+for additional positions:
+
+.. sourcecode:: text
 
     Incorrect number of bindings supplied. The current statement uses 6,
     and there are 4 supplied.
@@ -2048,10 +2120,12 @@ for additional positions::
 
 And with a "named" dialect, the same value for "id" would be re-used in
 each row (hence this change is backwards-incompatible with a system that
-relied on this)::
+relied on this):
+
+.. sourcecode:: sql
 
     INSERT INTO my_table (id, data) VALUES (:id, :data_0), (:id, :data_1), (:id, :data_2)
-    {u'data_2': 'd3', u'data_1': 'd2', u'data_0': 'd1', 'id': 1}
+    -- {u'data_2': 'd3', u'data_1': 'd2', u'data_0': 'd1', 'id': 1}
 
 The system will also refuse to invoke a "server side" default as inline-rendered
 SQL, since it cannot be guaranteed that a server side default is compatible
@@ -2076,17 +2150,21 @@ an exception is raised::
         )
     )
 
-will raise::
+will raise:
+
+.. sourcecode:: text
 
     sqlalchemy.exc.CompileError: INSERT value for column my_table.data is
     explicitly rendered as a boundparameter in the VALUES clause; a
     Python-side value or SQL expression is required
 
 Previously, the value "d1" would be copied into that of the third
-row (but again, only with named format!)::
+row (but again, only with named format!):
+
+.. sourcecode:: sql
 
     INSERT INTO my_table (data) VALUES (:data_0), (:data_1), (:data_0)
-    {u'data_1': 'd2', u'data_0': 'd1'}
+    -- {u'data_1': 'd2', u'data_0': 'd1'}
 
 :ticket:`3288`
 
index d90f49ec561ff93ff3c80402bea09b670d84881b..0732900c6d975eba8a0e21f2dc96b4009b215fb5 100644 (file)
@@ -366,7 +366,9 @@ query is against a subquery expression such as an exists::
 
     session.query(q).all()
 
-Produces::
+Produces:
+
+.. sourcecode:: sql
 
     SELECT EXISTS (SELECT 1
     FROM widget
@@ -469,7 +471,9 @@ removed would be lost, and the flush would incorrectly raise an error::
     s.add(A(id=1))
     s.commit()
 
-The above program would raise::
+The above program would raise:
+
+.. sourcecode:: text
 
     FlushError: New instance <User at 0x7f0287eca4d0> with identity key
     (<class 'test.orm.test_transaction.User'>, ('u1',)) conflicts
@@ -558,10 +562,12 @@ for the table itself::
     session.delete(some_b)
     session.commit()
 
-Will emit SQL as::
+Will emit SQL as:
+
+.. sourcecode:: sql
 
     DELETE FROM a WHERE a.id = %(id)s
-    {'id': 1}
+    -- {'id': 1}
     COMMIT
 
 As always, the target database must have foreign key support with
@@ -853,7 +859,9 @@ using with_polymorphic::
         == "Elbonia, Inc."
     )
 
-The above query now produces::
+The above query now produces:
+
+.. sourcecode:: sql
 
     SELECT people.name AS people_name
     FROM people
@@ -865,7 +873,9 @@ The above query now produces::
 
 Before the fix, the call to ``correlate(Person)`` would inadvertently
 attempt to correlate to the join of ``Person``, ``Engineer`` and ``Manager``
-as a single unit, so ``Person`` wouldn't be correlated::
+as a single unit, so ``Person`` wouldn't be correlated:
+
+.. sourcecode:: sql
 
     -- old, incorrect query
     SELECT people.name AS people_name
@@ -976,7 +986,9 @@ deep use case that's hard to reproduce, but the general idea is as follows::
     q = q.join(c_alias_2, A.c)
     q = q.options(contains_eager(A.c, alias=c_alias_2))
 
-The above query emits SQL like this::
+The above query emits SQL like this:
+
+.. sourcecode:: sql
 
     SELECT
         d.id AS d_id,
@@ -1284,7 +1296,9 @@ construct similar to an alias::
     stmt = select([selectable.c.people_id])
 
 Assuming ``people`` with a column ``people_id``, the above
-statement would render as::
+statement would render as:
+
+.. sourcecode:: sql
 
     SELECT alias.people_id FROM
     people AS alias TABLESAMPLE bernoulli(:bernoulli_1)
@@ -1351,7 +1365,9 @@ have autoincrement set up; given a table such as::
         Column("y", Integer, primary_key=True),
     )
 
-An INSERT emitted with no values for this table will produce this warning::
+An INSERT emitted with no values for this table will produce this warning:
+
+.. sourcecode:: text
 
     SAWarning: Column 'b.x' is marked as a member of the primary
     key for table 'b', but has no Python-side or server-side default
@@ -1509,7 +1525,9 @@ as well.   Given a statement like the following::
     ua = users.alias("ua")
     stmt = select([users.c.user_id, ua.c.user_id])
 
-The above statement will compile to::
+The above statement will compile to:
+
+.. sourcecode:: sql
 
     SELECT users.user_id, ua.user_id FROM users, users AS ua
 
@@ -1920,7 +1938,9 @@ A PostgreSQL element for an aggregate ORDER BY is also added via
     expr = func.array_agg(aggregate_order_by(table.c.a, table.c.b.desc()))
     stmt = select([expr])
 
-Producing::
+Producing:
+
+.. sourcecode:: sql
 
     SELECT array_agg(table1.a ORDER BY table1.b DESC) AS array_agg_1 FROM table1
 
@@ -1945,7 +1965,9 @@ Additionally, functions like ``percentile_cont()``, ``percentile_disc()``,
         ]
     )
 
-The above statement would produce SQL similar to::
+The above statement would produce SQL similar to:
+
+.. sourcecode:: sql
 
   SELECT department.id, percentile_cont(0.5)
   WITHIN GROUP (ORDER BY department.salary DESC)
@@ -2110,7 +2132,9 @@ our ``StringAsInt`` type which maintains the value as an integer in
 Python. We are then using :func:`.cast` so that as a SQL expression,
 the VARCHAR "id"  column will be CAST to an integer for a regular non-
 converted join as with :meth:`_query.Query.join` or :func:`_orm.joinedload`.
-That is, a joinedload of ``.pets`` looks like::
+That is, a joinedload of ``.pets`` looks like:
+
+.. sourcecode:: sql
 
     SELECT person.id AS person_id, pets_1.id AS pets_1_id,
            pets_1.person_id AS pets_1_person_id
@@ -2125,12 +2149,14 @@ The lazyload case of ``.pets`` relies upon replacing
 the ``Person.id`` column at load time with a bound parameter, which receives
 a Python-loaded value.  This replacement is specifically where the intent
 of our :func:`.type_coerce` function would be lost.  Prior to the change,
-this lazy load comes out as::
+this lazy load comes out as:
+
+.. sourcecode:: sql
 
     SELECT pets.id AS pets_id, pets.person_id AS pets_person_id
     FROM pets
     WHERE pets.person_id = CAST(CAST(%(param_1)s AS VARCHAR) AS INTEGER)
-    {'param_1': 5}
+    -- {'param_1': 5}
 
 Where above, we see that our in-Python value of ``5`` is CAST first
 to a VARCHAR, then back to an INTEGER in SQL; a double CAST which works,
@@ -2138,12 +2164,14 @@ but is nevertheless not what we asked for.
 
 With the change, the :func:`.type_coerce` function maintains a wrapper
 even after the column is swapped out for a bound parameter, and the query now
-looks like::
+looks like:
+
+.. sourcecode:: sql
 
     SELECT pets.id AS pets_id, pets.person_id AS pets_person_id
     FROM pets
     WHERE pets.person_id = CAST(%(param_1)s AS INTEGER)
-    {'param_1': 5}
+    -- {'param_1': 5}
 
 Where our outer CAST that's in our primaryjoin still takes effect, but the
 needless CAST that's in part of the ``StringAsInt`` custom type is removed
@@ -2214,13 +2242,17 @@ that are missing from the SELECT list, without duplicates::
         .order_by(User.id, User.name, User.fullname)
     )
 
-Produces::
+Produces:
+
+.. sourcecode:: sql
 
     SELECT DISTINCT user.id AS a_id, user.name AS name,
      user.fullname AS a_fullname
     FROM a ORDER BY user.id, user.name, user.fullname
 
-Previously, it would produce::
+Previously, it would produce:
+
+.. sourcecode:: sql
 
     SELECT DISTINCT user.id AS a_id, user.name AS name, user.name AS a_name,
       user.fullname AS a_fullname
@@ -2268,9 +2300,12 @@ last defined validator::
 
     configure_mappers()
 
-Will raise::
+Will raise:
+
+.. sourcecode:: text
 
-    sqlalchemy.exc.InvalidRequestError: A validation function for mapped attribute 'data' on mapper Mapper|A|a already exists.
+    sqlalchemy.exc.InvalidRequestError: A validation function for mapped attribute 'data'
+    on mapper Mapper|A|a already exists.
 
 :ticket:`3776`
 
@@ -2359,7 +2394,9 @@ A UNION or similar of SELECTs with LIMIT/OFFSET/ORDER BY now parenthesizes the e
 An issue that, like others, was long driven by SQLite's lack of capabilities
 has now been enhanced to work on all supporting backends.   We refer to a query that
 is a UNION of SELECT statements that themselves contain row-limiting or ordering
-features which include LIMIT, OFFSET, and/or ORDER BY::
+features which include LIMIT, OFFSET, and/or ORDER BY:
+
+.. sourcecode:: sql
 
     (SELECT x FROM table1 ORDER BY y LIMIT 1) UNION
     (SELECT x FROM table2 ORDER BY y LIMIT 2)
@@ -2434,7 +2471,9 @@ supported by PostgreSQL 9.5 in this area::
 
     conn.execute(do_update_stmt)
 
-The above will render::
+The above will render:
+
+.. sourcecode:: sql
 
     INSERT INTO my_table (id, data)
     VALUES (:id, :data)
@@ -2571,7 +2610,9 @@ as expected::
     e = create_engine("postgresql://scott:tiger@localhost/test", echo=True)
     Base.metadata.create_all(e)
 
-emits::
+emits:
+
+.. sourcecode:: sql
 
     CREATE TYPE work_place_roles AS ENUM (
         'manager', 'place_admin', 'carwash_admin', 'parking_admin',
@@ -2715,7 +2756,9 @@ not the first column, e.g.::
         mysql_engine="InnoDB",
     )
 
-DDL such as the following would be generated::
+DDL such as the following would be generated:
+
+.. sourcecode:: sql
 
     CREATE TABLE some_table (
         x INTEGER NOT NULL,
@@ -2729,7 +2772,9 @@ found its way into the dialect many years ago in response to the issue that
 the AUTO_INCREMENT would otherwise fail on InnoDB without this additional KEY.
 
 This workaround has been removed and replaced with the much better system
-of just stating the AUTO_INCREMENT column *first* within the primary key::
+of just stating the AUTO_INCREMENT column *first* within the primary key:
+
+.. sourcecode:: sql
 
     CREATE TABLE some_table (
         x INTEGER NOT NULL,
index 7b601a8d48c8ba2f32d9852a76e2a26505bdd7c6..3a6c394be95929b8ab3f356cbd8874eedcd9241c 100644 (file)
@@ -87,7 +87,9 @@ Given a query as below::
     )
 
 The SQL produced would be the query against ``User`` followed by the
-subqueryload for ``User.addresses`` (note the parameters are also listed)::
+subqueryload for ``User.addresses`` (note the parameters are also listed):
+
+.. sourcecode:: sql
 
     SELECT users.id AS users_id, users.name AS users_name
     FROM users
@@ -114,7 +116,9 @@ actual primary key values loaded in the parent query::
         .options(selectinload(User.addresses))
     )
 
-Produces::
+Produces:
+
+.. sourcecode:: sql
 
     SELECT users.id AS users_id, users.name AS users_name
     FROM users
@@ -176,16 +180,16 @@ loading that allows the loading of the base entity to proceed with a simple
 SELECT statement, but then the attributes of the additional subclasses
 are loaded with additional SELECT statements:
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
-    from sqlalchemy.orm import selectin_polymorphic
+    >>> from sqlalchemy.orm import selectin_polymorphic
 
-    query = session.query(Employee).options(
-        selectin_polymorphic(Employee, [Manager, Engineer])
-    )
+    >>> query = session.query(Employee).options(
+    ...     selectin_polymorphic(Employee, [Manager, Engineer])
+    ... )
 
-    {opensql}query.all()
-    SELECT
+    >>> query.all()
+    {opensql}SELECT
         employee.id AS employee_id,
         employee.name AS employee_name,
         employee.type AS employee_type
@@ -740,7 +744,9 @@ this condition is also removed.  The old behavior is available using the
 
 In SQL, the IN and NOT IN operators do not support comparison to a
 collection of values that is explicitly empty; meaning, this syntax is
-illegal::
+illegal:
+
+.. sourcecode:: sql
 
     mycolumn IN ()
 
@@ -779,7 +785,9 @@ questioned.  The notion that the expression "NULL IN ()" should return NULL was
 only theoretical, and could not be tested since databases don't support that
 syntax.  However, as it turns out, you can in fact ask a relational database
 what value it would return for "NULL IN ()" by simulating the empty set as
-follows::
+follows:
+
+.. sourcecode:: sql
 
     SELECT NULL IN (SELECT 1 WHERE 1 != 1)
 
@@ -904,7 +912,9 @@ Given a statement as::
     conn.execute(stmt)
 
 The resulting SQL from the above statement on a PostgreSQL backend
-would render as::
+would render as:
+
+.. sourcecode:: sql
 
     DELETE FROM users USING addresses
     WHERE users.id = addresses.id
@@ -1125,7 +1135,9 @@ Supposing ``Manager`` is a subclass of ``Employee``.  A query like the following
 
     sess.query(Manager.id)
 
-Would generate SQL as::
+Would generate SQL as:
+
+.. sourcecode:: sql
 
     SELECT employee.id FROM employee WHERE employee.type IN ('manager')
 
@@ -1134,11 +1146,15 @@ and not in the columns list, the discriminator would not be added::
 
     sess.query(func.count(1)).select_from(Manager)
 
-would generate::
+would generate:
+
+.. sourcecode:: sql
 
     SELECT count(1) FROM employee
 
-With the fix, :meth:`_query.Query.select_from` now works correctly and we get::
+With the fix, :meth:`_query.Query.select_from` now works correctly and we get:
+
+.. sourcecode:: sql
 
     SELECT count(1) FROM employee WHERE employee.type IN ('manager')
 
@@ -1350,7 +1366,9 @@ overwrite it::
 
 Above, the previous behavior would be that an UPDATE would emit after the
 INSERT, thus triggering the "onupdate" and overwriting the value
-"5".   The SQL now looks like::
+"5".   The SQL now looks like:
+
+.. sourcecode:: sql
 
     INSERT INTO a (favorite_b_id, updated) VALUES (?, ?)
     (None, 5)
@@ -1532,7 +1550,9 @@ is fixed, where a case sensitive name would not be quoted::
         mytable.c.somecolumn.collate("fr_FR")
     )
 
-now renders::
+now renders:
+
+.. sourcecode:: sql
 
     SELECT mytable.x, mytable.y,
     FROM mytable ORDER BY mytable.somecolumn COLLATE "fr_FR"
@@ -1627,7 +1647,9 @@ This :class:`_expression.Insert` subclass adds a new method
 
     conn.execute(on_conflict_stmt)
 
-The above will render::
+The above will render:
+
+.. sourcecode:: sql
 
     INSERT INTO my_table (id, data)
     VALUES (:id, :data)
index c3093c674be6bde3848b785a16ac88cbba032881..e799e718115484261cd4722ac3383b0d6ddfd6ef 100644 (file)
@@ -833,7 +833,9 @@ as:
 
 That is, the JOIN would implicitly be against the first entity that matches.
 The new behavior is that an exception requests that this ambiguity be
-resolved::
+resolved:
+
+.. sourcecode:: text
 
     sqlalchemy.exc.InvalidRequestError: Can't determine which FROM clause to
     join from, there are multiple FROMS which can join to this entity.
@@ -860,7 +862,9 @@ is not the first element in the list if the join is otherwise non-ambiguous::
 
     session.query(func.current_timestamp(), User).join(Address)
 
-Prior to this enhancement, the above query would raise::
+Prior to this enhancement, the above query would raise:
+
+.. sourcecode:: text
 
     sqlalchemy.exc.InvalidRequestError: Don't know how to join from
     CURRENT_TIMESTAMP; please use select_from() to establish the
@@ -897,7 +901,9 @@ Given a query as::
     session.query(A).options(joinedload(A.b)).limit(5)
 
 The :class:`_query.Query` object renders a SELECT of the following form when joined
-eager loading is combined with LIMIT::
+eager loading is combined with LIMIT:
+
+.. sourcecode:: sql
 
     SELECT subq.a_id, subq.a_data, b_alias.id, b_alias.data FROM (
         SELECT a.id AS a_id, a.data AS a_data FROM a LIMIT 5
@@ -905,7 +911,9 @@ eager loading is combined with LIMIT::
 
 This is so that the limit of rows takes place for the primary entity without
 affecting the joined eager load of related items.   When the above query is
-combined with "SELECT..FOR UPDATE", the behavior has been this::
+combined with "SELECT..FOR UPDATE", the behavior has been this:
+
+.. sourcecode:: sql
 
     SELECT subq.a_id, subq.a_data, b_alias.id, b_alias.data FROM (
         SELECT a.id AS a_id, a.data AS a_data FROM a LIMIT 5
@@ -913,7 +921,9 @@ combined with "SELECT..FOR UPDATE", the behavior has been this::
 
 However, MySQL due to https://bugs.mysql.com/bug.php?id=90693 does not lock
 the rows inside the subquery, unlike that of PostgreSQL and other databases.
-So the above query now renders as::
+So the above query now renders as:
+
+.. sourcecode:: sql
 
     SELECT subq.a_id, subq.a_data, b_alias.id, b_alias.data FROM (
         SELECT a.id AS a_id, a.data AS a_data FROM a LIMIT 5 FOR UPDATE
@@ -932,7 +942,9 @@ given::
 
     session.query(A).options(joinedload(A.b)).with_for_update(of=A).limit(5)
 
-The query would now render as::
+The query would now render as:
+
+.. sourcecode:: sql
 
     SELECT subq.a_id, subq.a_data, b_alias.id, b_alias.data FROM (
         SELECT a.id AS a_id, a.data AS a_data FROM a LIMIT 5 FOR UPDATE OF a
@@ -1023,7 +1035,9 @@ constraints with a name that joins together the names of all columns::
         UniqueConstraint("a", "b", "c"),
     )
 
-The CREATE TABLE for the above table will render as::
+The CREATE TABLE for the above table will render as:
+
+.. sourcecode:: sql
 
     CREATE TABLE info (
         a INTEGER,
@@ -1051,7 +1065,9 @@ constraint name would normally be generated from the table definition below::
     )
 
 The truncation logic will ensure a too-long name isn't generated for the
-UNIQUE constraint::
+UNIQUE constraint:
+
+.. sourcecode:: sql
 
     CREATE TABLE long_names (
         information_channel_code INTEGER,
@@ -1087,7 +1103,9 @@ to other kinds of constraints as well::
 
     print(AddConstraint(uq).compile(dialect=postgresql.dialect()))
 
-will output::
+will output:
+
+.. sourcecode:: text
 
     sqlalchemy.exc.IdentifierError: Identifier
     'this_is_too_long_of_a_name_for_any_database_backend_even_postgresql'
@@ -1105,7 +1123,9 @@ To apply SQLAlchemy-side truncation rules to the above identifier, use the
         name=conv("this_is_too_long_of_a_name_for_any_database_backend_even_postgresql"),
     )
 
-This will again output deterministically truncated SQL as in::
+This will again output deterministically truncated SQL as in:
+
+.. sourcecode:: sql
 
     ALTER TABLE t ADD CONSTRAINT this_is_too_long_of_a_name_for_any_database_backend_eve_ac05 UNIQUE (x)
 
@@ -1158,7 +1178,9 @@ side::
 Above, the :paramref:`_orm.relationship.primaryjoin` of the "descendants" relationship
 will produce a "left" and a "right" expression based on the first and second
 arguments passed to ``instr()``.   This allows features like the ORM
-lazyload to produce SQL like::
+lazyload to produce SQL like:
+
+.. sourcecode:: sql
 
     SELECT venue.id AS venue_id, venue.name AS venue_name
     FROM venue
@@ -1174,7 +1196,9 @@ and a joinedload, such as::
         .one()
     )
 
-to work as::
+to work as:
+
+.. sourcecode:: sql
 
     SELECT venue.id AS venue_id, venue.name AS venue_name,
       venue_1.id AS venue_1_id, venue_1.name AS venue_1_name
@@ -1268,7 +1292,9 @@ The above expression will render a function within SQL when used on SQLite only:
 
     print(select([column("x", CompressedLargeBinary)]).compile(dialect=sqlite.dialect()))
 
-will render::
+will render:
+
+.. sourcecode:: sql
 
     SELECT uncompress(x) AS x
 
@@ -1344,10 +1370,10 @@ The original usage model for SQLAlchemy looked like this::
 
     engine.begin()
 
-    table.insert().execute(<params>)
+    table.insert().execute(parameters)
     result = table.select().execute()
 
-    table.update().execute(<params>)
+    table.update().execute(parameters)
 
     engine.commit()
 
@@ -1361,10 +1387,10 @@ introduced, minus the context managers since they didn't yet exist in Python::
     try:
         trans = conn.begin()
 
-        conn.execute(table.insert(), <params>)
+        conn.execute(table.insert(), parameters)
         result = conn.execute(table.select())
 
-        conn.execute(table.update(), <params>)
+        conn.execute(table.update(), parameters)
 
         trans.commit()
     except:
@@ -1381,10 +1407,10 @@ Today, working with Core is much more succinct, and even more succinct than
 the original pattern, thanks to context managers::
 
     with engine.begin() as conn:
-        conn.execute(table.insert(), <params>)
+        conn.execute(table.insert(), parameters)
         result = conn.execute(table.select())
 
-        conn.execute(table.update(), <params>)
+        conn.execute(table.update(), parameters)
 
 At this point, any remaining code that is still relying upon the "threadlocal"
 style will be encouraged via this deprecation to modernize - the feature should
@@ -1562,7 +1588,9 @@ as several :class:`_schema.Column` -specific variants::
         UniqueConstraint("id", "data", sqlite_on_conflict="IGNORE"),
     )
 
-The above table would render in a CREATE TABLE statement as::
+The above table would render in a CREATE TABLE statement as:
+
+.. sourcecode:: sql
 
     CREATE TABLE some_table (
         id INTEGER NOT NULL,
@@ -1737,11 +1765,17 @@ separated by newlines, and newlines that are present in the original SQL
 statement are maintained.   The goal is to improve readability while still
 keeping the original error message on one line for logging purposes.
 
-This means that an error message that previously looked like this::
+This means that an error message that previously looked like this:
+
+.. sourcecode:: text
+
+    sqlalchemy.exc.StatementError: (sqlalchemy.exc.InvalidRequestError) A value is
+    required for bind parameter 'id' [SQL: 'select * from reviews\nwhere id = ?']
+    (Background on this error at: https://sqlalche.me/e/cd3x)
 
-    sqlalchemy.exc.StatementError: (sqlalchemy.exc.InvalidRequestError) A value is required for bind parameter 'id' [SQL: 'select * from reviews\nwhere id = ?'] (Background on this error at: https://sqlalche.me/e/cd3x)
+Will now look like this:
 
-Will now look like this::
+.. sourcecode:: text
 
     sqlalchemy.exc.StatementError: (sqlalchemy.exc.InvalidRequestError) A value is required for bind parameter 'id'
     [SQL: select * from reviews
index 88a51c776fca611f133817bfc3db2436a3dc20e5..de047d85baae5d3e241e73416226f1a5028cb793 100644 (file)
@@ -185,11 +185,15 @@ for queries that return many rows::
         result = session.query(Customer).filter(Customer.id == id_).one()
 
 This example in the 1.3 release of SQLAlchemy on a Dell XPS13 running Linux
-completes as follows::
+completes as follows:
+
+.. sourcecode:: text
 
     test_orm_query : (10000 iterations); total time 3.440652 sec
 
-In 1.4, the code above without modification completes::
+In 1.4, the code above without modification completes:
+
+.. sourcecode:: text
 
     test_orm_query : (10000 iterations); total time 2.367934 sec
 
@@ -214,7 +218,9 @@ Using this API looks as follows::
         stmt += lambda s: s.where(Customer.id == id_)
         session.execute(stmt).scalar_one()
 
-The code above completes::
+The code above completes:
+
+.. sourcecode:: text
 
     test_orm_query_newstyle_w_lambdas : (10000 iterations); total time 1.247092 sec
 
@@ -605,7 +611,9 @@ That is, this will now raise::
     stmt1 = select(user.c.id, user.c.name)
     stmt2 = select(addresses, stmt1).select_from(addresses.join(stmt1))
 
-Raising::
+Raising:
+
+.. sourcecode:: text
 
     sqlalchemy.exc.ArgumentError: Column expression or FROM clause expected,
     got <...Select object ...>. To create a FROM clause from a <class
@@ -637,7 +645,9 @@ The rationale for this change is based on the following:
   without first creating an alias or subquery would be that it creates an
   unnamed subquery.   While standard SQL does support this syntax, in practice
   it is rejected by most databases.  For example, both the MySQL and PostgreSQL
-  outright reject the usage of unnamed subqueries::
+  outright reject the usage of unnamed subqueries:
+
+  .. sourcecode:: sql
 
       # MySQL / MariaDB:
 
@@ -654,7 +664,9 @@ The rationale for this change is based on the following:
       HINT:  For example, FROM (SELECT ...) [AS] foo.
 
   A database like SQLite accepts them, however it is still often the case that
-  the names produced from such a subquery are too ambiguous to be useful::
+  the names produced from such a subquery are too ambiguous to be useful:
+
+  .. sourcecode:: sql
 
       sqlite> CREATE TABLE a(id integer);
       sqlite> CREATE TABLE b(id integer);
@@ -755,7 +767,9 @@ matching to the left entity::
         addresses_table, user_table.c.id == addresses_table.c.user_id
     )
 
-producing::
+producing:
+
+.. sourcecode:: sql
 
     SELECT user.id, user.name FROM user JOIN address ON user.id=address.user_id
 
@@ -779,7 +793,9 @@ allows easier specification of the left and right side of a join at once::
 
     stmt = select(Address.email_address, User.name).join_from(User, Address)
 
-producing::
+producing:
+
+.. sourcecode:: sql
 
     SELECT address.email_address, user.name FROM user JOIN address ON user.id == address.user_id
 
@@ -1074,7 +1090,9 @@ bound value to be rendered as it would be passed to the database::
     FROM a
     WHERE a.id IN (:id_1_1, :id_1_2, :id_1_3)
 
-Engine logging output shows the ultimate rendered statement as well::
+Engine logging output shows the ultimate rendered statement as well:
+
+.. sourcecode:: sql
 
     INFO sqlalchemy.engine.base.Engine SELECT a.id, a.data
     FROM a
@@ -1147,7 +1165,9 @@ not line up with these two tables will create an additional FROM entry::
 The above query selects from a JOIN of ``User`` and ``address_alias``, the
 latter of which is an alias of the ``Address`` entity.  However, the
 ``Address`` entity is used within the WHERE clause directly, so the above would
-result in the SQL::
+result in the SQL:
+
+.. sourcecode:: sql
 
     SELECT
         users.id AS users_id, users.name AS users_name,
@@ -1384,7 +1404,9 @@ Rationale: To behave more like a named tuple rather than a mapping
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 The difference between a named tuple and a mapping as far as boolean operators
-can be summarized.   Given a "named tuple" in pseudo code as::
+can be summarized.   Given a "named tuple" in pseudo code as:
+
+.. sourcecode:: text
 
     row = (id: 5,  name: 'some name')
 
@@ -1570,7 +1592,9 @@ Improved column labeling for simple column expressions using CAST or similar
 
 A user pointed out that the PostgreSQL database has a convenient behavior when
 using functions like CAST against a named column, in that the result column name
-is named the same as the inner expression::
+is named the same as the inner expression:
+
+.. sourcecode:: text
 
     test=> SELECT CAST(data AS VARCHAR) FROM foo;
 
@@ -1582,7 +1606,9 @@ is named the same as the inner expression::
 This allows one to apply CAST to table columns while not losing the column
 name (above using the name ``"data"``) in the result row.    Compare to
 databases such as MySQL/MariaDB, as well as most others, where the column
-name is taken from the full SQL expression and is not very portable::
+name is taken from the full SQL expression and is not very portable:
+
+.. sourcecode:: text
 
     MariaDB [test]> SELECT CAST(data AS CHAR) FROM foo;
     +--------------------+
@@ -1657,7 +1683,9 @@ OFFSET values, typically used for pagination and "top N" style results.
 
 While SQLAlchemy has used bound parameters for LIMIT/OFFSET schemes for many
 years, a few outliers remained where such parameters were not allowed, including
-a SQL Server "TOP N" statement, such as::
+a SQL Server "TOP N" statement, such as:
+
+.. sourcecode:: sql
 
     SELECT TOP 5 mytable.id, mytable.data FROM mytable
 
@@ -1665,7 +1693,9 @@ as well as with Oracle, where the FIRST_ROWS() hint (which SQLAlchemy will
 use if the ``optimize_limits=True`` parameter is passed to
 :func:`_sa.create_engine` with an Oracle URL) does not allow them,
 but also that using bound parameters with ROWNUM comparisons has been reported
-as producing slower query plans::
+as producing slower query plans:
+
+.. sourcecode:: sql
 
     SELECT anon_1.id, anon_1.data FROM (
         SELECT /*+ FIRST_ROWS(5) */
@@ -1687,11 +1717,15 @@ be rendered literally into the SQL string before sending it to the DBAPI
 SQL Server and Oracle dialects, so that the drivers receive the literal
 rendered value but the rest of SQLAlchemy can still consider this as a
 bound parameter.   The above two statements when stringified using
-``str(statement.compile(dialect=<dialect>))`` now look like::
+``str(statement.compile(dialect=<dialect>))`` now look like:
+
+.. sourcecode:: sql
 
     SELECT TOP [POSTCOMPILE_param_1] mytable.id, mytable.data FROM mytable
 
-and::
+and:
+
+.. sourcecode:: sql
 
     SELECT anon_1.id, anon_1.data FROM (
         SELECT /*+ FIRST_ROWS([POSTCOMPILE__ora_frow_1]) */
@@ -1707,7 +1741,9 @@ The ``[POSTCOMPILE_<param>]`` format is also what is seen when an
 "expanding IN" is used.
 
 When viewing the SQL logging output, the final form of the statement will
-be seen::
+be seen:
+
+.. sourcecode:: sql
 
     SELECT anon_1.id, anon_1.data FROM (
         SELECT /*+ FIRST_ROWS(5) */
@@ -1882,7 +1918,9 @@ approach to be performant.
 SQLAlchemy includes a :ref:`performance suite <examples_performance>` within
 its examples, where we can compare the times generated for the "batch_inserts"
 runner against 1.3 and 1.4, revealing a 3x-5x speedup for most flavors
-of batch insert::
+of batch insert:
+
+.. sourcecode:: text
 
     # 1.3
     $ python -m examples.performance bulk_inserts --dburl postgresql://scott:tiger@localhost/test
@@ -1905,13 +1943,17 @@ of batch insert::
 Note that the ``execute_values()`` extension modifies the INSERT statement in the psycopg2
 layer, **after** it's been logged by SQLAlchemy.  So with SQL logging, one will see the
 parameter sets batched together, but the joining of multiple "values" will not be visible
-on the application side::
+on the application side:
+
+.. sourcecode:: text
 
     2020-06-27 19:08:18,166 INFO sqlalchemy.engine.Engine INSERT INTO a (data) VALUES (%(data)s) RETURNING a.id
     2020-06-27 19:08:18,166 INFO sqlalchemy.engine.Engine [generated in 0.00698s] ({'data': 'data 1'}, {'data': 'data 2'}, {'data': 'data 3'}, {'data': 'data 4'}, {'data': 'data 5'}, {'data': 'data 6'}, {'data': 'data 7'}, {'data': 'data 8'}  ... displaying 10 of 4999 total bound parameter sets ...  {'data': 'data 4998'}, {'data': 'data 4999'})
     2020-06-27 19:08:18,254 INFO sqlalchemy.engine.Engine COMMIT
 
-The ultimate INSERT statement can be seen by enabling statement logging on the PostgreSQL side::
+The ultimate INSERT statement can be seen by enabling statement logging on the PostgreSQL side:
+
+.. sourcecode:: text
 
     2020-06-27 19:08:18.169 EDT [26960] LOG:  statement: INSERT INTO a (data)
     VALUES ('data 1'),('data 2'),('data 3'),('data 4'),('data 5'),('data 6'),('data
@@ -1943,7 +1985,9 @@ An ORM bulk update or delete that uses the "fetch" strategy::
 
 Will now use RETURNING if the backend database supports it; this currently
 includes PostgreSQL and SQL Server (the Oracle dialect does not support RETURNING
-of multiple rows)::
+of multiple rows):
+
+.. sourcecode:: text
 
     UPDATE users SET age_int=(users.age_int - %(age_int_1)s) WHERE users.age_int > %(age_int_2)s RETURNING users.id
     [generated in 0.00060s] {'age_int_1': 10, 'age_int_2': 29}
@@ -1952,7 +1996,9 @@ of multiple rows)::
     Row (4,)
 
 For backends that do not support RETURNING of multiple rows, the previous approach
-of emitting SELECT for the primary keys beforehand is still used::
+of emitting SELECT for the primary keys beforehand is still used:
+
+.. sourcecode:: text
 
     SELECT users.id FROM users WHERE users.age_int > %(age_int_1)s
     [generated in 0.00043s] {'age_int_1': 29}
@@ -2446,7 +2492,9 @@ to be inserted has the same primary key as an object that is already present::
     session.add(Product(id=1))
     s.commit()  # <-- will raise FlushError
 
-The change is that the :class:`.FlushError` is altered to be only a warning::
+The change is that the :class:`.FlushError` is altered to be only a warning:
+
+.. sourcecode:: text
 
     sqlalchemy/orm/persistence.py:408: SAWarning: New instance <Product at 0x7f1ff65e0ba8> with identity key (<class '__main__.Product'>, (1,), None) conflicts with persistent instance <Product at 0x7f1ff60a4550>
 
@@ -2454,7 +2502,9 @@ The change is that the :class:`.FlushError` is altered to be only a warning::
 Subsequent to that, the condition will attempt to insert the row into the
 database which will emit :class:`.IntegrityError`, which is the same error that
 would be raised if the primary key identity was not already present in the
-:class:`.Session`::
+:class:`.Session`:
+
+.. sourcecode:: text
 
     sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: product.id
 
@@ -2462,7 +2512,6 @@ The rationale is to allow code that is using :class:`.IntegrityError` to catch
 duplicates to function regardless of the existing state of the
 :class:`.Session`, as is often done using savepoints::
 
-
     # add another Product with same primary key
     try:
         with session.begin_nested():
@@ -2519,7 +2568,9 @@ disallowed::
         # this is now an error
         addresses = relationship("Address", viewonly=True, cascade="all, delete-orphan")
 
-The above will raise::
+The above will raise:
+
+.. sourcecode:: text
 
     sqlalchemy.exc.ArgumentError: Cascade settings
     "delete, delete-orphan, merge, save-update" apply to persistence
@@ -2562,7 +2613,9 @@ inheritance mapping::
 
 The subquery selects both the ``Engineer`` and the ``Manager`` rows, and
 even though the outer query is against ``Manager``, we get a non ``Manager``
-object back::
+object back:
+
+.. sourcecode:: text
 
     SELECT anon_1.type AS anon_1_type, anon_1.id AS anon_1_id
     FROM (SELECT employee.type AS type, employee.id AS id
@@ -2570,7 +2623,9 @@ object back::
     2020-01-29 18:04:13,524 INFO sqlalchemy.engine.base.Engine ()
     [<__main__.Engineer object at 0x7f7f5b9a9810>, <__main__.Manager object at 0x7f7f5b9a9750>]
 
-The new behavior is that this condition raises an error::
+The new behavior is that this condition raises an error:
+
+.. sourcecode:: text
 
     sqlalchemy.exc.InvalidRequestError: Row with identity key
     (<class '__main__.Employee'>, (1,), None) can't be loaded into an object;
@@ -2585,7 +2640,9 @@ to construct an entity is made.
 In the case of single inheritance mapping, the change in behavior is slightly
 more involved;   if ``Engineer`` and ``Manager`` above are mapped with
 single table inheritance, in 1.3 the following query would be emitted and
-only a ``Manager`` object is returned::
+only a ``Manager`` object is returned:
+
+.. sourcecode:: text
 
     SELECT anon_1.type AS anon_1_type, anon_1.id AS anon_1_id
     FROM (SELECT employee.type AS type, employee.id AS id
@@ -2603,7 +2660,9 @@ to return additional rows where the columns that correspond to the inheriting
 entity are NULL, which is a valid use case.    The behavior is now equivalent
 to that of joined table inheritance, where it is assumed that the subquery
 returns the correct rows and an error is raised if an unexpected polymorphic
-identity is encountered::
+identity is encountered:
+
+.. sourcecode:: text
 
     SELECT anon_1.type AS anon_1_type, anon_1.id AS anon_1_id
     FROM (SELECT employee.type AS type, employee.id AS id
@@ -2622,11 +2681,15 @@ is to adjust the given subquery to correctly filter the rows based on the
 discriminator column::
 
     print(
-        s.query(Manager).select_entity_from(
-            s.query(Employee).filter(Employee.discriminator == 'manager').
-            subquery()).all()
+        s.query(Manager)
+        .select_entity_from(
+            s.query(Employee).filter(Employee.discriminator == "manager").subquery()
+        )
+        .all()
     )
 
+.. sourcecode:: sql
+
     SELECT anon_1.type AS anon_1_type, anon_1.id AS anon_1_id
     FROM (SELECT employee.type AS type, employee.id AS id
     FROM employee
@@ -2708,7 +2771,9 @@ be cached before the VALUES are rendered.
 
 A quick test of the ``execute_values()`` approach using the
 ``bulk_inserts.py`` script in the :ref:`examples_performance` example
-suite reveals an approximate **fivefold performance increase**::
+suite reveals an approximate **fivefold performance increase**:
+
+.. sourcecode:: text
 
     $ python -m examples.performance bulk_inserts --test test_core_insert --num 100000 --dburl postgresql://scott:tiger@localhost/test
 
index 801235872379d6479fa5712069fb5729627ed73a..6f345003c814f7841395d14d560bcd804abefde0 100644 (file)
@@ -226,14 +226,18 @@ Given the example program below::
 The above program uses several patterns that many users will already identify
 as "legacy", namely the use of the :meth:`_engine.Engine.execute` method
 that's part of the "connectionless execution" API.  When we run the above
-program against 1.4, it returns a single line::
+program against 1.4, it returns a single line:
+
+.. sourcecode:: text
 
   $ python test3.py
   [(1,)]
 
 To enable "2.0 deprecations mode", we enable the ``SQLALCHEMY_WARN_20=1``
 variable, and additionally ensure that a `warnings filter`_ that will not
-suppress any warnings is selected::
+suppress any warnings is selected:
+
+.. sourcecode:: text
 
     SQLALCHEMY_WARN_20=1 python -W always::DeprecationWarning test3.py
 
@@ -244,7 +248,9 @@ using Python option ``-W error::DeprecationWarning``.
 
 .. _warnings filter: https://docs.python.org/3/library/warnings.html#the-warnings-filter
 
-With warnings turned on, our program now has a lot to say::
+With warnings turned on, our program now has a lot to say:
+
+.. sourcecode:: text
 
   $ SQLALCHEMY_WARN_20=1 python2 -W always::DeprecationWarning test3.py
   test3.py:9: RemovedIn20Warning: The Engine.execute() function/method is considered legacy as of the 1.x series of SQLAlchemy and will be removed in 2.0. All statement execution in SQLAlchemy 2.0 is performed by the Connection.execute() method of Connection, or in the ORM by the Session.execute() method of Session. (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
@@ -1857,7 +1863,9 @@ labeling::
     result = session.execute(stmt)
 
 The above query will disambiguate the ``.id`` column of ``User`` and
-``Address``, where ``Address.id`` is rendered and tracked as ``id_1``::
+``Address``, where ``Address.id`` is rendered and tracked as ``id_1``:
+
+.. sourcecode:: sql
 
   SELECT anon_1.id AS anon_1_id, anon_1.id_1 AS anon_1_id_1,
          anon_1.user_id AS anon_1_user_id,
index 7f1180a924c2b1ec769849a6aa7152bbea2fb941..023513e467b4dd958e3c9a352098366650a9c9aa 100644 (file)
@@ -935,7 +935,9 @@ within relationships, flushing joined-inheritance models, etc::
             session.flush()
         session.commit()
 
-This test can be run from any SQLAlchemy source tree as follows::
+This test can be run from any SQLAlchemy source tree as follows:
+
+.. sourcecode:: text
 
     python -m examples.performance.bulk_inserts --test test_flush_no_pk
 
@@ -1443,17 +1445,17 @@ and pylance.  Given a program as below::
 
     import typing
 
-
     from sqlalchemy import String
     from sqlalchemy.dialects.mysql import VARCHAR
 
-
     type_ = String(255).with_variant(VARCHAR(255, charset="utf8mb4"), "mysql", "mariadb")
 
     if typing.TYPE_CHECKING:
         reveal_type(type_)
 
-A type checker like pyright will now report the type as::
+A type checker like pyright will now report the type as:
+
+.. sourcecode:: text
 
     info: Type of "type_" is "String"
 
@@ -1481,7 +1483,9 @@ Given a "true division" operation against two integer values::
 The SQL division operator on PostgreSQL for example normally acts as "floor division"
 when used against integers, meaning the above result would return the integer
 "0".  For this and similar backends, SQLAlchemy now renders the SQL using
-a form which is equivalent towards::
+a form which is equivalent towards:
+
+.. sourcecode:: text
 
     %(param_1)s / CAST(%(param_2)s AS NUMERIC)
 
@@ -1495,7 +1499,9 @@ Given a "floor division" operation against two integer values::
 The SQL division operator on MySQL and Oracle for example normally acts
 as "true division" when used against integers, meaning the above result
 would return the floating point value "0.5".  For these and similar backends,
-SQLAlchemy now renders the SQL using a form which is equivalent towards::
+SQLAlchemy now renders the SQL using a form which is equivalent towards:
+
+.. sourcecode:: text
 
     FLOOR(%(param_1)s / %(param_2)s)
 
@@ -1545,7 +1551,9 @@ the state to one that is disallowed for the duration of the already-in-progress
 method that wants to get the current connection to run a database query.
 
 Using the test script illustrated at :ticket:`7433`, the previous
-error case looks like::
+error case looks like:
+
+.. sourcecode:: text
 
     Traceback (most recent call last):
     File "/home/classic/dev/sqlalchemy/test3.py", line 30, in worker
@@ -1560,7 +1568,9 @@ error case looks like::
 
 Where the ``_connection_for_bind()`` method isn't able to continue since
 concurrent access placed it into an invalid state.  Using the new approach, the
-originator of the state change throws the error instead::
+originator of the state change throws the error instead:
+
+.. sourcecode:: text
 
     File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/orm/session.py", line 1785, in close
        self._close_impl(invalidate=False)
index 0aee788def15b31c67581c7df5bc9edc883ec9e6..e9a21c23f6992b24818d04834608e8930e667de9 100644 (file)
@@ -784,7 +784,9 @@ render the schema as ``user_schema_one``::
 
     result = connection.execute(user_table.select())
 
-The above code will invoke SQL on the database of the form::
+The above code will invoke SQL on the database of the form:
+
+.. sourcecode:: sql
 
     SELECT user_schema_one.user.id, user_schema_one.user.name FROM
     user_schema_one.user
@@ -1015,7 +1017,9 @@ to such statements because they already exist in string form, and there
 is nothing known about what kinds of result rows will be returned since
 SQLAlchemy does not parse SQL strings ahead of time.
 
-The next statements we see are the CREATE TABLE statements::
+The next statements we see are the CREATE TABLE statements:
+
+.. sourcecode:: sql
 
   INFO sqlalchemy.engine.Engine
   CREATE TABLE a (
@@ -1055,6 +1059,8 @@ So far our cache is still empty.  The next statements will be cached however,
 a segment looks like::
 
 
+.. sourcecode:: sql
+
   INFO sqlalchemy.engine.Engine INSERT INTO a (data) VALUES (?)
   INFO sqlalchemy.engine.Engine [generated in 0.00011s] (None,)
   INFO sqlalchemy.engine.Engine INSERT INTO a (data) VALUES (?)
@@ -1113,7 +1119,9 @@ the
 
 Our example program then performs some SELECTs where we can see the same
 pattern of "generated" then "cached", for the SELECT of the "a" table as well
-as for subsequent lazy loads of the "b" table::
+as for subsequent lazy loads of the "b" table:
+
+.. sourcecode:: text
 
   INFO sqlalchemy.engine.Engine SELECT a.id AS a_id, a.data AS a_data
   FROM a
@@ -1302,7 +1310,9 @@ as a complete SQL expression, as follows::
 
         return text
 
-The approach above will generate a compiled SELECT statement that looks like::
+The approach above will generate a compiled SELECT statement that looks like:
+
+.. sourcecode:: sql
 
     SELECT x FROM y
     LIMIT __[POSTCOMPILE_param_1]
@@ -1785,13 +1795,13 @@ and more support towards in recent release series.
 Concretely, for most backends the behavior will rewrite a statement of the
 form:
 
-.. sourcecode:: none
+.. sourcecode:: sql
 
     INSERT INTO a (data, x, y) VALUES (%(data)s, %(x)s, %(y)s) RETURNING a.id
 
 into a "batched" form as:
 
-.. sourcecode:: none
+.. sourcecode:: sql
 
     INSERT INTO a (data, x, y) VALUES
         (%(data_0)s, %(x_0)s, %(y_0)s),
@@ -1950,7 +1960,9 @@ compared to how the psycopg2-only feature worked in previous 1.x series of
 SQLAlchemy, where the production of multiple INSERT statements was hidden from
 logging and events.  Logging display will truncate the long lists of parameters for readability,
 and will also indicate the specific batch of each statement. The example below illustrates
-an excerpt of this logging::
+an excerpt of this logging:
+
+.. sourcecode:: text
 
   INSERT INTO a (data, x, y) VALUES (?, ?, ?), ... 795 characters truncated ...  (?, ?, ?), (?, ?, ?) RETURNING id
   [generated in 0.00177s (insertmanyvalues)] ('d0', 0, 0, 'd1',  ...
index a100acc1626e0547a4050179ea0e586ee8010b07..f5a4b5f134d3770ff8454e1d9344cfe361fe5c2b 100644 (file)
@@ -578,7 +578,9 @@ generate very long names given the column names in use::
     )
 
 On the PostgreSQL dialect, names longer than 63 characters will be truncated
-as in the following example::
+as in the following example:
+
+.. sourcecode:: sql
 
     CREATE TABLE long_names (
         information_channel_code INTEGER,
@@ -680,7 +682,9 @@ A typical convention is ``"ck_%(table_name)s_%(constraint_name)s"``::
         CheckConstraint("value > 5", name="value_gt_5"),
     )
 
-The above table will produce the name ``ck_foo_value_gt_5``::
+The above table will produce the name ``ck_foo_value_gt_5``:
+
+.. sourcecode:: sql
 
     CREATE TABLE foo (
         value INTEGER,
@@ -708,7 +712,9 @@ or by using a :func:`_expression.column` inline::
         "foo", metadata_obj, Column("value", Integer), CheckConstraint(column("value") > 5)
     )
 
-Both will produce the name ``ck_foo_value``::
+Both will produce the name ``ck_foo_value``:
+
+.. sourcecode:: sql
 
     CREATE TABLE foo (
         value INTEGER,
@@ -746,7 +752,9 @@ and then applying a name to the type::
 
     Table("foo", metadata_obj, Column("flag", Boolean(name="flag_bool")))
 
-The above table will produce the constraint name ``ck_foo_flag_bool``::
+The above table will produce the constraint name ``ck_foo_flag_bool``:
+
+.. sourcecode:: sql
 
     CREATE TABLE foo (
         flag BOOL,
@@ -770,7 +778,9 @@ only one column::
 
     Table("foo", metadata_obj, Column("flag", Boolean()))
 
-The above schema will produce::
+The above schema will produce:
+
+.. sourcecode:: sql
 
     CREATE TABLE foo (
         flag BOOL,
index 6f29adc14dea1b286520c081432b642ef7bc9b05..d896869cfb306cee310b3d3ab8cc3c92364b4a28 100644 (file)
@@ -398,7 +398,9 @@ and use it in a :func:`_expression.select` construct::
 The resulting SQL embeds both functions as appropriate.   ``ST_AsText``
 is applied to the columns clause so that the return value is run through
 the function before passing into a result set, and ``ST_GeomFromText``
-is run on the bound parameter so that the passed-in value is converted::
+is run on the bound parameter so that the passed-in value is converted:
+
+.. sourcecode:: sql
 
     SELECT geometry.geom_id, ST_AsText(geometry.geom_data) AS geom_data_1
     FROM geometry
@@ -412,7 +414,9 @@ label is moved to the outside of the wrapped expression::
 
     print(select(geometry.c.geom_data.label("my_data")))
 
-Output::
+Output:
+
+.. sourcecode:: sql
 
     SELECT ST_AsText(geometry.geom_data) AS my_data
     FROM geometry
@@ -477,17 +481,19 @@ transparently::
         )
 
 The ``pgp_sym_encrypt`` and ``pgp_sym_decrypt`` functions are applied
-to the INSERT and SELECT statements::
+to the INSERT and SELECT statements:
+
+.. sourcecode:: sql
 
   INSERT INTO message (username, message)
     VALUES (%(username)s, pgp_sym_encrypt(%(message)s, %(pgp_sym_encrypt_1)s))
-    {'username': 'some user', 'message': 'this is my message',
-      'pgp_sym_encrypt_1': 'this is my passphrase'}
+    -- {'username': 'some user', 'message': 'this is my message',
+    --  'pgp_sym_encrypt_1': 'this is my passphrase'}
 
   SELECT pgp_sym_decrypt(message.message, %(pgp_sym_decrypt_1)s) AS message_1
     FROM message
     WHERE message.username = %(username_1)s
-    {'pgp_sym_decrypt_1': 'this is my passphrase', 'username_1': 'some user'}
+    -- {'pgp_sym_decrypt_1': 'this is my passphrase', 'username_1': 'some user'}
 
 
 
index 0e6d641c6adfdab20a312f938546a1552af087e1..35e3c37f4c70e5e81fa32bff1e729437992af614 100644 (file)
@@ -217,7 +217,7 @@ elements will be included in the CREATE TABLE sequence only against the
 PostgreSQL dialect.  If we run ``meta.create_all()`` against the SQLite
 dialect, for example, neither construct will be included:
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
     >>> from sqlalchemy import create_engine
     >>> sqlite_engine = create_engine("sqlite+pysqlite://", echo=True)
@@ -239,7 +239,7 @@ However, if we run the same commands against a PostgreSQL database, we will
 see inline DDL for the CHECK constraint as well as a separate CREATE
 statement emitted for the index:
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
     >>> from sqlalchemy import create_engine
     >>> postgresql_engine = create_engine(
index 60e7e2bc57dc3cbc13ace11a9f6e386c54cd4e78..e493512fedf431b89db4a23bc17fb52d86c30b34 100644 (file)
@@ -272,7 +272,9 @@ placed in the CREATE TABLE statement during a :meth:`_schema.Table.create` opera
         Column("index_value", Integer, server_default=text("0")),
     )
 
-A create call for the above table will produce::
+A create call for the above table will produce:
+
+.. sourcecode:: sql
 
     CREATE TABLE test (
         abc varchar(20) default 'abc',
@@ -373,7 +375,9 @@ Where above, the table "cartitems" is associated with a sequence named
 is passed for the "cart_id" column, the "cart_id_seq" sequence will be used to
 generate a value.   Typically, the sequence function is embedded in the
 INSERT statement, which is combined with RETURNING so that the newly generated
-value can be returned to the Python code::
+value can be returned to the Python code:
+
+.. sourcecode:: sql
 
     INSERT INTO cartitems (cart_id, description, createdate)
     VALUES (next_val(cart_id_seq), 'some description', '2015-10-15 12:00:15')
@@ -545,7 +549,9 @@ or with the ORM::
         createdate = Column(DateTime)
 
 When the "CREATE TABLE" statement is emitted, on PostgreSQL it would be
-emitted as::
+emitted as:
+
+.. sourcecode:: sql
 
     CREATE TABLE cartitems (
         cart_id INTEGER DEFAULT nextval('cart_id_seq') NOT NULL,
@@ -605,7 +611,9 @@ Example::
     )
 
 The DDL for the ``square`` table when run on a PostgreSQL 12 backend will look
-like::
+like:
+
+.. sourcecode:: sql
 
     CREATE TABLE square (
         id SERIAL NOT NULL,
@@ -696,7 +704,9 @@ Example::
     )
 
 The DDL for the ``data`` table when run on a PostgreSQL 12 backend will look
-like::
+like:
+
+.. sourcecode:: sql
 
     CREATE TABLE data (
         id INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 42 CYCLE) NOT NULL,
@@ -712,7 +722,9 @@ of the column, ignoring the value passed with the statement or raising an
 error, depending on the backend. To activate this mode, set the parameter
 :paramref:`_schema.Identity.always` to ``True`` in the
 :class:`.Identity` construct. Updating the previous
-example to include this parameter will generate the following DDL::
+example to include this parameter will generate the following DDL:
+
+.. sourcecode:: sql
 
     CREATE TABLE data (
         id INTEGER GENERATED ALWAYS AS IDENTITY (START WITH 42 CYCLE) NOT NULL,
index 7b6e7b747497bd118234e6091d3039142bf870cb..e3e2ac7bfd5688b0364d26f3c1fbba3c8854b4ef 100644 (file)
@@ -65,7 +65,7 @@ well as optional keyword arguments for additional configuration. In some cases
 a file path is accepted, and in others a "data source name" replaces the "host"
 and "database" portions. The typical form of a database URL is:
 
-.. sourcecode:: none
+.. sourcecode:: text
 
     dialect+driver://username:password@host:port/database
 
@@ -87,7 +87,7 @@ Below is an example of a URL that includes the password ``"kx@jj5/g"``, where th
 "at" sign and slash characters are represented as ``%40`` and ``%2F``,
 respectively:
 
-.. sourcecode:: none
+.. sourcecode:: text
 
     postgresql+pg8000://dbuser:kx%40jj5%2Fg@pghost10/appdb
 
index c2c636d85f5030810e5546bde6c457b6e24e9e56..5a84bc2ffa6e663604644df68755e88c65a950d3 100644 (file)
@@ -234,7 +234,9 @@ To illustrate the ramifications of this issue, consider tables from the
 schema is the default schema of our database connection, or if using a database
 such as PostgreSQL suppose the "project" schema is set up in the PostgreSQL
 ``search_path``.  This would mean that the database accepts the following
-two SQL statements as equivalent::
+two SQL statements as equivalent:
+
+.. sourcecode:: sql
 
     -- schema qualified
     SELECT message_id FROM project.messages
@@ -426,7 +428,9 @@ column reflection using the :meth:`_events.DDLEvents.column_reflect` event
 in conjunction with the :meth:`_types.TypeEngine.as_generic` method.
 
 Given a table in MySQL (chosen because MySQL has a lot of vendor-specific
-datatypes and options)::
+datatypes and options):
+
+.. sourcecode:: sql
 
     CREATE TABLE IF NOT EXISTS my_table (
         id INTEGER PRIMARY KEY AUTO_INCREMENT,
index 994ecc41ade7b5cb15dc836a983d9cf943519402..3149906cb46ebacb4450a3b7a7f0b1f9b394dd37 100644 (file)
@@ -1179,7 +1179,9 @@ For the typical example that's missing
         parent_id = Column(ForeignKey("parent.id"))
         parent = relationship("Parent")
 
-The above mapping will generate warnings::
+The above mapping will generate warnings:
+
+.. sourcecode:: text
 
   SAWarning: relationship 'Child.parent' will copy column parent.id to column child.parent_id,
   which conflicts with relationship(s): 'Parent.children' (copies parent.id to child.parent_id).
index 9962b25970a2a0491f5b78fdc49b917f30a4af0c..41094adf019ccca59f0c948d9a1ff953470df220 100644 (file)
@@ -62,7 +62,9 @@ flag on those columns::
 
 All tables in a relational database should have primary keys.   Even a many-to-many
 association table - the primary key would be the composite of the two association
-columns::
+columns:
+
+.. sourcecode:: sql
 
     CREATE TABLE my_association (
       user_id INTEGER REFERENCES user(id),
@@ -263,7 +265,7 @@ SQLAlchemy implements :func:`_orm.subqueryload` by issuing a separate query,
 the results of which are matched up to the results from the first query.
 We see two queries emitted like this:
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
     >>> session.scalars(select(User).options(subqueryload(User.addresses))).all()
     {opensql}-- the "main" query
@@ -282,7 +284,7 @@ The second query embeds the first query as a source of rows.
 When the inner query uses ``OFFSET`` and/or ``LIMIT`` without ordering,
 the two queries may not see the same results:
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
     >>> user = session.scalars(
     ...     select(User).options(subqueryload(User.addresses)).limit(1)
index 3b494a7c4cda3e3bc18857ddb8943170f3a8f95a..eb2bb52edd7a1ad26862a0e6b4a053439a22f798 100644 (file)
@@ -183,7 +183,9 @@ Sometimes just plain SQL logging (enabled via python's logging module
 or via the ``echo=True`` argument on :func:`_sa.create_engine`) can give an
 idea how long things are taking.  For example, if you log something
 right after a SQL operation, you'd see something like this in your
-log::
+log:
+
+.. sourcecode:: text
 
     17:37:48,325 INFO  [sqlalchemy.engine.base.Engine.0x...048c] SELECT ...
     17:37:48,326 INFO  [sqlalchemy.engine.base.Engine.0x...048c] {<params>}
index e48ff0ec42c45fd7eaa22a50f03ae9291f646b03..9f515f9b348f6bdc1805b25787ca32ac7a573552 100644 (file)
@@ -155,7 +155,9 @@ any time and be exactly consistent with what's been flushed to the database.
 While this is theoretically possible, the usefulness of the enhancement is
 greatly decreased by the fact that many database operations require a ROLLBACK
 in any case. Postgres in particular has operations which, once failed, the
-transaction is not allowed to continue::
+transaction is not allowed to continue:
+
+.. sourcecode:: text
 
     test=> create table foo(id integer primary key);
     NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "foo_pkey" for table "foo"
index eeb5be3f37ad07b240fcf8ecaa6455c35fd0d458..b5c5180af2f8c1f5491ebc46ef858384c951b760 100644 (file)
@@ -188,7 +188,9 @@ include:
 
           print(cursor.mogrify(str(compiled), compiled.params))
 
-  The above code will produce psycopg2's raw bytestring::
+  The above code will produce psycopg2's raw bytestring:
+
+  .. sourcecode:: sql
 
       b"SELECT a.id, a.data \nFROM a \nWHERE a.data = 'a511b0fc-76da-4c47-a4b4-716a8189b7ac'::uuid"
 
@@ -206,7 +208,9 @@ include:
     print(str(compiled) % compiled.params)
 
   This will produce a non-working string, that nonetheless is suitable for
-  debugging::
+  debugging:
+
+  .. sourcecode:: sql
 
     SELECT a.id, a.data
     FROM a
@@ -230,7 +234,9 @@ include:
 
     print(re.sub(r"\?", lambda m: next(params), str(compiled)))
 
-  The above snippet prints::
+  The above snippet prints:
+
+  .. sourcecode:: sql
 
     SELECT a.id, a.data
     FROM a
@@ -259,7 +265,9 @@ include:
     e = create_engine("postgresql+psycopg2://")
     print(stmt.compile(e, compile_kwargs={"use_my_literal_recipe": True}))
 
-  The above recipe will print::
+  The above recipe will print:
+
+  .. sourcecode:: sql
 
     SELECT a.id, a.data
     FROM a
@@ -287,7 +295,9 @@ include:
 
     print(stmt.compile(e, compile_kwargs={"literal_binds": True}))
 
-  Again printing the same form::
+  Again printing the same form:
+
+  .. sourcecode:: sql
 
     SELECT a.id, a.data
     FROM a
@@ -368,7 +378,9 @@ Many :term:`DBAPI` implementations make use of the ``pyformat`` or ``format``
 `paramstyle <https://www.python.org/dev/peps/pep-0249/#paramstyle>`_, which
 necessarily involve percent signs in their syntax.  Most DBAPIs that do this
 expect percent signs used for other reasons to be doubled up (i.e. escaped) in
-the string form of the statements used, e.g.::
+the string form of the statements used, e.g.:
+
+.. sourcecode:: sql
 
     SELECT a, b FROM some_table WHERE a = %s AND c = %s AND num %% modulus = 0
 
@@ -376,7 +388,9 @@ When SQL statements are passed to the underlying DBAPI by SQLAlchemy,
 substitution of bound parameters works in the same way as the Python string
 interpolation operator ``%``, and in many cases the DBAPI actually uses this
 operator directly.  Above, the substitution of bound parameters would then look
-like::
+like:
+
+.. sourcecode:: sql
 
     SELECT a, b FROM some_table WHERE a = 5 AND c = 10 AND num % modulus = 0
 
index 9f73f0a7f442e4a23f0e85b2c7b048074389a387..7210f1a156a9cfee6f8c61c7d4ba928757283598 100644 (file)
@@ -1071,7 +1071,9 @@ Glossary
         were created, as well as a way to get at server-generated
         default values in an atomic way.
 
-        An example of RETURNING, idiomatic to PostgreSQL, looks like::
+        An example of RETURNING, idiomatic to PostgreSQL, looks like:
+
+        .. sourcecode:: sql
 
             INSERT INTO user_account (name) VALUES ('new name') RETURNING id, timestamp
 
index a93dc767eda933bdf9774260b72cd308495c6097..d42196a2db9d435412b6c69fb224f642eeee6e62 100644 (file)
@@ -132,7 +132,9 @@ Install via pip
    the latest 1.4 release.
 
 When ``pip`` is available, the distribution can be
-downloaded from PyPI and installed in one step::
+downloaded from PyPI and installed in one step:
+
+.. sourcecode:: text
 
     pip install SQLAlchemy
 
@@ -142,7 +144,9 @@ to your system. For most common platforms, a Python Wheel file will be
 downloaded which provides native Cython / C extensions prebuilt.
 
 In order to install the latest **prerelease** version, such as ``2.0.0b1``,
-pip requires that the ``--pre`` flag be used::
+pip requires that the ``--pre`` flag be used:
+
+.. sourcecode:: text
 
     pip install --pre SQLAlchemy
 
@@ -154,7 +158,9 @@ Installing manually from the source distribution
 -------------------------------------------------
 
 When not installing from pip, the source distribution may be installed
-using the ``setup.py`` script::
+using the ``setup.py`` script:
+
+.. sourcecode:: text
 
     python setup.py install
 
@@ -177,7 +183,9 @@ within various areas, with a current emphasis on the speed of Core result sets.
 
 ``setup.py`` will automatically build the extensions if an appropriate platform
 is detected, assuming the Cython package is installed.  A complete manual
-build looks like::
+build looks like:
+
+.. sourcecode:: text
 
     # cd into SQLAlchemy source distribution
     cd path/to/sqlalchemy
@@ -192,7 +200,9 @@ build looks like::
     python setup.py install
 
 Source builds may also be performed using :pep:`517` techniques, such as
-using build_::
+using build_:
+
+.. sourcecode:: text
 
     # cd into SQLAlchemy source distribution
     cd path/to/sqlalchemy
@@ -212,7 +222,9 @@ To run the build/install without even attempting to compile the Cython
 extensions, the ``DISABLE_SQLALCHEMY_CEXT`` environment variable may be
 specified. The use case for this is either for special testing circumstances,
 or in the rare case of compatibility/build issues not overcome by the usual
-"rebuild" mechanism::
+"rebuild" mechanism:
+
+.. sourcecode:: text
 
   export DISABLE_SQLALCHEMY_CEXT=1; python setup.py install
 
@@ -235,9 +247,7 @@ Checking the Installed SQLAlchemy Version
 
 This documentation covers SQLAlchemy version 2.0. If you're working on a
 system that already has SQLAlchemy installed, check the version from your
-Python prompt like this:
-
-.. sourcecode:: python+sql
+Python prompt like this::
 
      >>> import sqlalchemy
      >>> sqlalchemy.__version__  # doctest: +SKIP
index 2a66ebfc0ed1cab58ff089356169116301db57ed..2c7c0d9cf464b254e711199bf0f03c4df69d8bf9 100644 (file)
@@ -254,7 +254,7 @@ related ``Address`` objects::
 If we mark ``user1`` for deletion, after the flush operation proceeds,
 ``address1`` and ``address2`` will also be deleted:
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
     >>> sess.delete(user1)
     >>> sess.commit()
@@ -277,7 +277,7 @@ reference to ``NULL``.  Using a mapping as follows::
 Upon deletion of a parent ``User`` object, the rows in ``address`` are not
 deleted, but are instead de-associated:
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
     >>> sess.delete(user1)
     >>> sess.commit()
index d2f494401f0311027fbb67c489b0c006ae5b7ef0..815cc64c9af5371239a9855c2f4d278e244d002d 100644 (file)
@@ -63,11 +63,12 @@ of the columns to be generated, in this case the names; the
         def __repr__(self):
             return f"Vertex(start={self.start}, end={self.end})"
 
-The above mapping would correspond to a CREATE TABLE statement as::
+The above mapping would correspond to a CREATE TABLE statement as:
+
+.. sourcecode:: pycon+sql
 
     >>> from sqlalchemy.schema import CreateTable
     {sql}>>> print(CreateTable(Vertex.__table__))
-
     CREATE TABLE vertices (
       id INTEGER NOT NULL,
       x1 INTEGER NOT NULL,
@@ -93,7 +94,7 @@ well as with instances of the ``Vertex`` class, where the ``.start`` and
   We can create a ``Vertex`` object, assign ``Point`` objects as members,
   and they will be persisted as expected:
 
-  .. sourcecode:: python+sql
+  .. sourcecode:: pycon+sql
 
     >>> v = Vertex(start=Point(3, 4), end=Point(5, 6))
     >>> session.add(v)
@@ -110,7 +111,7 @@ well as with instances of the ``Vertex`` class, where the ``.start`` and
   as possible when using the ORM :class:`_orm.Session` (including the legacy
   :class:`_orm.Query` object) to select ``Point`` objects:
 
-  .. sourcecode:: python+sql
+  .. sourcecode:: pycon+sql
 
     >>> stmt = select(Vertex.start, Vertex.end)
     {sql}>>> session.execute(stmt).all()
@@ -124,7 +125,7 @@ well as with instances of the ``Vertex`` class, where the ``.start`` and
   The ``Vertex.start`` and ``Vertex.end`` attributes may be used in
   WHERE criteria and similar, using ad-hoc ``Point`` objects for comparisons:
 
-  .. sourcecode:: python+sql
+  .. sourcecode:: pycon+sql
 
     >>> stmt = select(Vertex).where(Vertex.start == Point(3, 4)).where(Vertex.end < Point(7, 8))
     {sql}>>> session.scalars(stmt).all()
@@ -153,7 +154,7 @@ well as with instances of the ``Vertex`` class, where the ``.start`` and
   By default, the ``Point`` object **must be replaced by a new object** for
   changes to be detected:
 
-  .. sourcecode:: python+sql
+  .. sourcecode:: pycon+sql
 
     {sql}>>> v1 = session.scalars(select(Vertex)).one()
     SELECT vertices.id, vertices.x1, vertices.y1, vertices.x2, vertices.y2
@@ -161,8 +162,8 @@ well as with instances of the ``Vertex`` class, where the ``.start`` and
     [...] ()
     {stop}
 
-    v1.end = Point(x=10, y=14)
-    {sql}session.commit()
+    >>> v1.end = Point(x=10, y=14)
+    {sql}>>> session.commit()
     UPDATE vertices SET x2=?, y2=? WHERE vertices.id = ?
     [...] (10, 14, 1)
     COMMIT
index 78837775be88cc4a4809fa512679638315a4710c..fbb1a89e9a31a86edffd2a63638b17da0340d3d7 100644 (file)
@@ -235,7 +235,9 @@ type of the other::
             remote_side=ip_address,
         )
 
-The above relationship will produce a join like::
+The above relationship will produce a join like:
+
+.. sourcecode:: sql
 
     SELECT host_entry.id, host_entry.ip_address, host_entry.content
     FROM host_entry JOIN host_entry AS host_entry_1
@@ -308,7 +310,9 @@ Above, a query such as::
 
     select(IPA).join(IPA.network)
 
-Will render as::
+Will render as:
+
+.. sourcecode:: sql
 
     SELECT ip_address.id AS ip_address_id, ip_address.v4address AS ip_address_v4address
     FROM ip_address JOIN network ON ip_address.v4address << network.v4representation
@@ -511,7 +515,9 @@ we'll be dealing with collections so we keep things configured as "one to many":
         )
 
 Above, if given an ``Element`` object with a path attribute of ``"/foo/bar2"``,
-we seek for a load of ``Element.descendants`` to look like::
+we seek for a load of ``Element.descendants`` to look like:
+
+.. sourcecode:: sql
 
     SELECT element.path AS element_path
     FROM element
index abcd75804345521d3e57cf5f0d2f9a191057a8c6..f98f2bb1ea609968832ec25436104bab24145fa2 100644 (file)
@@ -559,7 +559,9 @@ to ensure that the fetch occurs::
 
 With a mapping similar to the above, the SQL rendered by the ORM for
 INSERT and UPDATE will include ``created`` and ``updated`` in the RETURNING
-clause::
+clause:
+
+.. sourcecode:: sql
 
   INSERT INTO my_table (created) VALUES (now()) RETURNING my_table.id, my_table.created, my_table.updated
 
index f2be63c89e2e8ebb623390cdf4fb1086d2ec3c33..e99cb3f24aaa92840d6074cf234c662f3745bf34 100644 (file)
@@ -299,7 +299,7 @@ contains a trigger which fires the first time the attribute is accessed.  This
 trigger typically issues a SQL call at the point of access
 in order to load the related object or objects:
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
     >>> spongebob.addresses
     {opensql}SELECT
@@ -424,7 +424,7 @@ as a default loading option on the mapping, in particular when used for
 collections rather than many-to-one-references.   This is achieved
 using the :func:`_orm.joinedload` loader option:
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
     >>> from sqlalchemy import select
     >>> from sqlalchemy.orm import joinedload
@@ -481,7 +481,7 @@ At the query option level, via the :paramref:`_orm.joinedload.innerjoin` flag::
 The JOIN will right-nest itself when applied in a chain that includes
 an OUTER JOIN:
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
     >>> from sqlalchemy import select
     >>> from sqlalchemy.orm import joinedload
@@ -550,7 +550,7 @@ LEFT OUTER JOIN from ``users`` to ``addresses``, however the ``ORDER BY`` added
 against ``Address.email_address`` is not valid - the ``Address`` entity is not
 named in the query:
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
     >>> from sqlalchemy import select
     >>> from sqlalchemy.orm import joinedload
@@ -580,7 +580,7 @@ Above, ``ORDER BY addresses.email_address`` is not valid since ``addresses`` is
 FROM list.   The correct way to load the ``User`` records and order by email
 address is to use :meth:`_sql.Select.join`:
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
     >>> from sqlalchemy import select
     >>> stmt = (
@@ -608,7 +608,7 @@ columns from ``addresses`` are not included in the result at all.   We can add
 are ordering on, the other is used anonymously to load the contents of the
 ``User.addresses`` collection:
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
 
     >>> stmt = (
@@ -644,7 +644,7 @@ use just one JOIN for collection loading as well as ordering, we use the
 to see why :func:`joinedload` does what it does, consider if we were
 **filtering** on a particular ``Address``:
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
     >>> stmt = (
     ...     select(User)
@@ -680,7 +680,7 @@ can change how the collection is loaded completely independently of SQL used to
 retrieve the actual ``User`` rows we want.  Below we change :func:`_orm.joinedload`
 into :func:`.subqueryload`:
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
     >>> stmt = (
     ...     select(User)
@@ -738,7 +738,7 @@ values of the parent object, or in the case of a many-to-one
 relationship to the those of the child objects, inside of an IN clause, in
 order to load related associations:
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
     >>> from sqlalchemy import select
     >>> from sqlalchemy import selectinload
@@ -779,7 +779,7 @@ statement has no joins or subqueries at all.
 For simple [1]_ many-to-one loads, a JOIN is also not needed as the foreign key
 value from the parent object is used:
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
     >>> from sqlalchemy import select
     >>> from sqlalchemy import selectinload
@@ -886,7 +886,7 @@ inside of a subquery, so that we retrieve the same list of primary keys
 for the primary object being returned, then link that to the sum of all
 the collection members to load them at once:
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
     >>> from sqlalchemy import select
     >>> from sqlalchemy.orm import subqueryload
index 5d1848812e4a313e9a4c3908b2df4b619db03bd8..21f4a3c675ca8c4fbefe377142203025cafafae7 100644 (file)
@@ -370,7 +370,7 @@ to ``user_id``, causing a failure.
 Most :meth:`~.Session.merge` issues can be examined by first checking -
 is the object prematurely in the session ?
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
     >>> a1 = Address(id=existing_a1, user_id=user.id)
     >>> assert a1 not in session
@@ -449,7 +449,7 @@ We see that while the internal "state" still hangs around, the values which
 correspond to the ``id`` and ``name`` columns are gone.   If we were to access
 one of these columns and are watching SQL, we'd see this:
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
     >>> print(user.name)
     {opensql}SELECT user.id AS user_id, user.name AS user_name
index 2e69ee77b146e34a09c1d3160408af541a886696..abbe149378aaa322c84ca9db83e7e3d48a79f6e9 100644 (file)
@@ -71,11 +71,13 @@ Above, the ``User`` mapping tracks integer versions using the column
 ``version_id``.   When an object of type ``User`` is first flushed, the
 ``version_id`` column will be given a value of "1".   Then, an UPDATE
 of the table later on will always be emitted in a manner similar to the
-following::
+following:
+
+.. sourcecode:: sql
 
     UPDATE user SET version_id=:version_id, name=:name
     WHERE user.id = :user_id AND user.version_id = :user_version_id
-    {"name": "new name", "version_id": 2, "user_id": 1, "user_version_id": 1}
+    -- {"name": "new name", "version_id": 2, "user_id": 1, "user_version_id": 1}
 
 The above UPDATE statement is updating the row that not only matches
 ``user.id = 1``, it also is requiring that ``user.version_id = 1``, where "1"
@@ -181,23 +183,27 @@ otherwise if emitting a SELECT statement afterwards, there is still a potential
 race condition where the version counter may change before it can be fetched.
 
 When the target database supports RETURNING, an INSERT statement for our ``User`` class will look
-like this::
+like this:
+
+.. sourcecode:: sql
 
     INSERT INTO "user" (name) VALUES (%(name)s) RETURNING "user".id, "user".xmin
-    {'name': 'ed'}
+    -- {'name': 'ed'}
 
 Where above, the ORM can acquire any newly generated primary key values along
 with server-generated version identifiers in one statement.   When the backend
 does not support RETURNING, an additional SELECT must be emitted for **every**
 INSERT and UPDATE, which is much less efficient, and also introduces the possibility of
-missed version counters::
+missed version counters:
+
+.. sourcecode:: sql
 
     INSERT INTO "user" (name) VALUES (%(name)s)
-    {'name': 'ed'}
+    -- {'name': 'ed'}
 
     SELECT "user".version_id AS user_version_id FROM "user" where
     "user".id = :param_1
-    {"param_1": 1}
+    -- {"param_1": 1}
 
 It is *strongly recommended* that server side version counters only be used
 when absolutely necessary and only on backends that support :term:`RETURNING`,
index c5871d2124187b6463855e59bfcaec32f1a71780..38511e579ddad2a1f75d15c7d7fc0d8eb577e680 100644 (file)
@@ -1,4 +1,5 @@
 git+https://github.com/sqlalchemyorg/changelog.git#egg=changelog
 git+https://github.com/sqlalchemyorg/sphinx-paramlinks.git#egg=sphinx-paramlinks
 git+https://github.com/sqlalchemyorg/zzzeeksphinx.git#egg=zzzeeksphinx
-sphinx-copybutton
\ No newline at end of file
+sphinx-copybutton
+sphinx-autobuild
index 16357d19004972fe134594003faf008b4db3c517..e187ab16c695f40ec5217f54a628c3cbade10bf6 100644 (file)
@@ -628,7 +628,7 @@ and :meth:`_sql.Select.having` methods.   Below we illustrate selecting
 user name fields as well as count of addresses, for those users that have more
 than one address:
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
     >>> with engine.connect() as conn:
     ...     result = conn.execute(
@@ -880,7 +880,7 @@ shows a series of ``User`` and ``Address`` objects, where the data for
 each ``Address`` object ultimately came from a subquery against the
 ``address`` table rather than that table directly:
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
     >>> subq = select(Address).where(~Address.email_address.like("%@aol.com")).subquery()
     >>> address_subq = aliased(Address, subq)
@@ -909,7 +909,7 @@ each ``Address`` object ultimately came from a subquery against the
 Another example follows, which is exactly the same except it makes use of the
 :class:`_sql.CTE` construct instead:
 
-.. sourcecode:: python+sql
+.. sourcecode:: pycon+sql
 
     >>> cte_obj = select(Address).where(~Address.email_address.like("%@aol.com")).cte()
     >>> address_cte = aliased(Address, cte_obj)
index 5414dd012efcb72e1f439ea30c9c10792f4f05b3..6cdbb9e3a9c67d89c14ca1aeb7d844f9e2d1194c 100644 (file)
@@ -254,8 +254,8 @@ as well as the :meth:`_engine.Result.scalar_one` method):
 
 .. sourcecode:: pycon+sql
 
-    {sql}>>> sandy = session.execute(select(User).filter_by(name="sandy")).scalar_one()
-    BEGIN (implicit)
+    >>> sandy = session.execute(select(User).filter_by(name="sandy")).scalar_one()
+    {opensql}BEGIN (implicit)
     SELECT user_account.id, user_account.name, user_account.fullname
     FROM user_account
     WHERE user_account.name = ?
@@ -332,8 +332,8 @@ Let's load up ``patrick`` from the database:
 
 .. sourcecode:: pycon+sql
 
-    {sql}>>> patrick = session.get(User, 3)
-    SELECT user_account.id AS user_account_id, user_account.name AS user_account_name,
+    >>> patrick = session.get(User, 3)
+    {opensql}SELECT user_account.id AS user_account_id, user_account.name AS user_account_name,
     user_account.fullname AS user_account_fullname
     FROM user_account
     WHERE user_account.id = ?
@@ -485,8 +485,8 @@ and of course the database data is present again as well:
 
 .. sourcecode:: pycon+sql
 
-    {sql}>>> session.execute(select(User).where(User.name == 'patrick')).scalar_one() is patrick
-    SELECT user_account.id, user_account.name, user_account.fullname
+    >>> session.execute(select(User).where(User.name == "patrick")).scalar_one() is patrick
+    {opensql}SELECT user_account.id, user_account.name, user_account.fullname
     FROM user_account
     WHERE user_account.name = ?
     [...] ('patrick',){stop}
index 18ea5315e24c53888d3cc7b1fcd340cc912126b3..b01290a7ca5d87b9f1c309751186109ea26add29 100644 (file)
@@ -33,6 +33,7 @@ def _format_block(
     else:
         add_padding = None
         code = "\n".join(c for *_, c in input_block)
+
     try:
         formatted = format_str(code, mode=BLACK_MODE)
     except Exception as e:
@@ -106,6 +107,7 @@ def format_file(
     disable_format = False
     for line_no, line in enumerate(original.splitlines(), 1):
         # start_code_section requires no spaces at the start
+
         if start_code_section.match(line.strip()):
             if plain_block:
                 buffer.extend(