pg.ddx.io  pgsql-www@postgresql.org mailing list archive  
help / color / mirror / Atom feed
From: Jonathan S. Katz <jkatz@postgresql.org>
To: Magnus Hagander <magnus@hagander.net>
Cc: pgsql-www@lists.postgresql.org <pgsql-www@lists.postgresql.org>
Subject: Re: Release Notes Archive Patch
Date: Wed, 27 Feb 2019 18:30:29 -0500
Message-ID: <bc9038eb-e61d-4cd8-4e01-0b3676d49d68@postgresql.org> (raw)
In-Reply-To: <CABUevEwzO34DEeAhyb3SFvq4CMnuuHLJFKHjmuVAa-XeEbCTjw@mail.gmail.com>
References: <e0f09c9a-bd2b-862a-d379-601dfabc8969@postgresql.org>
	<CABUevEwzO34DEeAhyb3SFvq4CMnuuHLJFKHjmuVAa-XeEbCTjw@mail.gmail.com>

Hi,

On 2/19/19 5:42 AM, Magnus Hagander wrote:

> A few comments on this one:
> 
> 1. It loses the "go to next minor" and "go to previous minor" links in
> the previous release notes. Those should be easy enough to get back, but
> should be done. E.g. if I'm on 9.6.3, I want links to 9.6.2 and 9.6.4.
> And we should also use the change to make it more "explicit" and *also*
> have a link to 9.6.0 on all of them amonst the links themsel
> 
> 2b. In fact, we should use this chance to create a proper set of links,
> e.g. when you get to release notes for 9.6.0, it should right then and
> there provide a list of all the minor releases I think -- to avoid
> having to go back.

So there could be an issue with that as we would have to carry the
lag/lead somehow. Not insurmountable, but given this is minimally
invasive, it would take a bit more complicating of that SQL query that
was just simplified.

> 
> 2. Links within the docs are just plain broken? E.g. the 9.6.0 release
> notes link to /docs/release/9.6.0/app-pg-dumpall.html which clearly
> doesn't exist. IIRC we discussed something around this, but it seems to
> have never made it into the patches? (It is listed in your known
> adjustments to be made above, but I could also not find a newer patch?)

I could not reproduce this. The links work fine for me.

> 
> 3. That SQL query really needs some documentation, because it takes
> quite a bit of reading to figure out what it really means. And while it
> works on my dev install, it fails when i test-ran it on the current
> database with the error "ERROR:  invalid input syntax for type numeric:
> "prior". Most likely it comes from there being a file called
> release-prior.html in versions 9.4-11.0 now. 
> 
> It should also be reviewed for the fact that you are pulling back *all*
> the documentation including *all* the contents in order to render a list
> of versions...That gets annoyingly expensive when you actually have the
> full set of documentation.

Per off-list discussion, Magnus added a simpler query that was provided.

> 
> 4. The "jump to..." list should probably be split between supported and
> unsupported versions, to keep it a bit less.

Well, with the below, I don't think we need that.

> 
> 5. In general, there's a huge amount of numbers on the index page. I'm
> not sure what's a good way to format it better, I normally leave that to
> you :) But the page is not very friendly at this point with the massive
> list of numbers you have to scroll through.

We could list out the major versions, then have the minor versions. I'm
not opposed to that. See attached.


Jonathan
From a6f252a096978d10069dc5b77e2c164dcef3119d Mon Sep 17 00:00:00 2001
From: "Jonathan S. Katz" <jonathan.katz@excoventures.com>
Date: Tue, 12 Feb 2019 20:50:48 +0100
Subject: [PATCH 3/4] Create Release Notes archive in the Documentation
 section.

This creates a consolidated area to reference all of the notes from
previous releases of PostgreSQL, as current releases only keep the
the notes for that specific major release of PostgreSQL.
---
 media/css/main.css                |  7 +++
 pgweb/docs/views.py               | 93 +++++++++++++++++++++++++++++++++++++++
 pgweb/urls.py                     |  2 +
 pgweb/util/contexts.py            |  1 +
 pgweb/util/db.py                  |  7 +++
 templates/docs/release_notes.html | 72 ++++++++++++++++++++++++++++++
 6 files changed, 182 insertions(+)
 create mode 100644 pgweb/util/db.py
 create mode 100644 templates/docs/release_notes.html

