Fixed #30365 -- Fixed syntax highlighting in SQL examples.

Sphinx interprets some "%[a-z]" in SQL statements as a
"Literal.String.Interpol" which leads to incorrect highlighting.
This commit is contained in:
Daniel Musketa 2019-04-13 15:49:55 +02:00 committed by Mariusz Felisiak
parent 25b5eea8cd
commit 6fd9c9daa6
6 changed files with 151 additions and 52 deletions

View File

@ -14,7 +14,9 @@ A simple lookup example
Let's start with a simple custom lookup. We will write a custom lookup ``ne``
which works opposite to ``exact``. ``Author.objects.filter(name__ne='Jack')``
will translate to the SQL::
will translate to the SQL:
.. code-block:: sql
"author"."name" <> 'Jack'
@ -124,14 +126,18 @@ Next, let's register it for ``IntegerField``::
IntegerField.register_lookup(AbsoluteValue)
We can now run the queries we had before.
``Experiment.objects.filter(change__abs=27)`` will generate the following SQL::
``Experiment.objects.filter(change__abs=27)`` will generate the following SQL:
.. code-block:: sql
SELECT ... WHERE ABS("experiments"."change") = 27
By using ``Transform`` instead of ``Lookup`` it means we are able to chain
further lookups afterwards. So
``Experiment.objects.filter(change__abs__lt=27)`` will generate the following
SQL::
SQL:
.. code-block:: sql
SELECT ... WHERE ABS("experiments"."change") < 27
@ -139,12 +145,16 @@ Note that in case there is no other lookup specified, Django interprets
``change__abs=27`` as ``change__abs__exact=27``.
This also allows the result to be used in ``ORDER BY`` and ``DISTINCT ON``
clauses. For example ``Experiment.objects.order_by('change__abs')`` generates::
clauses. For example ``Experiment.objects.order_by('change__abs')`` generates:
.. code-block:: sql
SELECT ... ORDER BY ABS("experiments"."change") ASC
And on databases that support distinct on fields (such as PostgreSQL),
``Experiment.objects.distinct('change__abs')`` generates::
``Experiment.objects.distinct('change__abs')`` generates:
.. code-block:: sql
SELECT ... DISTINCT ON ABS("experiments"."change")
@ -178,7 +188,9 @@ indexes efficiently in some cases. In particular, when we use
``change__lt=27``. (For the ``lte`` case we could use the SQL ``BETWEEN``).
So we would like ``Experiment.objects.filter(change__abs__lt=27)`` to generate
the following SQL::
the following SQL:
.. code-block:: sql
SELECT .. WHERE "experiments"."change" < 27 AND "experiments"."change" > -27
@ -253,7 +265,9 @@ Next, let's register it::
TextField.register_lookup(UpperCase)
Now, the queryset ``Author.objects.filter(name__upper="doe")`` will generate a case
insensitive query like this::
insensitive query like this:
.. code-block:: sql
SELECT ... WHERE UPPER("author"."name") = UPPER('doe')

View File

@ -1273,7 +1273,9 @@ subclass::
word must be in at least one of ``search_fields``. For example, if
``search_fields`` is set to ``['first_name', 'last_name']`` and a user
searches for ``john lennon``, Django will do the equivalent of this SQL
``WHERE`` clause::
``WHERE`` clause:
.. code-block:: sql
WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%')
AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%')

View File

