width: 30%;
}
+/** Release Notes */
+#release-notes .navheader,
+#release-notes .navfooter,
+#release-notes .NAVHEADER,
+#release-notes .NAVFOOTER,
+#release-notes .titlepage,
+#release-notes h1.SECT1,
+#release-notes .toc {
+ display: none;
+}
+
+#release-notes .version-list h2:after {
+ content: none;
+}
+
+.release-notes-list {
+ list-style-type: none;
+}
+
+.release-notes-list :not(.collapsed) > .right,
+.release-notes-list .collapsed > .down {
+ display: none;
+}
+
+.release-notes-list .collapsed > .right,
+.release-notes-list :not(.collapsed) > .down {
+ display: block;
+}
+
/** ALL RESPONSIVE QUERIES HERE */
/* Small devices (landscape phones, 576px and up)*/
@register.filter(name='json')
def tojson(value):
return json.dumps(value)
+
+@register.filter()
+def release_notes_pg_minor_version(minor_version, major_version):
+ """Formats the minor version number to the appropriate PostgreSQL version.
+ This is particularly for very old version of PostgreSQL.
+ """
+ if str(major_version) in ['0', '1']:
+ return str(minor_version)[2:4]
+ return minor_version
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
'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. We will limit our lookup to release notes from 9.3 on up,
+ # given 9.3 has all the release notes for PostgreSQL 9.3 and older
+ # 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 - current
+ # It is then put into a unique set
+ # Lastly, we determine the next/previous versions (lead/lag) so we are able
+ # to easily page between the different versions in the unique release note view
+ # We only include the content if we are doing an actual lookup on an exact
+ # major/minor release pair, to limit how much data we load into memory
+ sql = """
+ SELECT
+ {content}
+ file, major, minor,
+ lag(minor) OVER (PARTITION BY major ORDER BY minor) AS previous,
+ lead(minor) OVER (PARTITION BY major ORDER BY minor) AS next
+ FROM (
+ SELECT DISTINCT ON (file, major, minor)
+ {content}
+ 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
+ FROM (
+ SELECT
+ {content}
+ file,
+ string_to_array(regexp_replace(file, 'release-(.*)\.htm.*', '\\1'), '-') AS v
+ FROM docs
+ WHERE file ~ '^release-\d+' AND version >= 9.3
+ ) r
+ ) rr
+ """
+ params = []
+ # if the major + minor version are provided, then we want to narrow down
+ # the results to all the release notes for the minor version, as we need the
+ # list of the entire set in order to generate the nice side bar in the release
+ # notes
+ # otherwise ensure the release notes are returned in order
+ if major_version is not None and minor_version is not None:
+ # at this point, include the content
+ sql = sql.format(content="content,")
+ # restrict to the major version, order from latest to earliest minor
+ sql = """{}
+ WHERE rr.major = %s
+ ORDER BY rr.minor DESC""".format(sql)
+ params += [major_version]
+ else:
+ sql = sql.format(content="")
+ 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 neither are present, we load the list of all of the release notes to list out
+ if major_version is not None and minor_version is not None:
+ # first, see if any release notes were returned; if not, raise a 404
+ if not release_notes:
+ raise Http404()
+ # next, see if we can find the specific release notes we are looking for
+ # format what the "minor" version should look like
+ try:
+ minor = Decimal('0.{}'.format(minor_version) if major_version in ['0', '1'] else minor_version)
+ except TypeError:
+ raise Http404()
+ release_note = [r for r in release_notes if r['minor'] == minor][0]
+ # of course, if nothing is found, return a 404
+ if not release_note:
+ raise Http404()
+ context = {
+ 'major_version': major_version,
+ 'minor_version': minor_version,
+ 'release_note': release_note,
+ '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):
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),
{'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'},
--- /dev/null
+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()]
--- /dev/null
+{% extends "base/page.html" %}
+{% load pgfilters %}
+
+{% 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 }}.{{ release_note.minor|release_notes_pg_minor_version:major_version }}
+ </h2>
+ </section>
+ <div id="docContent">
+ {{ release_note.content|safe }}
+ </div>
+ <div class="row">
+ <div class="col-md-3">
+ {% if release_note.previous is not None %}
+ <a href="/docs/release/{{ major_version }}.{{ release_note.previous|release_notes_pg_minor_version:major_version }}/">
+ Previous
+ </a>
+ {% endif %}
+ </div>
+ <div class="col-md-6 text-center">
+ <p>
+ <a href="/docs/release/">
+ Return to the Release Notes Archive
+ </a>
+ </p>
+ </div>
+ <div class="col-md-3 text-right">
+ {% if release_note.next is not None %}
+ <a href="/docs/release/{{ major_version }}.{{ release_note.next|release_notes_pg_minor_version:major_version }}/">
+ Next
+ </a>
+ {% endif %}
+ </div>
+ </div>
+ </div>
+ <div class="col-md-2 version-list">
+ <section>
+ <h2>Versions</h2>
+ </section>
+ <ul>
+ {% for r in release_notes %}
+ <li>
+ {% if r.minor == release_note.minor %}
+ <strong>
+ {{ major_version }}.{{ r.minor|release_notes_pg_minor_version:major_version }}
+ </strong>
+ {% else %}
+ <a href="/docs/release/{{ major_version }}.{{ r.minor|release_notes_pg_minor_version:major_version }}/">
+ {{ major_version }}.{{ r.minor|release_notes_pg_minor_version:major_version }}
+ </a>
+ {% endif %}
+ </li>
+ {% endfor %}
+ </ul>
+ </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 class="release-notes-list fa-ul">
+ {% for release_note_group in release_note_groups %}
+ {% with major_version=release_note_group.grouper %}
+ <li>
+ <a class="collapsed" href="#release{{ major_version }}" data-toggle="collapse" role="button" aria-expanded="false" aria-controls="release{{ major_version }}">
+ <span class="fa-li right"><i class="fas fa-angle-right"></i></span>
+ <span class="fa-li down"><i class="fas fa-angle-down"></i></span>
+ {% if major_version == 0 %}Postgres95{% else %}PostgreSQL {{ major_version }}{% endif %}
+ </a>
+ <ul class="collapse release-notes-list" id="release{{ major_version }}">
+ {% for release_note in release_note_group.list %}
+ <li>
+ <a href="/docs/release/{{ major_version }}.{{ release_note.minor|release_notes_pg_minor_version:major_version }}/">
+ {{ major_version }}.{{ release_note.minor|release_notes_pg_minor_version:major_version }}
+ </a>
+ </li>
+ {% endfor %}
+ </ul>
+ </li>
+ {% endwith %}
+ {% endfor %}
+ </ul>
+ </div>
+ {% endif %}
+</div>
+
+{% endblock %}