diff --git a/media/css/main.css b/media/css/main.css
index e0462ad2..de71eb34 100644
--- a/media/css/main.css
+++ b/media/css/main.css
@@ -1294,6 +1294,13 @@ table.sponsor-table tbody tr td:nth-child(3) {
     width: 30%;
 }
 
+/** Release Notes */
+#release-notes .navheader,
+#release-notes .navfooter,
+#release-notes .titlepage,
+#release-notes .toc {
+    display: none;
+}
 
 /** ALL RESPONSIVE QUERIES HERE */
 /* Small devices (landscape phones, 576px and up)*/
diff --git a/pgweb/docs/views.py b/pgweb/docs/views.py
index 4577f0ce..815f3a37 100644
--- a/pgweb/docs/views.py
+++ b/pgweb/docs/views.py
@@ -13,6 +13,7 @@ from pgweb.util.helpers import template_to_string
 from pgweb.util.misc import send_template_mail
 
 from pgweb.core.models import Version
+from pgweb.util.db import exec_to_dict
 
 from .models import DocPage
 from .forms import DocCommentForm
@@ -140,6 +141,98 @@ def manualarchive(request):
         'versions': [_VersionPdfWrapper(v) for v in versions],
     })
 
+def release_notes(request, major_version=None, minor_version=None):
+    """Contains the main archive of release notes."""
+    # this query gets a list of a unique set of release notes for each version of
+    # PostgreSQL. From PostgreSQL 9.4+, release notes are only present for their
+    # specific version of PostgreSQL, so all legacy release notes are present in
+    # 9.3 and older
+    # First the query identifies all of the release note files that have been loaded
+    # into the docs. From there, it parses the version the release notes are for
+    # from the file name, and breaks it up into "major" and "minor" version from
+    # our understanding of how PostgreSQL version numbering is handled, which is
+    # in 3 camps: 1 and older, 6.0 - 9.6, 10 -
+    # From there, we take a unique set based on the filename + releaes version,
+    # and return the content
+    sql = """
+    SELECT DISTINCT ON (file, major, minor) version, file, major, minor, content
+    FROM (
+        SELECT
+            version,
+            file,
+            CASE
+                WHEN v[1]::int >= 10 THEN v[1]::numeric
+                WHEN v[1]::int <= 1 THEN v[1]::int
+                ELSE array_to_string(v[1:2], '.')::numeric END AS major,
+            COALESCE(
+                CASE
+                    WHEN v[1]::int >= 10 THEN v[2]
+                    WHEN v[1]::int <= 1 THEN '.' || v[2]
+                    ELSE v[3]
+                END::numeric, 0
+            ) AS minor,
+            content
+        FROM (
+            SELECT
+                version,
+                file,
+                string_to_array(regexp_replace(file, 'release-(.*)\.htm.*', '\\1'), '-') AS v,
+                content
+            FROM docs
+            WHERE file ~ '^release-\d+' AND version > 0
+        ) r
+    ) rr
+    """
+    params = []
+    # if the major + minor version are provided, then we want to narrow down
+    # the results to the exact release notes
+    # otherwise ensure the release notes are returned in order
+    if major_version is not None and minor_version is not None:
+        sql += """
+        WHERE major = %s AND minor = %s;
+        """
+        params += [major_version]
+        if major_version in ['0', '1']:
+            params += ['0.{}'.format(minor_version)]
+        else:
+            params += [minor_version]
+    elif major_version is not None:
+        sql += """
+        WHERE major = %s
+        ORDER BY rr.minor DESC;
+        """
+        params += [major_version]
+    else:
+        sql += """
+        ORDER BY rr.major DESC, rr.minor DESC;
+        """
+    # run the query, loading a list of dict that contain all of the release
+    # notes that are filtered out by the query
+    release_notes = exec_to_dict(sql, params)
+    # determine which set of data to pass to the template:
+    # if both major/minor versions are present, we will load the release notes
+    # if only major version is present, then we load all the releases for that major version
+    # if neither are present, we load the list of all major versions
+    if major_version is not None and minor_version is not None:
+        try:
+            release_note = release_notes[0]
+        except IndexError:
+            raise Http404()
+        context = {
+            'major_version': major_version,
+            'minor_version': minor_version,
+            'release_note': release_note,
+        }
+    elif major_version is not None:
+        if not release_notes:
+            raise Http404()
+        context = {
+            'major_version': major_version,
+            'release_notes': release_notes,
+        }
+    else:
+        context = { 'release_notes': release_notes }
+    return render_pgweb(request, 'docs', 'docs/release_notes.html', context)
 
 @login_required
 def commentform(request, itemid, version, filename):