@ -445,11 +445,15 @@ Geometry example::
# the intersection pattern (the pattern here is for 'contains').
Zipcode.objects.filter(poly__relate=(geom, 'T*T***FF*'))
PostGIS SQL equivalent::
PostGIS SQL equivalent:
.. code-block:: sql
SELECT ... WHERE ST_Relate(poly, geom, 'T*T***FF*')
SpatiaLite SQL equivalent::
SpatiaLite SQL equivalent:
.. code-block:: sql
SELECT ... WHERE Relate(poly, geom, 'T*T***FF*')
@ -458,7 +462,9 @@ Raster example::
Zipcode.objects.filter(poly__relate=(rast, 1, 'T*T***FF*'))
Zipcode.objects.filter(rast__2__relate=(rast, 1, 'T*T***FF*'))
PostGIS SQL equivalent::
PostGIS SQL equivalent:
.. code-block:: sql
SELECT ... WHERE ST_Relate(poly, ST_Polygon(rast, 1), 'T*T***FF*')
SELECT ... WHERE ST_Relate(ST_Polygon(rast, 2), ST_Polygon(rast, 1), 'T*T***FF*')
@ -477,7 +483,9 @@ Example::
Zipcode.objects.filter(poly__relate=(geom, 'anyinteract'))
Oracle SQL equivalent::
Oracle SQL equivalent:
.. code-block:: sql
SELECT ... WHERE SDO_RELATE(poly, geom, 'anyinteract')
@ -552,7 +560,9 @@ Example::
Zipcode.objects.filter(poly__left=geom)
PostGIS equivalent::
PostGIS equivalent:
.. code-block:: sql
SELECT ... WHERE poly << geom
@ -571,7 +581,9 @@ Example::
Zipcode.objects.filter(poly__right=geom)
PostGIS equivalent::
PostGIS equivalent:
.. code-block:: sql
SELECT ... WHERE poly >> geom
@ -590,7 +602,9 @@ Example::
Zipcode.objects.filter(poly__overlaps_left=geom)
PostGIS equivalent::
PostGIS equivalent:
.. code-block:: sql
SELECT ... WHERE poly &< geom
@ -610,7 +624,9 @@ Example::
Zipcode.objects.filter(poly__overlaps_right=geom)
PostGIS equivalent::
PostGIS equivalent:
.. code-block:: sql
SELECT ... WHERE poly &> geom
@ -629,7 +645,9 @@ Example::
Zipcode.objects.filter(poly__overlaps_above=geom)
PostGIS equivalent::
PostGIS equivalent:
.. code-block:: sql
SELECT ... WHERE poly |&> geom
@ -648,7 +666,9 @@ Example::
Zipcode.objects.filter(poly__overlaps_below=geom)
PostGIS equivalent::
PostGIS equivalent:
.. code-block:: sql
SELECT ... WHERE poly &<| geom
@ -667,7 +687,9 @@ Example::
Zipcode.objects.filter(poly__strictly_above=geom)
PostGIS equivalent::
PostGIS equivalent:
.. code-block:: sql
SELECT ... WHERE poly |>> geom
@ -686,7 +708,9 @@ Example::
Zipcode.objects.filter(poly__strictly_below=geom)
PostGIS equivalent::
PostGIS equivalent:
.. code-block:: sql
SELECT ... WHERE poly <<| geom

View File

@ -262,7 +262,9 @@ or they can be used to build a library of database functions::
queryset.annotate(field_lower=Lower('field'))
But both cases will result in a queryset where each model is annotated with an
extra attribute ``field_lower`` produced, roughly, from the following SQL::
extra attribute ``field_lower`` produced, roughly, from the following SQL:
.. code-block:: sql
SELECT
...

View File