diff --git a/pgweb/urls.py b/pgweb/urls.py
index d8c664f2..6ded70b6 100644
--- a/pgweb/urls.py
+++ b/pgweb/urls.py
@@ -58,6 +58,8 @@ urlpatterns = [
     url(r'^docs/$', pgweb.docs.views.root),
     url(r'^docs/manuals/$', pgweb.docs.views.manuals),
     url(r'^docs/manuals/archive/$', pgweb.docs.views.manualarchive),
+    url(r'^docs/release/$', pgweb.docs.views.release_notes),
+    url(r'^docs/release/((?P<major_version>(\d\.\d)|\d+)(\.(?P<minor_version>\d+))?)/$', pgweb.docs.views.release_notes),
     # Legacy URLs for accessing the docs page; provides a permanent redirect
     url(r'^docs/(current|devel|\d+(?:\.\d)?)/(static|interactive)/((.*).html?)?$', pgweb.docs.views.docspermanentredirect),
     url(r'^docs/(current|devel|\d+(?:\.\d)?)/(.*).html?$', pgweb.docs.views.docpage),
diff --git a/pgweb/util/contexts.py b/pgweb/util/contexts.py
index 25c4787e..c38f2480 100644
--- a/pgweb/util/contexts.py
+++ b/pgweb/util/contexts.py
@@ -34,6 +34,7 @@ sitenav = {
             {'title': 'Japanese', 'link': 'http://www.postgresql.jp/document/';},
             {'title': 'Russian', 'link': 'https://postgrespro.ru/docs/postgresql';},
         ]},
+        {'title': 'Release Notes', 'link': '/docs/release/'},
         {'title': 'Books', 'link': '/docs/books/'},
         {'title': 'Online Resources', 'link': '/docs/online-resources/'},
         {'title': 'Wiki', 'link': 'https://wiki.postgresql.org';},
diff --git a/pgweb/util/db.py b/pgweb/util/db.py
new file mode 100644
index 00000000..a1efae0a
--- /dev/null
+++ b/pgweb/util/db.py
@@ -0,0 +1,7 @@
+from django.db import connection
+
+def exec_to_dict(query, params=None):
+    curs = connection.cursor()
+    curs.execute(query, params)
+    columns = [col[0] for col in curs.description]
+    return [dict(list(zip(columns, row))) for row in curs.fetchall()]
diff --git a/templates/docs/release_notes.html b/templates/docs/release_notes.html
new file mode 100644
index 00000000..d40565ad
--- /dev/null
+++ b/templates/docs/release_notes.html
@@ -0,0 +1,72 @@
+{% extends "base/page.html" %}
+
+{% block extrahead %}
+{% if major_version is not None and minor_version is not None %}
+  <base href="/docs/{{ major_version }}/" />
+{% endif %}
+{% endblock extrahead %}
+
+{%block title%}Release Notes{%endblock%}
+
+{% block contents %}
+{% regroup release_notes by major as release_note_groups %}
+
+<div id="release-notes" class="row">
+  {% if major_version is not None and minor_version is not None %}
+    <div class="col-md-10">
+      <section>
+        <h1>Release Notes <i class="far fa-file-alt"></i></h1>
+        <h2>
+          {% if major_version == '0' %}Postgres95{% else %}PostgreSQL{% endif %}
+          {{ major_version }}.{% if major_version == '0' or major_version == '1' %}{{ release_note.minor|make_list|slice:"2:4"|join:"" }}{% else %}{{ release_note.minor }}{% endif %}
+        </h2>
+      </section>
+      <div id="docContent">
+        {{ release_note.content|safe }}
+      </div>
+      <p>
+        <a href="/docs/release/{{ major_version }}/">
+          Return to the {% if major_version == '0' %}Postgres95{% else %}PostgreSQL {{ major_version }}{% endif %}
+          Release Notes
+        </a>
+      </p>
+    </div>
+  {% elif major_version is not None %}
+    <div class="col-md-10">
+      <section>
+        <h1>Release Notes <i class="far fa-file-alt"></i></h1>
+         <h2>{% if major_version == '0' %}Postgres95{% else %}PostgreSQL {{ major_version }}{% endif %}</h2>
+      </section>
+      <ul>
+        {% for release_note in release_notes %}
+          <li>
+            <a href="/docs/release/{{ major_version }}.{% if major_version == '0' or major_version == '1' %}{{ release_note.minor|make_list|slice:"2:4"|join:"" }}{% else %}{{ release_note.minor }}{% endif %}/">
+                {{ major_version }}.{% if major_version == '0' or major_version == '1' %}{{ release_note.minor|make_list|slice:"2:4"|join:"" }}{% else %}{{ release_note.minor }}{% endif %}
+            </a>
+          </li>
+        {% endfor %}
+      </ul>
+      <p>
+        <a href="/docs/release/">Return to Release Notes</a>
+      </p>
+    </div>
+  {% else %}
+    <div class="col-md-9">
+      <section>
+        <h1>Release Notes <i class="far fa-file-alt"></i></h1>
+      </section>
+      <p>Below is the complete archive of release notes for every version of PostgreSQL.</p>
+      <ul>
+        {% for release_note_group in release_note_groups %}
+          <li>
+            <a href="/docs/release/{{ release_note_group.grouper }}/">
+              {% if release_note_group.grouper == 0 %}Postgres95{% else %}PostgreSQL {{ release_note_group.grouper }}{% endif %}
+            </a>
+          </li>
+        {% endfor %}
+      </ul>
+    </div>
+  {% endif %}
+</div>
+
+{% endblock %}
-- 
2.14.3 (Apple Git-98)


From 40036e6d8cfeda577a9c1f65bfbe2c38917afef8 Mon Sep 17 00:00:00 2001
From: "Jonathan S. Katz" <jonathan.katz@excoventures.com>
Date: Wed, 13 Feb 2019 15:22:49 -0500
Subject: [PATCH 4/4] Ensure release notes from older version still load with
 404 errors.

An upcoming change in PostgreSQL keeps only release notes in their
current versions. So e.g., PostgreSQL 11 only has the release notes
for 11.0, 11.1, 11.2 etc.

Thus, for PostgreSQL 9.4 on up, any URLs such as /docs/10/release-9-6-8.html
would return a 404. Additonal, URLs with /current/ and /devel/ would break
as well.

This patch prevents these 404s from occuring by redirecting users accessing
release notes in the 9.4 and above documentation to the older versions
of the release notes by redirecting them to the notes in the specific
version. So in the above example, a user would be redirect to
/docs/9.6/release-9-6-8.html

As we do not have documentation on the website past 7.2, any release
notes from an older version are redirected to the release notes tree
in 7.2
---
 pgweb/docs/views.py | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/pgweb/docs/views.py b/pgweb/docs/views.py
index 815f3a37..2304afbc 100644
--- a/pgweb/docs/views.py
+++ b/pgweb/docs/views.py
@@ -5,8 +5,9 @@ from pgweb.util.decorators import login_required, allow_frames, content_sources
 from django.db.models import Q
 from django.conf import settings
 
-from decimal import Decimal
+from decimal import Decimal, ROUND_DOWN
 import os
+import re
 
 from pgweb.util.contexts import render_pgweb
 from pgweb.util.helpers import template_to_string
@@ -54,6 +55,34 @@ def docpage(request, version, filename):
         return HttpResponsePermanentRedirect("/docs/{0}/{1}.html".format(int(ver), filename))
 
     fullname = "%s.%s" % (filename, extension)