@ -195,7 +195,9 @@ AND whose ``headline`` is "Hello"::
Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline='Hello')
In SQL terms, that evaluates to::
In SQL terms, that evaluates to:
.. code-block:: sql
SELECT ...
WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello')
@ -205,7 +207,9 @@ OR whose headline is "Hello"::
Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline='Hello')
In SQL terms, that evaluates to::
In SQL terms, that evaluates to:
.. code-block:: sql
SELECT ...
WHERE NOT pub_date > '2005-1-3'
@ -1308,9 +1312,11 @@ generated by a ``QuerySet``.
``params`` in order to protect against SQL injection attacks.
You also must not quote placeholders in the SQL string. This example is
vulnerable to SQL injection because of the quotes around ``%s``::
vulnerable to SQL injection because of the quotes around ``%s``:
"select col from sometable where othercol = '%s'" # unsafe!
.. code-block:: sql
SELECT col FROM sometable WHERE othercol = '%s' # unsafe!
You can read more about how Django's :ref:`SQL injection protection
<sql-injection-protection>` works.
@ -1337,8 +1343,9 @@ of the arguments is required, but you should use at least one of them.
is greater than Jan. 1, 2006.
Django inserts the given SQL snippet directly into the ``SELECT``
statement, so the resulting SQL of the above example would be something
like::
statement, so the resulting SQL of the above example would be something like:
.. code-block:: sql
SELECT blog_entry.*, (pub_date > '2006-01-01') AS is_recent
FROM blog_entry;
@ -1357,7 +1364,9 @@ of the arguments is required, but you should use at least one of them.
In this particular case, we're exploiting the fact that the query will
already contain the ``blog_blog`` table in its ``FROM`` clause.
The resulting SQL of the above example would be::
The resulting SQL of the above example would be:
.. code-block:: sql
SELECT blog_blog.*, (SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id) AS entry_count
FROM blog_blog;
@ -1394,7 +1403,9 @@ of the arguments is required, but you should use at least one of them.
Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
...translates (roughly) into the following SQL::
...translates (roughly) into the following SQL:
.. code-block:: sql
SELECT * FROM blog_entry WHERE (foo='a' OR bar='a') AND (baz='a')
@ -2622,7 +2633,9 @@ Examples::
Entry.objects.get(id__exact=14)
Entry.objects.get(id__exact=None)
SQL equivalents::
SQL equivalents:
.. code-block:: sql
SELECT ... WHERE id = 14;
SELECT ... WHERE id IS NULL;
@ -2650,7 +2663,9 @@ Example::
Blog.objects.get(name__iexact='beatles blog')
Blog.objects.get(name__iexact=None)
SQL equivalents::
SQL equivalents:
.. code-block:: sql
SELECT ... WHERE name ILIKE 'beatles blog';
SELECT ... WHERE name IS NULL;
@ -2675,7 +2690,9 @@ Example::
Entry.objects.get(headline__contains='Lennon')
SQL equivalent::
SQL equivalent:
.. code-block:: sql
SELECT ... WHERE headline LIKE '%Lennon%';
@ -2700,7 +2717,9 @@ Example::
Entry.objects.get(headline__icontains='Lennon')
SQL equivalent::
SQL equivalent:
.. code-block:: sql
SELECT ... WHERE headline ILIKE '%Lennon%';
@ -2722,7 +2741,9 @@ Examples::
Entry.objects.filter(id__in=[1, 3, 4])
Entry.objects.filter(headline__in='abc')
SQL equivalents::
SQL equivalents:
.. code-block:: sql
SELECT ... WHERE id IN (1, 3, 4);
SELECT ... WHERE headline IN ('a', 'b', 'c');
@ -2733,7 +2754,9 @@ instead of providing a list of literal values::
inner_qs = Blog.objects.filter(name__contains='Cheddar')
entries = Entry.objects.filter(blog__in=inner_qs)
This queryset will be evaluated as subselect statement::
This queryset will be evaluated as subselect statement:
.. code-block:: sql
SELECT ... WHERE blog.id IN (SELECT id FROM ... WHERE NAME LIKE '%Cheddar%')
@ -2782,7 +2805,9 @@ Example::
Entry.objects.filter(id__gt=4)
SQL equivalent::
SQL equivalent:
.. code-block:: sql
SELECT ... WHERE id > 4;
@ -2818,7 +2843,9 @@ Example::
Entry.objects.filter(headline__startswith='Lennon')
SQL equivalent::
SQL equivalent:
.. code-block:: sql
SELECT ... WHERE headline LIKE 'Lennon%';
@ -2836,7 +2863,9 @@ Example::
Entry.objects.filter(headline__istartswith='Lennon')
SQL equivalent::
SQL equivalent:
.. code-block:: sql
SELECT ... WHERE headline ILIKE 'Lennon%';
@ -2856,7 +2885,9 @@ Example::
Entry.objects.filter(headline__endswith='Lennon')
SQL equivalent::
SQL equivalent:
.. code-block:: sql
SELECT ... WHERE headline LIKE '%Lennon';
@ -2877,7 +2908,9 @@ Example::
Entry.objects.filter(headline__iendswith='Lennon')
SQL equivalent::
SQL equivalent:
.. code-block:: sql
SELECT ... WHERE headline ILIKE '%Lennon'
@ -2900,7 +2933,9 @@ Example::
end_date = datetime.date(2005, 3, 31)
Entry.objects.filter(pub_date__range=(start_date, end_date))
SQL equivalent::
SQL equivalent:
.. code-block:: sql
SELECT ... WHERE pub_date BETWEEN '2005-01-01' and '2005-03-31';
@ -2912,7 +2947,9 @@ numbers and even characters.
Filtering a ``DateTimeField`` with dates won't include items on the last
day, because the bounds are interpreted as "0am on the given date". If
``pub_date`` was a ``DateTimeField``, the above expression would be turned
into this SQL::
into this SQL:
.. code-block:: sql
SELECT ... WHERE pub_date BETWEEN '2005-01-01 00:00:00' and '2005-03-31 00:00:00';
@ -2950,7 +2987,9 @@ Example::
Entry.objects.filter(pub_date__year=2005)
Entry.objects.filter(pub_date__year__gte=2005)
SQL equivalent::
SQL equivalent:
.. code-block:: sql
SELECT ... WHERE pub_date BETWEEN '2005-01-01' AND '2005-12-31';
SELECT ... WHERE pub_date >= '2005-01-01';
@ -2993,7 +3032,9 @@ Example::
Entry.objects.filter(pub_date__month=12)
Entry.objects.filter(pub_date__month__gte=6)
SQL equivalent::
SQL equivalent:
.. code-block:: sql
SELECT ... WHERE EXTRACT('month' FROM pub_date) = '12';
SELECT ... WHERE EXTRACT('month' FROM pub_date) >= '6';
@ -3017,7 +3058,9 @@ Example::
Entry.objects.filter(pub_date__day=3)
Entry.objects.filter(pub_date__day__gte=3)
SQL equivalent::
SQL equivalent:
.. code-block:: sql
SELECT ... WHERE EXTRACT('day' FROM pub_date) = '3';
SELECT ... WHERE EXTRACT('day' FROM pub_date) >= '3';
@ -3131,7 +3174,9 @@ Example::
Event.objects.filter(time__hour=5)
Event.objects.filter(timestamp__hour__gte=12)
SQL equivalent::
SQL equivalent:
.. code-block:: sql
SELECT ... WHERE EXTRACT('hour' FROM timestamp) = '23';
SELECT ... WHERE EXTRACT('hour' FROM time) = '5';
@ -3156,7 +3201,9 @@ Example::
Event.objects.filter(time__minute=46)
Event.objects.filter(timestamp__minute__gte=29)
SQL equivalent::
SQL equivalent:
.. code-block:: sql
SELECT ... WHERE EXTRACT('minute' FROM timestamp) = '29';
SELECT ... WHERE EXTRACT('minute' FROM time) = '46';
@ -3181,7 +3228,9 @@ Example::
Event.objects.filter(time__second=2)
Event.objects.filter(timestamp__second__gte=31)
SQL equivalent::
SQL equivalent:
.. code-block:: sql
SELECT ... WHERE EXTRACT('second' FROM timestamp) = '31';
SELECT ... WHERE EXTRACT('second' FROM time) = '2';
@ -3204,7 +3253,9 @@ Example::
Entry.objects.filter(pub_date__isnull=True)
SQL equivalent::
SQL equivalent:
.. code-block:: sql
SELECT ... WHERE pub_date IS NULL;
@ -3224,7 +3275,9 @@ Example::
Entry.objects.get(title__regex=r'^(An?|The) +')
SQL equivalents::
SQL equivalents:
.. code-block:: sql
SELECT ... WHERE title REGEXP BINARY '^(An?|The) +'; -- MySQL
@ -3248,7 +3301,9 @@ Example::
Entry.objects.get(title__iregex=r'^(an?|the) +')
SQL equivalents::
SQL equivalents:
.. code-block:: sql
SELECT ... WHERE title REGEXP '^(an?|the) +'; -- MySQL

View File

@ -840,7 +840,9 @@ together. For example::
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)
... roughly translates into the SQL::
... roughly translates into the SQL:
.. code-block:: sql
SELECT * from polls WHERE question LIKE 'Who%'
AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')