+
+    # Before looking up the documentation, we need to make a check for release
+    # notes. Based on a change, from PostgreSQL 9.4 and up, release notes are
+    # only available for the current version (e.g. 11 only has 11.0, 11.1, 11.2)
+    # This checks to see if there is a mismatch (e.g. ver = 9.4, fullname = release-9-3-2.html)
+    # and perform a redirect to the older version
+    if fullname.startswith('release-') and ver >= Decimal("9.4"):
+        # figure out which version to redirect to. Note that the oldest version
+        # of the docs loaded is 7.2
+        release_version = re.sub(r'release-((\d+)(-\d+)?)(-\d+)?.html',
+            r'\1', fullname).replace('-', '.')
+        # convert to Decimal for ease of manipulation
+        release_version = Decimal(release_version)
+        # if the version is greater than 10, truncate the number
+        if release_version >= Decimal('10'):
+            release_version = release_version.quantize(Decimal('1'), rounding=ROUND_DOWN)
+        # only proceed if the release version of the documents does not match
+        # the calculated release version
+        if release_version != ver:
+            url = "/docs/"
+            if release_version >= Decimal('10'):
+                url += "{}/{}".format(int(release_version), fullname)
+            elif release_version < Decimal('7.2'):
+                url += "7.2/{}".format(fullname)
+            else:
+                url += "{}/{}".format(release_version, fullname)
+            return HttpResponsePermanentRedirect(url)
+
     page = get_object_or_404(DocPage, version=ver, file=fullname)
     versions = DocPage.objects.extra(
         where=["file=%s OR file IN (SELECT file2 FROM docsalias WHERE file1=%s) OR file IN (SELECT file1 FROM docsalias WHERE file2=%s)"],
-- 
2.14.3 (Apple Git-98)



Attachments:

  [text/plain] 0003-Create-Release-Notes-archive-in-the-Documentation-se.patch (10.3K, ../bc9038eb-e61d-4cd8-4e01-0b3676d49d68@postgresql.org/2-0003-Create-Release-Notes-archive-in-the-Documentation-se.patch)
  download | inline diff:
From a6f252a096978d10069dc5b77e2c164dcef3119d Mon Sep 17 00:00:00 2001
From: "Jonathan S. Katz" <jonathan.katz@excoventures.com>
Date: Tue, 12 Feb 2019 20:50:48 +0100
Subject: [PATCH 3/4] Create Release Notes archive in the Documentation
 section.

This creates a consolidated area to reference all of the notes from
previous releases of PostgreSQL, as current releases only keep the
the notes for that specific major release of PostgreSQL.
---
 media/css/main.css                |  7 +++
 pgweb/docs/views.py               | 93 +++++++++++++++++++++++++++++++++++++++
 pgweb/urls.py                     |  2 +
 pgweb/util/contexts.py            |  1 +
 pgweb/util/db.py                  |  7 +++
 templates/docs/release_notes.html | 72 ++++++++++++++++++++++++++++++
 6 files changed, 182 insertions(+)
 create mode 100644 pgweb/util/db.py
 create mode 100644 templates/docs/release_notes.html

diff --git a/media/css/main.css b/media/css/main.css
index e0462ad2..de71eb34 100644
--- a/media/css/main.css
+++ b/media/css/main.css
@@ -1294,6 +1294,13 @@ table.sponsor-table tbody tr td:nth-child(3) {
     width: 30%;
 }
 
+/** Release Notes */
+#release-notes .navheader,
+#release-notes .navfooter,
+#release-notes .titlepage,
+#release-notes .toc {
+    display: none;
+}
 
 /** ALL RESPONSIVE QUERIES HERE */
 /* Small devices (landscape phones, 576px and up)*/
diff --git a/pgweb/docs/views.py b/pgweb/docs/views.py
index 4577f0ce..815f3a37 100644
--- a/pgweb/docs/views.py
+++ b/pgweb/docs/views.py
@@ -13,6 +13,7 @@ from pgweb.util.helpers import template_to_string
 from pgweb.util.misc import send_template_mail
 
 from pgweb.core.models import Version
+from pgweb.util.db import exec_to_dict
 
 from .models import DocPage
 from .forms import DocCommentForm
@@ -140,6 +141,98 @@ def manualarchive(request):
         'versions': [_VersionPdfWrapper(v) for v in versions],
     })
 
+def release_notes(request, major_version=None, minor_version=None):
+    """Contains the main archive of release notes."""
+    # this query gets a list of a unique set of release notes for each version of
+    # PostgreSQL. From PostgreSQL 9.4+, release notes are only present for their
+    # specific version of PostgreSQL, so all legacy release notes are present in
+    # 9.3 and older
+    # First the query identifies all of the release note files that have been loaded
+    # into the docs. From there, it parses the version the release notes are for
+    # from the file name, and breaks it up into "major" and "minor" version from
+    # our understanding of how PostgreSQL version numbering is handled, which is
+    # in 3 camps: 1 and older, 6.0 - 9.6, 10 -
+    # From there, we take a unique set based on the filename + releaes version,
+    # and return the content
+    sql = """
+    SELECT DISTINCT ON (file, major, minor) version, file, major, minor, content
+    FROM (
+        SELECT
+            version,
+            file,
+            CASE
+                WHEN v[1]::int >= 10 THEN v[1]::numeric
+                WHEN v[1]::int <= 1 THEN v[1]::int
+                ELSE array_to_string(v[1:2], '.')::numeric END AS major,
+            COALESCE(
+                CASE
+                    WHEN v[1]::int >= 10 THEN v[2]
+                    WHEN v[1]::int <= 1 THEN '.' || v[2]
+                    ELSE v[3]
+                END::numeric, 0
+            ) AS minor,
+            content
+        FROM (
+            SELECT
+                version,
+                file,
+                string_to_array(regexp_replace(file, 'release-(.*)\.htm.*', '\\1'), '-') AS v,
+                content
+            FROM docs
+            WHERE file ~ '^release-\d+' AND version > 0
+        ) r
+    ) rr
+    """
+    params = []
+    # if the major + minor version are provided, then we want to narrow down
+    # the results to the exact release notes
+    # otherwise ensure the release notes are returned in order
+    if major_version is not None and minor_version is not None:
+        sql += """
+        WHERE major = %s AND minor = %s;
+        """
+        params += [major_version]
+        if major_version in ['0', '1']:
+            params += ['0.{}'.format(minor_version)]
+        else:
+            params += [minor_version]
+    elif major_version is not None:
+        sql += """
+        WHERE major = %s
+        ORDER BY rr.minor DESC;
+        """
+        params += [major_version]
+    else:
+        sql += """
+        ORDER BY rr.major DESC, rr.minor DESC;
+        """
+    # run the query, loading a list of dict that contain all of the release
+    # notes that are filtered out by the query
+    release_notes = exec_to_dict(sql, params)
+    # determine which set of data to pass to the template:
+    # if both major/minor versions are present, we will load the release notes
+    # if only major version is present, then we load all the releases for that major version
+    # if neither are present, we load the list of all major versions
+    if major_version is not None and minor_version is not None:
+        try:
+            release_note = release_notes[0]
+        except IndexError:
+            raise Http404()
+        context = {
+            'major_version': major_version,
+            'minor_version': minor_version,
+            'release_note': release_note,
+        }
+    elif major_version is not None:
+        if not release_notes:
+            raise Http404()
+        context = {
+            'major_version': major_version,
+            'release_notes': release_notes,
+        }
+    else:
+        context = { 'release_notes': release_notes }
+    return render_pgweb(request, 'docs', 'docs/release_notes.html', context)
 
 @login_required
 def commentform(request, itemid, version, filename):
diff --git a/pgweb/urls.py b/pgweb/urls.py
index d8c664f2..6ded70b6 100644
--- a/pgweb/urls.py
+++ b/pgweb/urls.py
@@ -58,6 +58,8 @@ urlpatterns = [
     url(r'^docs/$', pgweb.docs.views.root),
     url(r'^docs/manuals/$', pgweb.docs.views.manuals),
     url(r'^docs/manuals/archive/$', pgweb.docs.views.manualarchive),
+    url(r'^docs/release/$', pgweb.docs.views.release_notes),
+    url(r'^docs/release/((?P<major_version>(\d\.\d)|\d+)(\.(?P<minor_version>\d+))?)/$', pgweb.docs.views.release_notes),
     # Legacy URLs for accessing the docs page; provides a permanent redirect
     url(r'^docs/(current|devel|\d+(?:\.\d)?)/(static|interactive)/((.*).html?)?$', pgweb.docs.views.docspermanentredirect),
     url(r'^docs/(current|devel|\d+(?:\.\d)?)/(.*).html?$', pgweb.docs.views.docpage),
diff --git a/pgweb/util/contexts.py b/pgweb/util/contexts.py
index 25c4787e..c38f2480 100644
--- a/pgweb/util/contexts.py
+++ b/pgweb/util/contexts.py
@@ -34,6 +34,7 @@ sitenav = {
             {'title': 'Japanese', 'link': 'http://www.postgresql.jp/document/'},
             {'title': 'Russian', 'link': 'https://postgrespro.ru/docs/postgresql'},
         ]},
+        {'title': 'Release Notes', 'link': '/docs/release/'},
         {'title': 'Books', 'link': '/docs/books/'},
         {'title': 'Online Resources', 'link': '/docs/online-resources/'},
         {'title': 'Wiki', 'link': 'https://wiki.postgresql.org'},
diff --git a/pgweb/util/db.py b/pgweb/util/db.py
new file mode 100644
index 00000000..a1efae0a
--- /dev/null
+++ b/pgweb/util/db.py
@@ -0,0 +1,7 @@
+from django.db import connection
+
+def exec_to_dict(query, params=None):
+    curs = connection.cursor()
+    curs.execute(query, params)
+    columns = [col[0] for col in curs.description]
+    return [dict(list(zip(columns, row))) for row in curs.fetchall()]
diff --git a/templates/docs/release_notes.html b/templates/docs/release_notes.html
new file mode 100644
index 00000000..d40565ad
--- /dev/null
+++ b/templates/docs/release_notes.html
@@ -0,0 +1,72 @@
+{% extends "base/page.html" %}
+
+{% block extrahead %}
+{% if major_version is not None and minor_version is not None %}
+  <base href="/docs/{{ major_version }}/" />
+{% endif %}
+{% endblock extrahead %}
+
+{%block title%}Release Notes{%endblock%}
+
+{% block contents %}
+{% regroup release_notes by major as release_note_groups %}
+
+<div id="release-notes" class="row">
+  {% if major_version is not None and minor_version is not None %}
+    <div class="col-md-10">
+      <section>
+        <h1>Release Notes <i class="far fa-file-alt"></i></h1>
+        <h2>
+          {% if major_version == '0' %}Postgres95{% else %}PostgreSQL{% endif %}
+          {{ major_version }}.{% if major_version == '0' or major_version == '1' %}{{ release_note.minor|make_list|slice:"2:4"|join:"" }}{% else %}{{ release_note.minor }}{% endif %}
+        </h2>
+      </section>
+      <div id="docContent">
+        {{ release_note.content|safe }}
+      </div>
+      <p>
+        <a href="/docs/release/{{ major_version }}/">
+          Return to the {% if major_version == '0' %}Postgres95{% else %}PostgreSQL {{ major_version }}{% endif %}
+          Release Notes
+        </a>
+      </p>
+    </div>
+  {% elif major_version is not None %}
+    <div class="col-md-10">
+      <section>
+        <h1>Release Notes <i class="far fa-file-alt"></i></h1>
+         <h2>{% if major_version == '0' %}Postgres95{% else %}PostgreSQL {{ major_version }}{% endif %}</h2>
+      </section>
+      <ul>
+        {% for release_note in release_notes %}
+          <li>
+            <a href="/docs/release/{{ major_version }}.{% if major_version == '0' or major_version == '1' %}{{ release_note.minor|make_list|slice:"2:4"|join:"" }}{% else %}{{ release_note.minor }}{% endif %}/">
+                {{ major_version }}.{% if major_version == '0' or major_version == '1' %}{{ release_note.minor|make_list|slice:"2:4"|join:"" }}{% else %}{{ release_note.minor }}{% endif %}
+            </a>
+          </li>
+        {% endfor %}
+      </ul>
+      <p>
+        <a href="/docs/release/">Return to Release Notes</a>
+      </p>
+    </div>
+  {% else %}
+    <div class="col-md-9">
+      <section>
+        <h1>Release Notes <i class="far fa-file-alt"></i></h1>
+      </section>
+      <p>Below is the complete archive of release notes for every version of PostgreSQL.</p>
+      <ul>
+        {% for release_note_group in release_note_groups %}
+          <li>
+            <a href="/docs/release/{{ release_note_group.grouper }}/">
+              {% if release_note_group.grouper == 0 %}Postgres95{% else %}PostgreSQL {{ release_note_group.grouper }}{% endif %}
+            </a>
+          </li>
+        {% endfor %}
+      </ul>
+    </div>
+  {% endif %}
+</div>
+
+{% endblock %}
-- 
2.14.3 (Apple Git-98)



  [text/plain] 0004-Ensure-release-notes-from-older-version-still-load-w.patch (3.6K, ../bc9038eb-e61d-4cd8-4e01-0b3676d49d68@postgresql.org/3-0004-Ensure-release-notes-from-older-version-still-load-w.patch)
  download | inline diff:
From 40036e6d8cfeda577a9c1f65bfbe2c38917afef8 Mon Sep 17 00:00:00 2001
From: "Jonathan S. Katz" <jonathan.katz@excoventures.com>
Date: Wed, 13 Feb 2019 15:22:49 -0500
Subject: [PATCH 4/4] Ensure release notes from older version still load with
 404 errors.

An upcoming change in PostgreSQL keeps only release notes in their
current versions. So e.g., PostgreSQL 11 only has the release notes
for 11.0, 11.1, 11.2 etc.

Thus, for PostgreSQL 9.4 on up, any URLs such as /docs/10/release-9-6-8.html
would return a 404. Additonal, URLs with /current/ and /devel/ would break
as well.

This patch prevents these 404s from occuring by redirecting users accessing
release notes in the 9.4 and above documentation to the older versions
of the release notes by redirecting them to the notes in the specific
version. So in the above example, a user would be redirect to
/docs/9.6/release-9-6-8.html

As we do not have documentation on the website past 7.2, any release
notes from an older version are redirected to the release notes tree
in 7.2
---
 pgweb/docs/views.py | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/pgweb/docs/views.py b/pgweb/docs/views.py
index 815f3a37..2304afbc 100644
--- a/pgweb/docs/views.py
+++ b/pgweb/docs/views.py
@@ -5,8 +5,9 @@ from pgweb.util.decorators import login_required, allow_frames, content_sources
 from django.db.models import Q
 from django.conf import settings
 
-from decimal import Decimal
+from decimal import Decimal, ROUND_DOWN
 import os
+import re
 
 from pgweb.util.contexts import render_pgweb
 from pgweb.util.helpers import template_to_string
@@ -54,6 +55,34 @@ def docpage(request, version, filename):
         return HttpResponsePermanentRedirect("/docs/{0}/{1}.html".format(int(ver), filename))
 
     fullname = "%s.%s" % (filename, extension)
+
+    # Before looking up the documentation, we need to make a check for release
+    # notes. Based on a change, from PostgreSQL 9.4 and up, release notes are
+    # only available for the current version (e.g. 11 only has 11.0, 11.1, 11.2)
+    # This checks to see if there is a mismatch (e.g. ver = 9.4, fullname = release-9-3-2.html)
+    # and perform a redirect to the older version
+    if fullname.startswith('release-') and ver >= Decimal("9.4"):
+        # figure out which version to redirect to. Note that the oldest version
+        # of the docs loaded is 7.2
+        release_version = re.sub(r'release-((\d+)(-\d+)?)(-\d+)?.html',
+            r'\1', fullname).replace('-', '.')
+        # convert to Decimal for ease of manipulation
+        release_version = Decimal(release_version)
+        # if the version is greater than 10, truncate the number
+        if release_version >= Decimal('10'):
+            release_version = release_version.quantize(Decimal('1'), rounding=ROUND_DOWN)
+        # only proceed if the release version of the documents does not match
+        # the calculated release version
+        if release_version != ver:
+            url = "/docs/"
+            if release_version >= Decimal('10'):
+                url += "{}/{}".format(int(release_version), fullname)
+            elif release_version < Decimal('7.2'):
+                url += "7.2/{}".format(fullname)
+            else:
+                url += "{}/{}".format(release_version, fullname)
+            return HttpResponsePermanentRedirect(url)
+
     page = get_object_or_404(DocPage, version=ver, file=fullname)
     versions = DocPage.objects.extra(
         where=["file=%s OR file IN (SELECT file2 FROM docsalias WHERE file1=%s) OR file IN (SELECT file1 FROM docsalias WHERE file2=%s)"],
-- 
2.14.3 (Apple Git-98)



  [application/pgp-signature] signature.asc (832B, ../bc9038eb-e61d-4cd8-4e01-0b3676d49d68@postgresql.org/4-signature.asc)
  download

view thread (25+ messages)  latest in thread

Message-ID: <bc9038eb-e61d-4cd8-4e01-0b3676d49d68@postgresql.org>
Permalink:  ../bc9038eb-e61d-4cd8-4e01-0b3676d49d68@postgresql.org/
Also on:    postgresql.org/message-id/bc9038eb-e61d-4cd8-4e01-0b3676d49d68@postgresql.org

 ·  · 

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pgsql-www@postgresql.org
  Cc: jkatz@postgresql.org, magnus@hagander.net, pgsql-www@lists.postgresql.org
  Subject: Re: Release Notes Archive Patch
  In-Reply-To: <bc9038eb-e61d-4cd8-4e01-0b3676d49d68@postgresql.org>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox