Thread: Getting our tables to render better in PDF output
The crummy formatting of our tables of functions and operators has been an issue for a long time. To my mind, there are several things that need to be addressed: * The layout is completely unfriendly to function descriptions that run to more than a few words. * It's not very practical to have more than one example per function (or at least, we seldom do so). * The results look completely awful in PDF format, because of the narrow effectively-available space, plus the fact that the toolchain will prefer to overprint following columns instead of breaking text where there's no whitespace. In [1], Alvaro suggested that we might be able to improve matters by taking advantage of DocBook's features for column and row spanning. I did some concrete experimentation in that line, and attached are two alternative patches that show a couple of things we might do. Both patches change tables 9.31 (Date/Time Functions) and 9.33 (Enum Support Functions), which I chose somewhat at random, but of course there would be a lot more to be done if we choose to go this way. The first patch uses only one row for each function example, while the second patch uses two rows (i.e., example and result in separate table rows). Otherwise they're the same. I initially did the enum-support table, and what I tried there included getting rid of the separate table column for function result type by writing the functions in the form "func(argtypes) returns resulttype". (Note that this table failed to specify the result types at all before, which doesn't seem great.) The layout idea is function name, args, result description example example result where we can repeat the "example / example result" row if we want more examples per function. Alternatively, in the second patch, it's function name, args, result description example example result To my eyes, the first alternative is preferable in HTML, unless maybe you want to read the manual in a *very* narrow browser window. But some of the examples/results still overrun the available space when looking at it in PDF A4 format. The second patch fixes that problem, but seems not very pretty in a normal-width browser window. When I tried to apply the same idea to the date/time functions table, it didn't really work well at all, mainly because of a few beasts like make_interval() --- that caused the left column to be so wide that the right-hand columns were horrid. (At least with the toolchain version I'm using, it seems like the colwidth specifications are respected rigidly in PDF output but just plain ignored in HTML output. What seems to happen in HTML is that earlier columns get their preferred width and later ones get squeezed.) So the layout idea that the patches show for that table is function name arg types result type description example example result or function name arg types result type description example example result (Even with that, I had to savage make_interval's arg-types list a bit to keep that column from eating too much space...) I'm not especially wedded to any of these ideas, but I hope to provoke some discussion about what we might do in this area. DocBook tables aren't the greatest layout tool in the world, but they do have abilities we're not exploiting. Even with these changes, the amount of space available for examples and results in PDF format is pretty tiny. With examples and results in the same row, it seems that you can only have a couple of dozen consecutive non-whitespace characters without running into overwrite issues, whereas in HTML format the trouble threshold is a good deal higher. I wonder if we could improve matters by switching to some narrower font for <literal> text in PDF? regards, tom lane [1] https://www.postgresql.org/message-id/20200116184444.GA25792%40alvherre.pgsql diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index ceda48e..385fdc0 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -6798,471 +6798,618 @@ SELECT regexp_match('abc01234xyz', '(?:(.*?)(\d+)(.*)){1,1}'); <table id="functions-datetime-table"> <title>Date/Time Functions</title> - <tgroup cols="5"> + <tgroup cols="3"> + <colspec colnum="1" colname="col1" colwidth="1*"/> + <colspec colnum="2" colname="col2" colwidth="1*"/> + <colspec colnum="3" colname="col3" colwidth="1*"/> + <spanspec spanname="func" namest="col1" nameend="col1" align="left"/> + <spanspec spanname="args" namest="col2" nameend="col2" align="left"/> + <spanspec spanname="result" namest="col3" nameend="col3" align="left"/> + <spanspec spanname="desc" namest="col2" nameend="col3" align="left"/> + <spanspec spanname="example" namest="col2" nameend="col2" align="left"/> + <spanspec spanname="exresult" namest="col3" nameend="col3" align="left"/> <thead> <row> - <entry>Function</entry> - <entry>Return Type</entry> - <entry>Description</entry> - <entry>Example</entry> - <entry>Result</entry> + <entry spanname="func" align="center" morerows="2">Function</entry> + <entry spanname="args" align="center">Argument Types</entry> + <entry spanname="result" align="center">Result Type</entry> + </row> + <row> + <entry spanname="desc" align="center">Description</entry> + </row> + <row> + <entry spanname="example" align="center">Example</entry> + <entry spanname="exresult" align="center">Example Result</entry> </row> </thead> <tbody> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>age</primary> </indexterm> - <literal><function>age(<type>timestamp</type>, <type>timestamp</type>)</function></literal> + <function>age</function> </entry> - <entry><type>interval</type></entry> - <entry>Subtract arguments, producing a <quote>symbolic</quote> result that + <entry spanname="args"><type>timestamp</type>, <type>timestamp</type></entry> + <entry spanname="result"><type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Subtract arguments, producing a <quote>symbolic</quote> result that uses years and months, rather than just days</entry> - <entry><literal>age(timestamp '2001-04-10', timestamp '1957-06-13')</literal></entry> - <entry><literal>43 years 9 mons 27 days</literal></entry> + </row> + <row> + <entry spanname="example"><literal>age(timestamp '2001-04-10', timestamp '1957-06-13')</literal></entry> + <entry spanname="exresult"><literal>43 years 9 mons 27 days</literal></entry> </row> <row> - <entry><literal><function>age(<type>timestamp</type>)</function></literal></entry> - <entry><type>interval</type></entry> - <entry>Subtract from <function>current_date</function> (at midnight)</entry> - <entry><literal>age(timestamp '1957-06-13')</literal></entry> - <entry><literal>43 years 8 mons 3 days</literal></entry> + <entry spanname="func" morerows="2"><function>age</function></entry> + <entry spanname="args"><type>timestamp</type></entry> + <entry spanname="result"><type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Subtract from <function>current_date</function> (at midnight)</entry> + </row> + <row> + <entry spanname="example"><literal>age(timestamp '1957-06-13')</literal></entry> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>clock_timestamp</primary> </indexterm> - <literal><function>clock_timestamp()</function></literal> + <function>clock_timestamp</function> </entry> - <entry><type>timestamp with time zone</type></entry> - <entry>Current date and time (changes during statement execution); + <entry spanname="args">none</entry> + <entry spanname="result"><type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Current date and time (changes during statement execution); see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>clock_timestamp()</literal></entry> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>current_date</primary> </indexterm> - <literal><function>current_date</function></literal> + <function>current_date</function> </entry> - <entry><type>date</type></entry> - <entry>Current date; + <entry spanname="args">none (written without parentheses)</entry> + <entry spanname="result"><type>date</type></entry> + </row> + <row> + <entry spanname="desc">Current date; see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>current_date</literal></entry> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>current_time</primary> </indexterm> - <literal><function>current_time</function></literal> + <function>current_time</function> </entry> - <entry><type>time with time zone</type></entry> - <entry>Current time of day; + <entry spanname="args">none (written without parentheses)</entry> + <entry spanname="result"><type>time with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Current time of day; see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>current_time</literal></entry> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>current_timestamp</primary> </indexterm> - <literal><function>current_timestamp</function></literal> + <function>current_timestamp</function> </entry> - <entry><type>timestamp with time zone</type></entry> - <entry>Current date and time (start of current transaction); + <entry spanname="args">none (written without parentheses)</entry> + <entry spanname="result"><type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Current date and time (start of current transaction); see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>current_timestamp</literal></entry> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>date_part</primary> </indexterm> - <literal><function>date_part(<type>text</type>, <type>timestamp</type>)</function></literal> + <function>date_part</function> </entry> - <entry><type>double precision</type></entry> - <entry>Get subfield (equivalent to <function>extract</function>); + <entry spanname="args"><type>text</type>, <type>timestamp</type></entry> + <entry spanname="result"><type>double precision</type></entry> + </row> + <row> + <entry spanname="desc">Get subfield (equivalent to <function>extract</function>); see <xref linkend="functions-datetime-extract"/> </entry> - <entry><literal>date_part('hour', timestamp '2001-02-16 20:38:40')</literal></entry> - <entry><literal>20</literal></entry> + </row> + <row> + <entry spanname="example"><literal>date_part('hour', timestamp '2001-02-16 20:38:40')</literal></entry> + <entry spanname="exresult"><literal>20</literal></entry> </row> <row> - <entry><literal><function>date_part(<type>text</type>, <type>interval</type>)</function></literal></entry> - <entry><type>double precision</type></entry> - <entry>Get subfield (equivalent to + <entry spanname="func" morerows="2"><function>date_part</function></entry> + <entry spanname="args"><type>text</type>, <type>interval</type></entry> + <entry spanname="result"><type>double precision</type></entry> + </row> + <row> + <entry spanname="desc">Get subfield (equivalent to <function>extract</function>); see <xref linkend="functions-datetime-extract"/> </entry> - <entry><literal>date_part('month', interval '2 years 3 months')</literal></entry> - <entry><literal>3</literal></entry> + </row> + <row> + <entry spanname="example"><literal>date_part('month', interval '2 years 3 months')</literal></entry> + <entry spanname="exresult"><literal>3</literal></entry> </row> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>date_trunc</primary> </indexterm> - <literal><function>date_trunc(<type>text</type>, <type>timestamp</type>)</function></literal> + <function>date_trunc</function> </entry> - <entry><type>timestamp</type></entry> - <entry>Truncate to specified precision; see <xref linkend="functions-datetime-trunc"/> + <entry spanname="args"><type>text</type>, <type>timestamp</type></entry> + <entry spanname="result"><type>timestamp</type></entry> + </row> + <row> + <entry spanname="desc">Truncate to specified precision; see <xref linkend="functions-datetime-trunc"/> </entry> - <entry><literal>date_trunc('hour', timestamp '2001-02-16 20:38:40')</literal></entry> - <entry><literal>2001-02-16 20:00:00</literal></entry> + </row> + <row> + <entry spanname="example"><literal>date_trunc('hour', timestamp '2001-02-16 20:38:40')</literal></entry> + <entry spanname="exresult"><literal>2001-02-16 20:00:00</literal></entry> </row> <row> - <entry><literal><function>date_trunc(<type>text</type>, <type>timestamp with time zone</type>, <type>text</type>)</function></literal></entry> - <entry><type>timestamp with time zone</type></entry> - <entry>Truncate to specified precision in the specified time zone; see <xref linkend="functions-datetime-trunc"/> + <entry spanname="func" morerows="2"><function>date_trunc</function></entry> + <entry spanname="args"><type>text</type>, <type>timestamp with time zone</type>, <type>text</type></entry> + <entry spanname="result"><type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Truncate to specified precision in the specified time zone; see <xref linkend="functions-datetime-trunc"/> </entry> - <entry><literal>date_trunc('day', timestamptz '2001-02-16 20:38:40+00', 'Australia/Sydney')</literal></entry> - <entry><literal>2001-02-16 13:00:00+00</literal></entry> + </row> + <row> + <entry spanname="example"><literal>date_trunc('day', timestamptz '2001-02-16 20:38:40+00', 'Australia/Sydney')</literal></entry> + <entry spanname="exresult"><literal>2001-02-16 13:00:00+00</literal></entry> </row> <row> - <entry><literal><function>date_trunc(<type>text</type>, <type>interval</type>)</function></literal></entry> - <entry><type>interval</type></entry> - <entry>Truncate to specified precision; see <xref linkend="functions-datetime-trunc"/> + <entry spanname="func" morerows="2"><function>date_trunc</function></entry> + <entry spanname="args"><type>text</type>, <type>interval</type></entry> + <entry spanname="result"><type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Truncate to specified precision; see <xref linkend="functions-datetime-trunc"/> </entry> - <entry><literal>date_trunc('hour', interval '2 days 3 hours 40 minutes')</literal></entry> - <entry><literal>2 days 03:00:00</literal></entry> + </row> + <row> + <entry spanname="example"><literal>date_trunc('hour', interval '2 days 3 hours 40 minutes')</literal></entry> + <entry spanname="exresult"><literal>2 days 03:00:00</literal></entry> </row> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>extract</primary> </indexterm> - <literal><function>extract</function>(<parameter>field</parameter> from - <type>timestamp</type>)</literal> + <function>extract</function> </entry> - <entry><type>double precision</type></entry> - <entry>Get subfield; see <xref linkend="functions-datetime-extract"/> + <entry spanname="args"><parameter>field</parameter> <literal>from</literal> <type>timestamp</type></entry> + <entry spanname="result"><type>double precision</type></entry> + </row> + <row> + <entry spanname="desc">Get subfield; see <xref linkend="functions-datetime-extract"/> </entry> - <entry><literal>extract(hour from timestamp '2001-02-16 20:38:40')</literal></entry> - <entry><literal>20</literal></entry> + </row> + <row> + <entry spanname="example"><literal>extract(hour from timestamp '2001-02-16 20:38:40')</literal></entry> + <entry spanname="exresult"><literal>20</literal></entry> </row> <row> - <entry><literal><function>extract</function>(<parameter>field</parameter> from - <type>interval</type>)</literal></entry> - <entry><type>double precision</type></entry> - <entry>Get subfield; see <xref linkend="functions-datetime-extract"/> + <entry spanname="func" morerows="2"><function>extract</function></entry> + <entry spanname="args"><parameter>field</parameter> <literal>from</literal> <type>interval</type></entry> + <entry spanname="result"><type>double precision</type></entry> + </row> + <row> + <entry spanname="desc">Get subfield; see <xref linkend="functions-datetime-extract"/> </entry> - <entry><literal>extract(month from interval '2 years 3 months')</literal></entry> - <entry><literal>3</literal></entry> + </row> + <row> + <entry spanname="example"><literal>extract(month from interval '2 years 3 months')</literal></entry> + <entry spanname="exresult"><literal>3</literal></entry> </row> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>isfinite</primary> </indexterm> - <literal><function>isfinite(<type>date</type>)</function></literal> + <function>isfinite</function> </entry> - <entry><type>boolean</type></entry> - <entry>Test for finite date (not +/-infinity)</entry> - <entry><literal>isfinite(date '2001-02-16')</literal></entry> - <entry><literal>true</literal></entry> + <entry spanname="args"><type>date</type></entry> + <entry spanname="result"><type>boolean</type></entry> + </row> + <row> + <entry spanname="desc">Test for finite date (not +/-infinity)</entry> + </row> + <row> + <entry spanname="example"><literal>isfinite(date '2001-02-16')</literal></entry> + <entry spanname="exresult"><literal>true</literal></entry> </row> <row> - <entry><literal><function>isfinite(<type>timestamp</type>)</function></literal></entry> - <entry><type>boolean</type></entry> - <entry>Test for finite time stamp (not +/-infinity)</entry> - <entry><literal>isfinite(timestamp '2001-02-16 21:28:30')</literal></entry> - <entry><literal>true</literal></entry> + <entry spanname="func" morerows="2"><function>isfinite</function></entry> + <entry spanname="args"><type>timestamp</type></entry> + <entry spanname="result"><type>boolean</type></entry> + </row> + <row> + <entry spanname="desc">Test for finite time stamp (not +/-infinity)</entry> + </row> + <row> + <entry spanname="example"><literal>isfinite(timestamp '2001-02-16 21:28:30')</literal></entry> + <entry spanname="exresult"><literal>true</literal></entry> </row> <row> - <entry><literal><function>isfinite(<type>interval</type>)</function></literal></entry> - <entry><type>boolean</type></entry> - <entry>Test for finite interval</entry> - <entry><literal>isfinite(interval '4 hours')</literal></entry> - <entry><literal>true</literal></entry> + <entry spanname="func" morerows="2"><function>isfinite</function></entry> + <entry spanname="args"><type>interval</type></entry> + <entry spanname="result"><type>boolean</type></entry> + </row> + <row> + <entry spanname="desc">Test for finite interval</entry> + </row> + <row> + <entry spanname="example"><literal>isfinite(interval '4 hours')</literal></entry> + <entry spanname="exresult"><literal>true</literal></entry> </row> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>justify_days</primary> </indexterm> - <literal><function>justify_days(<type>interval</type>)</function></literal> + <function>justify_days</function> </entry> - <entry><type>interval</type></entry> - <entry>Adjust interval so 30-day time periods are represented as months</entry> - <entry><literal>justify_days(interval '35 days')</literal></entry> - <entry><literal>1 mon 5 days</literal></entry> + <entry spanname="args"><type>interval</type></entry> + <entry spanname="result"><type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Adjust interval so 30-day time periods are represented as months</entry> + </row> + <row> + <entry spanname="example"><literal>justify_days(interval '35 days')</literal></entry> + <entry spanname="exresult"><literal>1 mon 5 days</literal></entry> </row> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>justify_hours</primary> </indexterm> - <literal><function>justify_hours(<type>interval</type>)</function></literal> + <function>justify_hours</function> </entry> - <entry><type>interval</type></entry> - <entry>Adjust interval so 24-hour time periods are represented as days</entry> - <entry><literal>justify_hours(interval '27 hours')</literal></entry> - <entry><literal>1 day 03:00:00</literal></entry> + <entry spanname="args"><type>interval</type></entry> + <entry spanname="result"><type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Adjust interval so 24-hour time periods are represented as days</entry> + </row> + <row> + <entry spanname="example"><literal>justify_hours(interval '27 hours')</literal></entry> + <entry spanname="exresult"><literal>1 day 03:00:00</literal></entry> </row> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>justify_interval</primary> </indexterm> - <literal><function>justify_interval(<type>interval</type>)</function></literal> + <function>justify_interval</function> </entry> - <entry><type>interval</type></entry> - <entry>Adjust interval using <function>justify_days</function> and <function>justify_hours</function>, with additionalsign adjustments</entry> - <entry><literal>justify_interval(interval '1 mon -1 hour')</literal></entry> - <entry><literal>29 days 23:00:00</literal></entry> + <entry spanname="args"><type>interval</type></entry> + <entry spanname="result"><type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Adjust interval using <function>justify_days</function> and <function>justify_hours</function>,with additional sign adjustments</entry> + </row> + <row> + <entry spanname="example"><literal>justify_interval(interval '1 mon -1 hour')</literal></entry> + <entry spanname="exresult"><literal>29 days 23:00:00</literal></entry> </row> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>localtime</primary> </indexterm> - <literal><function>localtime</function></literal> + <function>localtime</function> </entry> - <entry><type>time</type></entry> - <entry>Current time of day; + <entry spanname="args">none (written without parentheses)</entry> + <entry spanname="result"><type>time</type></entry> + </row> + <row> + <entry spanname="desc">Current time of day; see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>localtime</literal></entry> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>localtimestamp</primary> </indexterm> - <literal><function>localtimestamp</function></literal> + <function>localtimestamp</function> </entry> - <entry><type>timestamp</type></entry> - <entry>Current date and time (start of current transaction); + <entry spanname="args">none (written without parentheses)</entry> + <entry spanname="result"><type>timestamp</type></entry> + </row> + <row> + <entry spanname="desc">Current date and time (start of current transaction); see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>localtimestamp</literal></entry> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>make_date</primary> </indexterm> - <literal> - <function> - make_date(<parameter>year</parameter> <type>int</type>, - <parameter>month</parameter> <type>int</type>, - <parameter>day</parameter> <type>int</type>) - </function> - </literal> + <function>make_date</function> </entry> - <entry><type>date</type></entry> - <entry> + <entry spanname="args"><parameter>year</parameter> <type>int</type>, + <parameter>month</parameter> <type>int</type>, + <parameter>day</parameter> <type>int</type></entry> + <entry spanname="result"><type>date</type></entry> + </row> + <row> + <entry spanname="desc"> Create date from year, month and day fields </entry> - <entry><literal>make_date(2013, 7, 15)</literal></entry> - <entry><literal>2013-07-15</literal></entry> + </row> + <row> + <entry spanname="example"><literal>make_date(2013, 7, 15)</literal></entry> + <entry spanname="exresult"><literal>2013-07-15</literal></entry> </row> <row> - <entry> - <indexterm> + <entry spanname="func" morerows="2"><indexterm> <primary>make_interval</primary> </indexterm> - <literal> - <function> - make_interval(<parameter>years</parameter> <type>int</type> DEFAULT 0, - <parameter>months</parameter> <type>int</type> DEFAULT 0, - <parameter>weeks</parameter> <type>int</type> DEFAULT 0, - <parameter>days</parameter> <type>int</type> DEFAULT 0, - <parameter>hours</parameter> <type>int</type> DEFAULT 0, - <parameter>mins</parameter> <type>int</type> DEFAULT 0, - <parameter>secs</parameter> <type>double precision</type> DEFAULT 0.0) - </function> - </literal> + <function>make_interval</function> </entry> - <entry><type>interval</type></entry> - <entry> + <entry spanname="args"><optional> <type>int</type> + <optional>, <type>int</type> + <optional>, <type>int</type> + <optional>, <type>int</type> + <optional>, <type>int</type> + <optional>, <type>int</type> + <optional>, <type>double precision</type> + </optional></optional></optional></optional></optional></optional></optional></entry> + <entry spanname="result"><type>interval</type></entry> + </row> + <row> + <entry spanname="desc"> Create interval from years, months, weeks, days, hours, minutes and - seconds fields + seconds fields, each of which can default to zero </entry> - <entry><literal>make_interval(days => 10)</literal></entry> - <entry><literal>10 days</literal></entry> + </row> + <row> + <entry spanname="example"><literal>make_interval(days => 10)</literal></entry> + <entry spanname="exresult"><literal>10 days</literal></entry> </row> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>make_time</primary> </indexterm> - <literal> - <function> - make_time(<parameter>hour</parameter> <type>int</type>, - <parameter>min</parameter> <type>int</type>, - <parameter>sec</parameter> <type>double precision</type>) - </function> - </literal> + <function>make_time</function> </entry> - <entry><type>time</type></entry> - <entry> + <entry spanname="args"><parameter>hour</parameter> <type>int</type>, + <parameter>min</parameter> <type>int</type>, + <parameter>sec</parameter> <type>double precision</type></entry> + <entry spanname="result"><type>time</type></entry> + </row> + <row> + <entry spanname="desc"> Create time from hour, minute and seconds fields </entry> - <entry><literal>make_time(8, 15, 23.5)</literal></entry> - <entry><literal>08:15:23.5</literal></entry> + </row> + <row> + <entry spanname="example"><literal>make_time(8, 15, 23.5)</literal></entry> + <entry spanname="exresult"><literal>08:15:23.5</literal></entry> </row> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>make_timestamp</primary> </indexterm> - <literal> - <function> - make_timestamp(<parameter>year</parameter> <type>int</type>, - <parameter>month</parameter> <type>int</type>, - <parameter>day</parameter> <type>int</type>, - <parameter>hour</parameter> <type>int</type>, - <parameter>min</parameter> <type>int</type>, - <parameter>sec</parameter> <type>double precision</type>) - </function> - </literal> + <function>make_timestamp</function> </entry> - <entry><type>timestamp</type></entry> - <entry> + <entry spanname="args"><parameter>year</parameter> <type>int</type>, + <parameter>month</parameter> <type>int</type>, + <parameter>day</parameter> <type>int</type>, + <parameter>hour</parameter> <type>int</type>, + <parameter>min</parameter> <type>int</type>, + <parameter>sec</parameter> <type>double precision</type></entry> + <entry spanname="result"><type>timestamp</type></entry> + </row> + <row> + <entry spanname="desc"> Create timestamp from year, month, day, hour, minute and seconds fields </entry> - <entry><literal>make_timestamp(2013, 7, 15, 8, 15, 23.5)</literal></entry> - <entry><literal>2013-07-15 08:15:23.5</literal></entry> + </row> + <row> + <entry spanname="example"><literal>make_timestamp(2013, 7, 15, 8, 15, 23.5)</literal></entry> + <entry spanname="exresult"><literal>2013-07-15 08:15:23.5</literal></entry> </row> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>make_timestamptz</primary> </indexterm> - <literal> - <function> - make_timestamptz(<parameter>year</parameter> <type>int</type>, - <parameter>month</parameter> <type>int</type>, - <parameter>day</parameter> <type>int</type>, - <parameter>hour</parameter> <type>int</type>, - <parameter>min</parameter> <type>int</type>, - <parameter>sec</parameter> <type>double precision</type>, - <optional> <parameter>timezone</parameter> <type>text</type> </optional>) - </function> - </literal> + <function>make_timestamptz</function> </entry> - <entry><type>timestamp with time zone</type></entry> - <entry> + <entry spanname="args"><parameter>year</parameter> <type>int</type>, + <parameter>month</parameter> <type>int</type>, + <parameter>day</parameter> <type>int</type>, + <parameter>hour</parameter> <type>int</type>, + <parameter>min</parameter> <type>int</type>, + <parameter>sec</parameter> <type>double precision</type>, + <optional> <parameter>timezone</parameter> <type>text</type> </optional></entry> + <entry spanname="result"><type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc"> Create timestamp with time zone from year, month, day, hour, minute and seconds fields; if <parameter>timezone</parameter> is not specified, the current time zone is used </entry> - <entry><literal>make_timestamptz(2013, 7, 15, 8, 15, 23.5)</literal></entry> - <entry><literal>2013-07-15 08:15:23.5+01</literal></entry> + </row> + <row> + <entry spanname="example"><literal>make_timestamptz(2013, 7, 15, 8, 15, 23.5)</literal></entry> + <entry spanname="exresult"><literal>2013-07-15 08:15:23.5+01</literal></entry> </row> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>now</primary> </indexterm> - <literal><function>now()</function></literal> + <function>now</function> </entry> - <entry><type>timestamp with time zone</type></entry> - <entry>Current date and time (start of current transaction); + <entry spanname="args">none</entry> + <entry spanname="result"><type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Current date and time (start of current transaction); see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>now()</literal></entry> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>statement_timestamp</primary> </indexterm> - <literal><function>statement_timestamp()</function></literal> + <function>statement_timestamp</function> </entry> - <entry><type>timestamp with time zone</type></entry> - <entry>Current date and time (start of current statement); + <entry spanname="args">none</entry> + <entry spanname="result"><type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Current date and time (start of current statement); see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>statement_timestamp()</literal></entry> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>timeofday</primary> </indexterm> - <literal><function>timeofday()</function></literal> + <function>timeofday</function> </entry> - <entry><type>text</type></entry> - <entry>Current date and time + <entry spanname="args">none</entry> + <entry spanname="result"><type>text</type></entry> + </row> + <row> + <entry spanname="desc">Current date and time (like <function>clock_timestamp</function>, but as a <type>text</type> string); see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>timeofday()</literal></entry> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>transaction_timestamp</primary> </indexterm> - <literal><function>transaction_timestamp()</function></literal> + <function>transaction_timestamp</function> </entry> - <entry><type>timestamp with time zone</type></entry> - <entry>Current date and time (start of current transaction); + <entry spanname="args">none</entry> + <entry spanname="result"><type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Current date and time (start of current transaction); see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> </row> <row> - <entry> + <entry spanname="example"><literal>transaction_timestamp()</literal></entry> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> + </row> + <row> + <entry spanname="func" morerows="2"> <indexterm> <primary>to_timestamp</primary> </indexterm> - <literal><function>to_timestamp(<type>double precision</type>)</function></literal> + <function>to_timestamp</function> </entry> - <entry><type>timestamp with time zone</type></entry> - <entry>Convert Unix epoch (seconds since 1970-01-01 00:00:00+00) to + <entry spanname="args"><type>double precision</type></entry> + <entry spanname="result"><type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Convert Unix epoch (seconds since 1970-01-01 00:00:00+00) to timestamp</entry> - <entry><literal>to_timestamp(1284352323)</literal></entry> - <entry><literal>2010-09-13 04:32:03+00</literal></entry> + </row> + <row> + <entry spanname="example"><literal>to_timestamp(1284352323)</literal></entry> + <entry spanname="exresult"><literal>2010-09-13 04:32:03+00</literal></entry> </row> </tbody> </tgroup> @@ -8236,52 +8383,67 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple <table id="functions-enum-table"> <title>Enum Support Functions</title> - <tgroup cols="4"> + <tgroup cols="3"> + <colspec colnum="1" colname="col1" colwidth="1*"/> + <colspec colnum="2" colname="col2" colwidth="1*"/> + <colspec colnum="3" colname="col3" colwidth="1*"/> + <spanspec spanname="func" namest="col1" nameend="col1" align="left"/> + <spanspec spanname="desc" namest="col2" nameend="col3" align="left"/> + <spanspec spanname="example" namest="col2" nameend="col2" align="left"/> + <spanspec spanname="exresult" namest="col3" nameend="col3" align="left"/> <thead> <row> - <entry>Function</entry> - <entry>Description</entry> - <entry>Example</entry> - <entry>Example Result</entry> + <entry spanname="func" align="center" morerows="1">Function</entry> + <entry spanname="desc" align="center">Description</entry> + </row> + <row> + <entry spanname="example" align="center">Example</entry> + <entry spanname="exresult" align="center">Result</entry> </row> </thead> <tbody> <row> - <entry> + <entry spanname="func" morerows="1"> <indexterm> <primary>enum_first</primary> </indexterm> - <literal>enum_first(anyenum)</literal> + <literal>enum_first(anyenum) returns anyenum</literal> </entry> - <entry>Returns the first value of the input enum type</entry> - <entry><literal>enum_first(null::rainbow)</literal></entry> - <entry><literal>red</literal></entry> + <entry spanname="desc">Returns the first value of the input enum type</entry> </row> <row> - <entry> + <entry spanname="example"><literal>enum_first(null::rainbow)</literal></entry> + <entry spanname="exresult"><literal>red</literal></entry> + </row> + <row> + <entry spanname="func" morerows="1"> <indexterm> <primary>enum_last</primary> </indexterm> - <literal>enum_last(anyenum)</literal> + <literal>enum_last(anyenum) returns anyenum</literal> </entry> - <entry>Returns the last value of the input enum type</entry> - <entry><literal>enum_last(null::rainbow)</literal></entry> - <entry><literal>purple</literal></entry> + <entry spanname="desc">Returns the last value of the input enum type</entry> </row> <row> - <entry> + <entry spanname="example"><literal>enum_last(null::rainbow)</literal></entry> + <entry spanname="exresult"><literal>purple</literal></entry> + </row> + <row> + <entry spanname="func" morerows="1"> <indexterm> <primary>enum_range</primary> </indexterm> - <literal>enum_range(anyenum)</literal> + <literal>enum_range(anyenum) returns anyarray</literal> </entry> - <entry>Returns all values of the input enum type in an ordered array</entry> - <entry><literal>enum_range(null::rainbow)</literal></entry> - <entry><literal>{red,orange,yellow,green,blue,purple}</literal></entry> + <entry spanname="desc">Returns all values of the input enum type in an ordered array</entry> + </row> + <row> + <entry spanname="example"><literal>enum_range(null::rainbow)</literal></entry> + <entry spanname="exresult"><literal>{red,orange,yellow,green,blue,purple}</literal></entry> </row> <row> - <entry morerows="2"><literal>enum_range(anyenum, anyenum)</literal></entry> - <entry morerows="2"> + <entry spanname="func" morerows="3"><literal>enum_range(anyenum, anyenum) returns anyarray</literal></entry> + <entry spanname="desc"> Returns the range between the two given enum values, as an ordered array. The values must be from the same enum type. If the first parameter is null, the result will start with the first value of @@ -8289,16 +8451,18 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple If the second parameter is null, the result will end with the last value of the enum type. </entry> - <entry><literal>enum_range('orange'::rainbow, 'green'::rainbow)</literal></entry> - <entry><literal>{orange,yellow,green}</literal></entry> </row> <row> - <entry><literal>enum_range(NULL, 'green'::rainbow)</literal></entry> - <entry><literal>{red,orange,yellow,green}</literal></entry> + <entry spanname="example"><literal>enum_range('orange'::rainbow, 'green'::rainbow)</literal></entry> + <entry spanname="exresult"><literal>{orange,yellow,green}</literal></entry> + </row> + <row> + <entry spanname="example"><literal>enum_range(NULL, 'green'::rainbow)</literal></entry> + <entry spanname="exresult"><literal>{red,orange,yellow,green}</literal></entry> </row> <row> - <entry><literal>enum_range('orange'::rainbow, NULL)</literal></entry> - <entry><literal>{orange,yellow,green,blue,purple}</literal></entry> + <entry spanname="example"><literal>enum_range('orange'::rainbow, NULL)</literal></entry> + <entry spanname="exresult"><literal>{orange,yellow,green,blue,purple}</literal></entry> </row> </tbody> </tgroup> diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index ceda48e..7364294 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -6798,471 +6798,682 @@ SELECT regexp_match('abc01234xyz', '(?:(.*?)(\d+)(.*)){1,1}'); <table id="functions-datetime-table"> <title>Date/Time Functions</title> - <tgroup cols="5"> + <tgroup cols="3"> + <colspec colnum="1" colname="col1" colwidth="1*"/> + <colspec colnum="2" colname="col2" colwidth="1*"/> + <colspec colnum="3" colname="col3" colwidth="1*"/> + <spanspec spanname="func" namest="col1" nameend="col1" align="left"/> + <spanspec spanname="args" namest="col2" nameend="col2" align="left"/> + <spanspec spanname="result" namest="col3" nameend="col3" align="left"/> + <spanspec spanname="desc" namest="col2" nameend="col3" align="left"/> + <spanspec spanname="example" namest="col2" nameend="col3" align="left"/> + <spanspec spanname="exresult" namest="col2" nameend="col3" align="left"/> <thead> <row> - <entry>Function</entry> - <entry>Return Type</entry> - <entry>Description</entry> - <entry>Example</entry> - <entry>Result</entry> + <entry spanname="func" align="center" morerows="3">Function</entry> + <entry spanname="args" align="center">Argument Types</entry> + <entry spanname="result" align="center">Result Type</entry> + </row> + <row> + <entry spanname="desc" align="center">Description</entry> + </row> + <row> + <entry spanname="example" align="center">Example</entry> + </row> + <row> + <entry spanname="exresult" align="center">Example Result</entry> </row> </thead> <tbody> <row> - <entry> + <entry spanname="func" morerows="3"> <indexterm> <primary>age</primary> </indexterm> - <literal><function>age(<type>timestamp</type>, <type>timestamp</type>)</function></literal> + <function>age</function> </entry> - <entry><type>interval</type></entry> - <entry>Subtract arguments, producing a <quote>symbolic</quote> result that + <entry spanname="args"><type>timestamp</type>, <type>timestamp</type></entry> + <entry spanname="result"><type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Subtract arguments, producing a <quote>symbolic</quote> result that uses years and months, rather than just days</entry> - <entry><literal>age(timestamp '2001-04-10', timestamp '1957-06-13')</literal></entry> - <entry><literal>43 years 9 mons 27 days</literal></entry> + </row> + <row> + <entry spanname="example"><literal>age(timestamp '2001-04-10', timestamp '1957-06-13')</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>43 years 9 mons 27 days</literal></entry> </row> <row> - <entry><literal><function>age(<type>timestamp</type>)</function></literal></entry> - <entry><type>interval</type></entry> - <entry>Subtract from <function>current_date</function> (at midnight)</entry> - <entry><literal>age(timestamp '1957-06-13')</literal></entry> - <entry><literal>43 years 8 mons 3 days</literal></entry> + <entry spanname="func" morerows="3"><function>age</function></entry> + <entry spanname="args"><type>timestamp</type></entry> + <entry spanname="result"><type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Subtract from <function>current_date</function> (at midnight)</entry> + </row> + <row> + <entry spanname="example"><literal>age(timestamp '1957-06-13')</literal></entry> + </row> + <row> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="func" morerows="3"> <indexterm> <primary>clock_timestamp</primary> </indexterm> - <literal><function>clock_timestamp()</function></literal> + <function>clock_timestamp</function> </entry> - <entry><type>timestamp with time zone</type></entry> - <entry>Current date and time (changes during statement execution); + <entry spanname="args">none</entry> + <entry spanname="result"><type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Current date and time (changes during statement execution); see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>clock_timestamp()</literal></entry> + </row> + <row> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="func" morerows="3"> <indexterm> <primary>current_date</primary> </indexterm> - <literal><function>current_date</function></literal> + <function>current_date</function> </entry> - <entry><type>date</type></entry> - <entry>Current date; + <entry spanname="args">none (written without parentheses)</entry> + <entry spanname="result"><type>date</type></entry> + </row> + <row> + <entry spanname="desc">Current date; see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>current_date</literal></entry> + </row> + <row> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="func" morerows="3"> <indexterm> <primary>current_time</primary> </indexterm> - <literal><function>current_time</function></literal> + <function>current_time</function> </entry> - <entry><type>time with time zone</type></entry> - <entry>Current time of day; + <entry spanname="args">none (written without parentheses)</entry> + <entry spanname="result"><type>time with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Current time of day; see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>current_time</literal></entry> + </row> + <row> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="func" morerows="3"> <indexterm> <primary>current_timestamp</primary> </indexterm> - <literal><function>current_timestamp</function></literal> + <function>current_timestamp</function> </entry> - <entry><type>timestamp with time zone</type></entry> - <entry>Current date and time (start of current transaction); + <entry spanname="args">none (written without parentheses)</entry> + <entry spanname="result"><type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Current date and time (start of current transaction); see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>current_timestamp</literal></entry> + </row> + <row> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="func" morerows="3"> <indexterm> <primary>date_part</primary> </indexterm> - <literal><function>date_part(<type>text</type>, <type>timestamp</type>)</function></literal> + <function>date_part</function> </entry> - <entry><type>double precision</type></entry> - <entry>Get subfield (equivalent to <function>extract</function>); + <entry spanname="args"><type>text</type>, <type>timestamp</type></entry> + <entry spanname="result"><type>double precision</type></entry> + </row> + <row> + <entry spanname="desc">Get subfield (equivalent to <function>extract</function>); see <xref linkend="functions-datetime-extract"/> </entry> - <entry><literal>date_part('hour', timestamp '2001-02-16 20:38:40')</literal></entry> - <entry><literal>20</literal></entry> + </row> + <row> + <entry spanname="example"><literal>date_part('hour', timestamp '2001-02-16 20:38:40')</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>20</literal></entry> </row> <row> - <entry><literal><function>date_part(<type>text</type>, <type>interval</type>)</function></literal></entry> - <entry><type>double precision</type></entry> - <entry>Get subfield (equivalent to + <entry spanname="func" morerows="3"><function>date_part</function></entry> + <entry spanname="args"><type>text</type>, <type>interval</type></entry> + <entry spanname="result"><type>double precision</type></entry> + </row> + <row> + <entry spanname="desc">Get subfield (equivalent to <function>extract</function>); see <xref linkend="functions-datetime-extract"/> </entry> - <entry><literal>date_part('month', interval '2 years 3 months')</literal></entry> - <entry><literal>3</literal></entry> + </row> + <row> + <entry spanname="example"><literal>date_part('month', interval '2 years 3 months')</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>3</literal></entry> </row> <row> - <entry> + <entry spanname="func" morerows="3"> <indexterm> <primary>date_trunc</primary> </indexterm> - <literal><function>date_trunc(<type>text</type>, <type>timestamp</type>)</function></literal> + <function>date_trunc</function> </entry> - <entry><type>timestamp</type></entry> - <entry>Truncate to specified precision; see <xref linkend="functions-datetime-trunc"/> + <entry spanname="args"><type>text</type>, <type>timestamp</type></entry> + <entry spanname="result"><type>timestamp</type></entry> + </row> + <row> + <entry spanname="desc">Truncate to specified precision; see <xref linkend="functions-datetime-trunc"/> </entry> - <entry><literal>date_trunc('hour', timestamp '2001-02-16 20:38:40')</literal></entry> - <entry><literal>2001-02-16 20:00:00</literal></entry> + </row> + <row> + <entry spanname="example"><literal>date_trunc('hour', timestamp '2001-02-16 20:38:40')</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>2001-02-16 20:00:00</literal></entry> </row> <row> - <entry><literal><function>date_trunc(<type>text</type>, <type>timestamp with time zone</type>, <type>text</type>)</function></literal></entry> - <entry><type>timestamp with time zone</type></entry> - <entry>Truncate to specified precision in the specified time zone; see <xref linkend="functions-datetime-trunc"/> + <entry spanname="func" morerows="3"><function>date_trunc</function></entry> + <entry spanname="args"><type>text</type>, <type>timestamp with time zone</type>, <type>text</type></entry> + <entry spanname="result"><type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Truncate to specified precision in the specified time zone; see <xref linkend="functions-datetime-trunc"/> </entry> - <entry><literal>date_trunc('day', timestamptz '2001-02-16 20:38:40+00', 'Australia/Sydney')</literal></entry> - <entry><literal>2001-02-16 13:00:00+00</literal></entry> + </row> + <row> + <entry spanname="example"><literal>date_trunc('day', timestamptz '2001-02-16 20:38:40+00', 'Australia/Sydney')</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>2001-02-16 13:00:00+00</literal></entry> </row> <row> - <entry><literal><function>date_trunc(<type>text</type>, <type>interval</type>)</function></literal></entry> - <entry><type>interval</type></entry> - <entry>Truncate to specified precision; see <xref linkend="functions-datetime-trunc"/> + <entry spanname="func" morerows="3"><function>date_trunc</function></entry> + <entry spanname="args"><type>text</type>, <type>interval</type></entry> + <entry spanname="result"><type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Truncate to specified precision; see <xref linkend="functions-datetime-trunc"/> </entry> - <entry><literal>date_trunc('hour', interval '2 days 3 hours 40 minutes')</literal></entry> - <entry><literal>2 days 03:00:00</literal></entry> + </row> + <row> + <entry spanname="example"><literal>date_trunc('hour', interval '2 days 3 hours 40 minutes')</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>2 days 03:00:00</literal></entry> </row> <row> - <entry> + <entry spanname="func" morerows="3"> <indexterm> <primary>extract</primary> </indexterm> - <literal><function>extract</function>(<parameter>field</parameter> from - <type>timestamp</type>)</literal> + <function>extract</function> </entry> - <entry><type>double precision</type></entry> - <entry>Get subfield; see <xref linkend="functions-datetime-extract"/> + <entry spanname="args"><parameter>field</parameter> <literal>from</literal> <type>timestamp</type></entry> + <entry spanname="result"><type>double precision</type></entry> + </row> + <row> + <entry spanname="desc">Get subfield; see <xref linkend="functions-datetime-extract"/> </entry> - <entry><literal>extract(hour from timestamp '2001-02-16 20:38:40')</literal></entry> - <entry><literal>20</literal></entry> + </row> + <row> + <entry spanname="example"><literal>extract(hour from timestamp '2001-02-16 20:38:40')</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>20</literal></entry> </row> <row> - <entry><literal><function>extract</function>(<parameter>field</parameter> from - <type>interval</type>)</literal></entry> - <entry><type>double precision</type></entry> - <entry>Get subfield; see <xref linkend="functions-datetime-extract"/> + <entry spanname="func" morerows="3"><function>extract</function></entry> + <entry spanname="args"><parameter>field</parameter> <literal>from</literal> <type>interval</type></entry> + <entry spanname="result"><type>double precision</type></entry> + </row> + <row> + <entry spanname="desc">Get subfield; see <xref linkend="functions-datetime-extract"/> </entry> - <entry><literal>extract(month from interval '2 years 3 months')</literal></entry> - <entry><literal>3</literal></entry> + </row> + <row> + <entry spanname="example"><literal>extract(month from interval '2 years 3 months')</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>3</literal></entry> </row> <row> - <entry> + <entry spanname="func" morerows="3"> <indexterm> <primary>isfinite</primary> </indexterm> - <literal><function>isfinite(<type>date</type>)</function></literal> + <function>isfinite</function> </entry> - <entry><type>boolean</type></entry> - <entry>Test for finite date (not +/-infinity)</entry> - <entry><literal>isfinite(date '2001-02-16')</literal></entry> - <entry><literal>true</literal></entry> + <entry spanname="args"><type>date</type></entry> + <entry spanname="result"><type>boolean</type></entry> + </row> + <row> + <entry spanname="desc">Test for finite date (not +/-infinity)</entry> + </row> + <row> + <entry spanname="example"><literal>isfinite(date '2001-02-16')</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>true</literal></entry> </row> <row> - <entry><literal><function>isfinite(<type>timestamp</type>)</function></literal></entry> - <entry><type>boolean</type></entry> - <entry>Test for finite time stamp (not +/-infinity)</entry> - <entry><literal>isfinite(timestamp '2001-02-16 21:28:30')</literal></entry> - <entry><literal>true</literal></entry> + <entry spanname="func" morerows="3"><function>isfinite</function></entry> + <entry spanname="args"><type>timestamp</type></entry> + <entry spanname="result"><type>boolean</type></entry> + </row> + <row> + <entry spanname="desc">Test for finite time stamp (not +/-infinity)</entry> + </row> + <row> + <entry spanname="example"><literal>isfinite(timestamp '2001-02-16 21:28:30')</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>true</literal></entry> </row> <row> - <entry><literal><function>isfinite(<type>interval</type>)</function></literal></entry> - <entry><type>boolean</type></entry> - <entry>Test for finite interval</entry> - <entry><literal>isfinite(interval '4 hours')</literal></entry> - <entry><literal>true</literal></entry> + <entry spanname="func" morerows="3"><function>isfinite</function></entry> + <entry spanname="args"><type>interval</type></entry> + <entry spanname="result"><type>boolean</type></entry> + </row> + <row> + <entry spanname="desc">Test for finite interval</entry> + </row> + <row> + <entry spanname="example"><literal>isfinite(interval '4 hours')</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>true</literal></entry> </row> <row> - <entry> + <entry spanname="func" morerows="3"> <indexterm> <primary>justify_days</primary> </indexterm> - <literal><function>justify_days(<type>interval</type>)</function></literal> + <function>justify_days</function> </entry> - <entry><type>interval</type></entry> - <entry>Adjust interval so 30-day time periods are represented as months</entry> - <entry><literal>justify_days(interval '35 days')</literal></entry> - <entry><literal>1 mon 5 days</literal></entry> + <entry spanname="args"><type>interval</type></entry> + <entry spanname="result"><type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Adjust interval so 30-day time periods are represented as months</entry> + </row> + <row> + <entry spanname="example"><literal>justify_days(interval '35 days')</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>1 mon 5 days</literal></entry> </row> <row> - <entry> + <entry spanname="func" morerows="3"> <indexterm> <primary>justify_hours</primary> </indexterm> - <literal><function>justify_hours(<type>interval</type>)</function></literal> + <function>justify_hours</function> </entry> - <entry><type>interval</type></entry> - <entry>Adjust interval so 24-hour time periods are represented as days</entry> - <entry><literal>justify_hours(interval '27 hours')</literal></entry> - <entry><literal>1 day 03:00:00</literal></entry> + <entry spanname="args"><type>interval</type></entry> + <entry spanname="result"><type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Adjust interval so 24-hour time periods are represented as days</entry> + </row> + <row> + <entry spanname="example"><literal>justify_hours(interval '27 hours')</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>1 day 03:00:00</literal></entry> </row> <row> - <entry> + <entry spanname="func" morerows="3"> <indexterm> <primary>justify_interval</primary> </indexterm> - <literal><function>justify_interval(<type>interval</type>)</function></literal> + <function>justify_interval</function> </entry> - <entry><type>interval</type></entry> - <entry>Adjust interval using <function>justify_days</function> and <function>justify_hours</function>, with additionalsign adjustments</entry> - <entry><literal>justify_interval(interval '1 mon -1 hour')</literal></entry> - <entry><literal>29 days 23:00:00</literal></entry> + <entry spanname="args"><type>interval</type></entry> + <entry spanname="result"><type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Adjust interval using <function>justify_days</function> and <function>justify_hours</function>,with additional sign adjustments</entry> + </row> + <row> + <entry spanname="example"><literal>justify_interval(interval '1 mon -1 hour')</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>29 days 23:00:00</literal></entry> </row> <row> - <entry> + <entry spanname="func" morerows="3"> <indexterm> <primary>localtime</primary> </indexterm> - <literal><function>localtime</function></literal> + <function>localtime</function> </entry> - <entry><type>time</type></entry> - <entry>Current time of day; + <entry spanname="args">none (written without parentheses)</entry> + <entry spanname="result"><type>time</type></entry> + </row> + <row> + <entry spanname="desc">Current time of day; see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>localtime</literal></entry> + </row> + <row> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="func" morerows="3"> <indexterm> <primary>localtimestamp</primary> </indexterm> - <literal><function>localtimestamp</function></literal> + <function>localtimestamp</function> </entry> - <entry><type>timestamp</type></entry> - <entry>Current date and time (start of current transaction); + <entry spanname="args">none (written without parentheses)</entry> + <entry spanname="result"><type>timestamp</type></entry> + </row> + <row> + <entry spanname="desc">Current date and time (start of current transaction); see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>localtimestamp</literal></entry> + </row> + <row> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="func" morerows="3"> <indexterm> <primary>make_date</primary> </indexterm> - <literal> - <function> - make_date(<parameter>year</parameter> <type>int</type>, - <parameter>month</parameter> <type>int</type>, - <parameter>day</parameter> <type>int</type>) - </function> - </literal> + <function>make_date</function> </entry> - <entry><type>date</type></entry> - <entry> + <entry spanname="args"><parameter>year</parameter> <type>int</type>, + <parameter>month</parameter> <type>int</type>, + <parameter>day</parameter> <type>int</type></entry> + <entry spanname="result"><type>date</type></entry> + </row> + <row> + <entry spanname="desc"> Create date from year, month and day fields </entry> - <entry><literal>make_date(2013, 7, 15)</literal></entry> - <entry><literal>2013-07-15</literal></entry> + </row> + <row> + <entry spanname="example"><literal>make_date(2013, 7, 15)</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>2013-07-15</literal></entry> </row> <row> - <entry> - <indexterm> + <entry spanname="func" morerows="3"><indexterm> <primary>make_interval</primary> </indexterm> - <literal> - <function> - make_interval(<parameter>years</parameter> <type>int</type> DEFAULT 0, - <parameter>months</parameter> <type>int</type> DEFAULT 0, - <parameter>weeks</parameter> <type>int</type> DEFAULT 0, - <parameter>days</parameter> <type>int</type> DEFAULT 0, - <parameter>hours</parameter> <type>int</type> DEFAULT 0, - <parameter>mins</parameter> <type>int</type> DEFAULT 0, - <parameter>secs</parameter> <type>double precision</type> DEFAULT 0.0) - </function> - </literal> + <function>make_interval</function> </entry> - <entry><type>interval</type></entry> - <entry> + <entry spanname="args"><optional> <type>int</type> + <optional>, <type>int</type> + <optional>, <type>int</type> + <optional>, <type>int</type> + <optional>, <type>int</type> + <optional>, <type>int</type> + <optional>, <type>double precision</type> + </optional></optional></optional></optional></optional></optional></optional></entry> + <entry spanname="result"><type>interval</type></entry> + </row> + <row> + <entry spanname="desc"> Create interval from years, months, weeks, days, hours, minutes and - seconds fields + seconds fields, each of which can default to zero </entry> - <entry><literal>make_interval(days => 10)</literal></entry> - <entry><literal>10 days</literal></entry> + </row> + <row> + <entry spanname="example"><literal>make_interval(days => 10)</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>10 days</literal></entry> </row> <row> - <entry> + <entry spanname="func" morerows="3"> <indexterm> <primary>make_time</primary> </indexterm> - <literal> - <function> - make_time(<parameter>hour</parameter> <type>int</type>, - <parameter>min</parameter> <type>int</type>, - <parameter>sec</parameter> <type>double precision</type>) - </function> - </literal> + <function>make_time</function> </entry> - <entry><type>time</type></entry> - <entry> + <entry spanname="args"><parameter>hour</parameter> <type>int</type>, + <parameter>min</parameter> <type>int</type>, + <parameter>sec</parameter> <type>double precision</type></entry> + <entry spanname="result"><type>time</type></entry> + </row> + <row> + <entry spanname="desc"> Create time from hour, minute and seconds fields </entry> - <entry><literal>make_time(8, 15, 23.5)</literal></entry> - <entry><literal>08:15:23.5</literal></entry> + </row> + <row> + <entry spanname="example"><literal>make_time(8, 15, 23.5)</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>08:15:23.5</literal></entry> </row> <row> - <entry> + <entry spanname="func" morerows="3"> <indexterm> <primary>make_timestamp</primary> </indexterm> - <literal> - <function> - make_timestamp(<parameter>year</parameter> <type>int</type>, - <parameter>month</parameter> <type>int</type>, - <parameter>day</parameter> <type>int</type>, - <parameter>hour</parameter> <type>int</type>, - <parameter>min</parameter> <type>int</type>, - <parameter>sec</parameter> <type>double precision</type>) - </function> - </literal> + <function>make_timestamp</function> </entry> - <entry><type>timestamp</type></entry> - <entry> + <entry spanname="args"><parameter>year</parameter> <type>int</type>, + <parameter>month</parameter> <type>int</type>, + <parameter>day</parameter> <type>int</type>, + <parameter>hour</parameter> <type>int</type>, + <parameter>min</parameter> <type>int</type>, + <parameter>sec</parameter> <type>double precision</type></entry> + <entry spanname="result"><type>timestamp</type></entry> + </row> + <row> + <entry spanname="desc"> Create timestamp from year, month, day, hour, minute and seconds fields </entry> - <entry><literal>make_timestamp(2013, 7, 15, 8, 15, 23.5)</literal></entry> - <entry><literal>2013-07-15 08:15:23.5</literal></entry> + </row> + <row> + <entry spanname="example"><literal>make_timestamp(2013, 7, 15, 8, 15, 23.5)</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>2013-07-15 08:15:23.5</literal></entry> </row> <row> - <entry> + <entry spanname="func" morerows="3"> <indexterm> <primary>make_timestamptz</primary> </indexterm> - <literal> - <function> - make_timestamptz(<parameter>year</parameter> <type>int</type>, - <parameter>month</parameter> <type>int</type>, - <parameter>day</parameter> <type>int</type>, - <parameter>hour</parameter> <type>int</type>, - <parameter>min</parameter> <type>int</type>, - <parameter>sec</parameter> <type>double precision</type>, - <optional> <parameter>timezone</parameter> <type>text</type> </optional>) - </function> - </literal> + <function>make_timestamptz</function> </entry> - <entry><type>timestamp with time zone</type></entry> - <entry> + <entry spanname="args"><parameter>year</parameter> <type>int</type>, + <parameter>month</parameter> <type>int</type>, + <parameter>day</parameter> <type>int</type>, + <parameter>hour</parameter> <type>int</type>, + <parameter>min</parameter> <type>int</type>, + <parameter>sec</parameter> <type>double precision</type>, + <optional> <parameter>timezone</parameter> <type>text</type> </optional></entry> + <entry spanname="result"><type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc"> Create timestamp with time zone from year, month, day, hour, minute and seconds fields; if <parameter>timezone</parameter> is not specified, the current time zone is used </entry> - <entry><literal>make_timestamptz(2013, 7, 15, 8, 15, 23.5)</literal></entry> - <entry><literal>2013-07-15 08:15:23.5+01</literal></entry> + </row> + <row> + <entry spanname="example"><literal>make_timestamptz(2013, 7, 15, 8, 15, 23.5)</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>2013-07-15 08:15:23.5+01</literal></entry> </row> <row> - <entry> + <entry spanname="func" morerows="3"> <indexterm> <primary>now</primary> </indexterm> - <literal><function>now()</function></literal> + <function>now</function> </entry> - <entry><type>timestamp with time zone</type></entry> - <entry>Current date and time (start of current transaction); + <entry spanname="args">none</entry> + <entry spanname="result"><type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Current date and time (start of current transaction); see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>now()</literal></entry> + </row> + <row> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="func" morerows="3"> <indexterm> <primary>statement_timestamp</primary> </indexterm> - <literal><function>statement_timestamp()</function></literal> + <function>statement_timestamp</function> </entry> - <entry><type>timestamp with time zone</type></entry> - <entry>Current date and time (start of current statement); + <entry spanname="args">none</entry> + <entry spanname="result"><type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Current date and time (start of current statement); see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>statement_timestamp()</literal></entry> + </row> + <row> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="func" morerows="3"> <indexterm> <primary>timeofday</primary> </indexterm> - <literal><function>timeofday()</function></literal> + <function>timeofday</function> </entry> - <entry><type>text</type></entry> - <entry>Current date and time + <entry spanname="args">none</entry> + <entry spanname="result"><type>text</type></entry> + </row> + <row> + <entry spanname="desc">Current date and time (like <function>clock_timestamp</function>, but as a <type>text</type> string); see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>timeofday()</literal></entry> + </row> + <row> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="func" morerows="3"> <indexterm> <primary>transaction_timestamp</primary> </indexterm> - <literal><function>transaction_timestamp()</function></literal> + <function>transaction_timestamp</function> </entry> - <entry><type>timestamp with time zone</type></entry> - <entry>Current date and time (start of current transaction); + <entry spanname="args">none</entry> + <entry spanname="result"><type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Current date and time (start of current transaction); see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> </row> <row> - <entry> + <entry spanname="example"><literal>transaction_timestamp()</literal></entry> + </row> + <row> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> + </row> + <row> + <entry spanname="func" morerows="3"> <indexterm> <primary>to_timestamp</primary> </indexterm> - <literal><function>to_timestamp(<type>double precision</type>)</function></literal> + <function>to_timestamp</function> </entry> - <entry><type>timestamp with time zone</type></entry> - <entry>Convert Unix epoch (seconds since 1970-01-01 00:00:00+00) to + <entry spanname="args"><type>double precision</type></entry> + <entry spanname="result"><type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Convert Unix epoch (seconds since 1970-01-01 00:00:00+00) to timestamp</entry> - <entry><literal>to_timestamp(1284352323)</literal></entry> - <entry><literal>2010-09-13 04:32:03+00</literal></entry> + </row> + <row> + <entry spanname="example"><literal>to_timestamp(1284352323)</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>2010-09-13 04:32:03+00</literal></entry> </row> </tbody> </tgroup> @@ -8236,52 +8447,74 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple <table id="functions-enum-table"> <title>Enum Support Functions</title> - <tgroup cols="4"> + <tgroup cols="2"> + <colspec colnum="1" colname="col1" colwidth="1*"/> + <colspec colnum="2" colname="col2" colwidth="2*"/> + <spanspec spanname="func" namest="col1" nameend="col1" align="left"/> + <spanspec spanname="desc" namest="col2" nameend="col2" align="left"/> + <spanspec spanname="example" namest="col2" nameend="col2" align="left"/> + <spanspec spanname="exresult" namest="col2" nameend="col2" align="left"/> <thead> <row> - <entry>Function</entry> - <entry>Description</entry> - <entry>Example</entry> - <entry>Example Result</entry> + <entry spanname="func" align="center" morerows="2">Function</entry> + <entry spanname="desc" align="center">Description</entry> + </row> + <row> + <entry spanname="example" align="center">Example</entry> + </row> + <row> + <entry spanname="exresult" align="center">Result</entry> </row> </thead> <tbody> <row> - <entry> + <entry spanname="func" morerows="2"> <indexterm> <primary>enum_first</primary> </indexterm> - <literal>enum_first(anyenum)</literal> + <literal>enum_first(anyenum) returns anyenum</literal> </entry> - <entry>Returns the first value of the input enum type</entry> - <entry><literal>enum_first(null::rainbow)</literal></entry> - <entry><literal>red</literal></entry> + <entry spanname="desc">Returns the first value of the input enum type</entry> </row> <row> - <entry> + <entry spanname="example"><literal>enum_first(null::rainbow)</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>red</literal></entry> + </row> + <row> + <entry spanname="func" morerows="2"> <indexterm> <primary>enum_last</primary> </indexterm> - <literal>enum_last(anyenum)</literal> + <literal>enum_last(anyenum) returns anyenum</literal> </entry> - <entry>Returns the last value of the input enum type</entry> - <entry><literal>enum_last(null::rainbow)</literal></entry> - <entry><literal>purple</literal></entry> + <entry spanname="desc">Returns the last value of the input enum type</entry> </row> <row> - <entry> + <entry spanname="example"><literal>enum_last(null::rainbow)</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>purple</literal></entry> + </row> + <row> + <entry spanname="func" morerows="2"> <indexterm> <primary>enum_range</primary> </indexterm> - <literal>enum_range(anyenum)</literal> + <literal>enum_range(anyenum) returns anyarray</literal> </entry> - <entry>Returns all values of the input enum type in an ordered array</entry> - <entry><literal>enum_range(null::rainbow)</literal></entry> - <entry><literal>{red,orange,yellow,green,blue,purple}</literal></entry> + <entry spanname="desc">Returns all values of the input enum type in an ordered array</entry> + </row> + <row> + <entry spanname="example"><literal>enum_range(null::rainbow)</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>{red,orange,yellow,green,blue,purple}</literal></entry> </row> <row> - <entry morerows="2"><literal>enum_range(anyenum, anyenum)</literal></entry> - <entry morerows="2"> + <entry spanname="func" morerows="6"><literal>enum_range(anyenum, anyenum) returns anyarray</literal></entry> + <entry spanname="desc"> Returns the range between the two given enum values, as an ordered array. The values must be from the same enum type. If the first parameter is null, the result will start with the first value of @@ -8289,16 +8522,24 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple If the second parameter is null, the result will end with the last value of the enum type. </entry> - <entry><literal>enum_range('orange'::rainbow, 'green'::rainbow)</literal></entry> - <entry><literal>{orange,yellow,green}</literal></entry> </row> <row> - <entry><literal>enum_range(NULL, 'green'::rainbow)</literal></entry> - <entry><literal>{red,orange,yellow,green}</literal></entry> + <entry spanname="example"><literal>enum_range('orange'::rainbow, 'green'::rainbow)</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>{orange,yellow,green}</literal></entry> + </row> + <row> + <entry spanname="example"><literal>enum_range(NULL, 'green'::rainbow)</literal></entry> + </row> + <row> + <entry spanname="exresult"><literal>{red,orange,yellow,green}</literal></entry> + </row> + <row> + <entry spanname="example"><literal>enum_range('orange'::rainbow, NULL)</literal></entry> </row> <row> - <entry><literal>enum_range('orange'::rainbow, NULL)</literal></entry> - <entry><literal>{orange,yellow,green,blue,purple}</literal></entry> + <entry spanname="exresult"><literal>{orange,yellow,green,blue,purple}</literal></entry> </row> </tbody> </tgroup>
Hello Tom, 12.02.2020 00:51, Tom Lane wrote: > The crummy formatting of our tables of functions and operators has > been an issue for a long time. To my mind, there are several things > that need to be addressed: > > * The layout is completely unfriendly to function descriptions that > run to more than a few words. > > * It's not very practical to have more than one example per function > (or at least, we seldom do so). > > * The results look completely awful in PDF format, because of the > narrow effectively-available space, plus the fact that the toolchain > will prefer to overprint following columns instead of breaking text > where there's no whitespace. Please look at a less invasive approach that we use at Postgres Pro for some time (mainly for improving the translated documentation, but it works for the original one too). The idea is to add zero-width spaces after/before some chars ('(', ',', '[', etc) to let fop split lines where desired. It has one disadvantage - it's not search-friendly (though maybe that is application-dependent). But if it's feasible, I think this approach can at least complement a manual tables reformatting. Decreasing a font size in the tables seems appropriate to me too. Best regards, Alexander
Attachment
Alexander Lakhin <exclusion@gmail.com> writes: > Please look at a less invasive approach that we use at Postgres Pro for > some time (mainly for improving the translated documentation, but it > works for the original one too). The idea is to add zero-width spaces > after/before some chars ('(', ',', '[', etc) to let fop split lines > where desired. It has one disadvantage - it's not search-friendly > (though maybe that is application-dependent). > But if it's feasible, I think this approach can at least complement a > manual tables reformatting. Decreasing a font size in the tables seems > appropriate to me too. Hmm, interesting proposal. I experimented and verified that injecting zero-width space () does allow line breaking to occur in both HTML and PDF output, so this could be a route to improving the situation for overlength example texts. I do not think I like the idea of automatically injecting tons of them, though. As you say, it might hinder searching; and it would allow some silly breaks; and there are cases where it still wouldn't find a break, such as the examples for sha256() et al. I'd be happier about manually inserting breaks just in the places we really need them. To keep the source readable, I'd want to write something like "&zwsp;" not a numeric entity code, but it looks like we can define custom entities if we want. For amusement's sake, attached is a screenshot of what Table 9-33 looks like in A4 format, with my one-row-per-example patch of yesterday plus a few manually-added zero-width spaces to break up the examples. This is the first PDF rendering of that table that I've seen that I actually like. I also attached a screenshot of a segment of Table 9-31, to show what that layout proposal looks like. It's a little busier, but it does have the advantage that it's clearer how to apply that format to operator tables. The "returns <type>" notation isn't used anywhere in SQL for operators, so I am not in love with the idea of writing the operator tables that way. Also worth noting is that in most function tables, and certainly in the operator tables, we could make the first column narrower. The same table with the first column half as wide as the others is depicted in the last screenshot. (For this particular table, doing that would require breaking some of the longer function names such as transaction_timestamp. Not sure whether that's a net win, but we do have the option.) One issue that I've found is that the toolchain has no idea that the table rows are in groups, so it's happy to split a table across pages with a function's description and/or examples on a new page. No idea if there's any way around that. Fortunately it's not an issue in HTML, so maybe we don't have to fix it. Thoughts? regards, tom lane
Attachment
On 2020-Feb-12, Tom Lane wrote: > For amusement's sake, attached is a screenshot of what Table 9-33 > looks like in A4 format, with my one-row-per-example patch of > yesterday plus a few manually-added zero-width spaces to break up > the examples. This is the first PDF rendering of that table that > I've seen that I actually like. I like this. The trick of mkaing the first cell take up two or three rows makes this much clearer and sensible than what I had obtained. > I also attached a screenshot of a segment of Table 9-31, to show > what that layout proposal looks like. It's a little busier, but > it does have the advantage that it's clearer how to apply that > format to operator tables. The "returns <type>" notation isn't used > anywhere in SQL for operators, so I am not in love with the idea of > writing the operator tables that way. Yeah, that's a little less obvious. I just noticed that the operators tables show the operator names but not the input datatypes except in the examples. Perhaps we could use a layout with a cell labelled "signature" (namest=col2 nameend=col3) instead of input types + return types and separate them using → which would look like this: date + integer → date > Also worth noting is that in most function tables, and certainly > in the operator tables, we could make the first column narrower. > The same table with the first column half as wide as the others > is depicted in the last screenshot. (For this particular table, > doing that would require breaking some of the longer function > names such as transaction_timestamp. Not sure whether that's > a net win, but we do have the option.) I like making that column narrower. > One issue that I've found is that the toolchain has no idea that > the table rows are in groups, so it's happy to split a table > across pages with a function's description and/or examples on > a new page. No idea if there's any way around that. Fortunately > it's not an issue in HTML, so maybe we don't have to fix it. My vote goes to postponing a solution to this problem :-) -- Álvaro Herrera https://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
Alvaro Herrera <alvherre@2ndquadrant.com> writes: > On 2020-Feb-12, Tom Lane wrote: >> I also attached a screenshot of a segment of Table 9-31, to show >> what that layout proposal looks like. It's a little busier, but >> it does have the advantage that it's clearer how to apply that >> format to operator tables. The "returns <type>" notation isn't used >> anywhere in SQL for operators, so I am not in love with the idea of >> writing the operator tables that way. > Yeah, that's a little less obvious. I just noticed that the operators > tables show the operator names but not the input datatypes except in the > examples. Perhaps we could use a layout with a cell labelled > "signature" (namest=col2 nameend=col3) instead of input types + return > types and separate them using → which would look like this: > date + integer → date Oh, that's a thought. We could do the same for functions: function name type1, type2, type3 → rettype description ... example example result which'd relieve the column-width pressure for functions with several arguments. On the other hand, that would look a little funny for functions with no arguments ... not but what they're going to look funny no matter what. I used "none" in my conversion of table 9.31, but wasn't satisfied with that, because it relies completely on font choice to be distinguishable from a data type named "none". With a separate argument-types cell it'd likely be better to just leave the cell empty, but do we want to write just "→ rettype" in a signature cell? The other thing I was struggling with was how to distinguish normal zero-argument functions (written with parens) from those SQL abominations that are function calls with no parens. I think we need to show that somehow, so that it's clear that the examples are correct and not typos. It doesn't have to be *totally* obvious, perhaps, if we have an example to back it up ... but the example can't be the only thing. Maybe don't take out the parens? So it'd work like Function Signature age (timestamp) → interval now () → timestamp with time zone current_timestamp → timestamp with time zone Also, I think we're both imagining that we'd use the operator name in operator signatures: Operator Signature + integer + integer → integer + + integer → integer so being consistent with that might suggest including the function name in function signatures: Function Signature age age(timestamp) → interval now now() → timestamp with time zone current_timestamp current_timestamp → timestamp with time zone I'm a bit suspicious of how much horizontal space that would eat, but if we're able to get rid of the separate cell for result type, it might work out OK. regards, tom lane
On 2020-Feb-12, Tom Lane wrote: > With a separate argument-types cell it'd likely be > better to just leave the cell empty, but do we want to write > just "→ rettype" in a signature cell? Yeah, it'd look very odd, and certainly the no-parens case makes it worse. I like this end result: > so being consistent with that might suggest including the function name > in function signatures: > > Function Signature > > age age(timestamp) → interval > > now now() → timestamp with time zone > > current_timestamp current_timestamp → timestamp with time zone > > I'm a bit suspicious of how much horizontal space that would eat, but > if we're able to get rid of the separate cell for result type, it > might work out OK. Regarding no-parens function signatures, perhaps we can add a footnote indicating that such functions have this strange shape because of the SQL committee, such as "† This function signature uses no parentheses because the SQL standard defines it in that way." -- Álvaro Herrera https://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
Alvaro Herrera <alvherre@2ndquadrant.com> writes: > Yeah, it'd look very odd, and certainly the no-parens case makes it > worse. I like this end result: >> Function Signature >> age age(timestamp) → interval >> now now() → timestamp with time zone >> current_timestamp current_timestamp → timestamp with time zone I gave that a try, and it seems to work really well. It can even handle the ridiculously long signature for make_interval() in reasonable style, as shown in the screenshot attached. One problem with the rightarrow idea is that it's not rendering quite right for me: it looks great in HTML, but in PDF it comes out flush with the baseline, as you can see in the screenshot. Hopefully there's a way to fix that that we can hide in the custom entity ... but I have no idea how. I decided to try converting the date/time operators table too, to see how well this works for that. It's bulkier than before, but also (I think) more precise. I realized that this table actually had three examples already for float8 * interval, but it wasn't at all obvious that they were the same operator. So that aspect is a lot nicer here. On the other hand, it seems like the text descriptions are only marginally useful here. I can imagine that they would be useful in some other operator tables, such as geometric operators, but I'm a bit tempted to leave them out in this particular table. The format would adapt to that easily. Another thing worth considering is removing duplicate left-hand- column entries, that is, considering all the instances of similarly-named functions/operators to be "the same". In the attached patch, I did that for isfinite() but not anywhere else. I'm not quite sure if it's a good idea or not. It seems like it makes sense for isfinite(), but perhaps less so for operators. Again, comments welcome. This is starting to feel like a real proposal now, but I'm still not at all wedded to it. regards, tom lane diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index ceda48e..adfa571 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -2934,7 +2934,7 @@ SELECT format('Testing %3$s, %2$s, %s', 'one', 'two', 'three'); the result written in hexadecimal </entry> <entry><literal>md5('Th\000omas'::bytea)</literal></entry> - <entry><literal>8ab2d3c9689aaf18b4958c334c82d8b1</literal></entry> + <entry><literal>8ab2d3c9689aaf18&break;b4958c334c82d8b1</literal></entry> </row> <row> @@ -2985,7 +2985,7 @@ SELECT format('Testing %3$s, %2$s, %s', 'one', 'two', 'three'); SHA-224 <link linkend="functions-hash-note">hash</link> </entry> <entry><literal>sha224('abc'::bytea)</literal></entry> - <entry><literal>\x23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7</literal></entry> + <entry><literal>\x23097d223405d8228642a477bda2&break;55b32aadbce4bda0b3f7e36c9da7</literal></entry> </row> <row> @@ -3000,7 +3000,7 @@ SELECT format('Testing %3$s, %2$s, %s', 'one', 'two', 'three'); SHA-256 <link linkend="functions-hash-note">hash</link> </entry> <entry><literal>sha256('abc'::bytea)</literal></entry> - <entry><literal>\xba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad</literal></entry> + <entry><literal>\xba7816bf8f01cfea414140de5dae2223&break;b00361a396177a9cb410ff61f20015ad</literal></entry> </row> <row> @@ -3015,7 +3015,7 @@ SELECT format('Testing %3$s, %2$s, %s', 'one', 'two', 'three'); SHA-384 <link linkend="functions-hash-note">hash</link> </entry> <entry><literal>sha384('abc'::bytea)</literal></entry> - <entry><literal>\xcb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7</literal></entry> + <entry><literal>\xcb00753f45a35e8bb5a03d699ac65007&break;272c32ab0eded1631a8b605a43ff5bed&break;8086072ba1e7cc2358baeca134c825a7</literal></entry> </row> <row> @@ -3030,7 +3030,7 @@ SELECT format('Testing %3$s, %2$s, %s', 'one', 'two', 'three'); SHA-512 <link linkend="functions-hash-note">hash</link> </entry> <entry><literal>sha512('abc'::bytea)</literal></entry> - <entry><literal>\xddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f</literal></entry> + <entry><literal>\xddaf35a193617abacc417349ae204131&break;12e6fa4e89a97ea20a9eeee64b55d39a&break;2192992a274fc1a836ba3c23a3feebbd&break;454d4423643ce80e2a9ac94fa54ca49f</literal></entry> </row> <row> @@ -6670,127 +6670,256 @@ SELECT regexp_match('abc01234xyz', '(?:(.*?)(\d+)(.*)){1,1}'); <title>Date/Time Operators</title> <tgroup cols="3"> + <colspec colnum="1" colname="col1" colwidth="0.25*"/> + <colspec colnum="2" colname="col2" colwidth="1*"/> + <colspec colnum="3" colname="col3" colwidth="1*"/> + <spanspec spanname="name" namest="col1" nameend="col1" align="left"/> + <spanspec spanname="sig" namest="col2" nameend="col3" align="left"/> + <spanspec spanname="desc" namest="col2" nameend="col3" align="left"/> + <spanspec spanname="example" namest="col2" nameend="col2" align="left"/> + <spanspec spanname="exresult" namest="col3" nameend="col3" align="left"/> <thead> <row> - <entry>Operator</entry> - <entry>Example</entry> - <entry>Result</entry> + <entry spanname="name" align="center" morerows="2">Operator</entry> + <entry spanname="sig" align="center">Signature</entry> + </row> + <row> + <entry spanname="desc" align="center">Description</entry> + </row> + <row> + <entry spanname="example" align="center">Example</entry> + <entry spanname="exresult" align="center">Example Result</entry> </row> </thead> <tbody> <row> - <entry> <literal>+</literal> </entry> - <entry><literal>date '2001-09-28' + integer '7'</literal></entry> - <entry><literal>date '2001-10-05'</literal></entry> + <entry spanname="name" morerows="2"> <literal>+</literal> </entry> + <entry spanname="sig"><type>date</type> <literal>+</literal> <type>integer</type> + &returns; <type>date</type></entry> </row> - <row> - <entry> <literal>+</literal> </entry> - <entry><literal>date '2001-09-28' + interval '1 hour'</literal></entry> - <entry><literal>timestamp '2001-09-28 01:00:00'</literal></entry> + <entry spanname="desc">Add a number of days to a date</entry> </row> - <row> - <entry> <literal>+</literal> </entry> - <entry><literal>date '2001-09-28' + time '03:00'</literal></entry> - <entry><literal>timestamp '2001-09-28 03:00:00'</literal></entry> + <entry spanname="example"><literal>date '2001-09-28' + 7</literal></entry> + <entry spanname="exresult"><literal>2001-10-05</literal></entry> </row> <row> - <entry> <literal>+</literal> </entry> - <entry><literal>interval '1 day' + interval '1 hour'</literal></entry> - <entry><literal>interval '1 day 01:00:00'</literal></entry> + <entry spanname="name" morerows="2"> <literal>+</literal> </entry> + <entry spanname="sig"><type>date</type> <literal>+</literal> <type>interval</type> + &returns; <type>timestamp</type></entry> + </row> + <row> + <entry spanname="desc">Add an interval to a date</entry> + </row> + <row> + <entry spanname="example"><literal>date '2001-09-28' + interval '1 hour'</literal></entry> + <entry spanname="exresult"><literal>2001-09-28 01:00:00</literal></entry> </row> <row> - <entry> <literal>+</literal> </entry> - <entry><literal>timestamp '2001-09-28 01:00' + interval '23 hours'</literal></entry> - <entry><literal>timestamp '2001-09-29 00:00:00'</literal></entry> + <entry spanname="name" morerows="2"> <literal>+</literal> </entry> + <entry spanname="sig"><type>date</type> <literal>+</literal> <type>time</type> + &returns; <type>timestamp</type></entry> + </row> + <row> + <entry spanname="desc">Add a time-of-day to a date</entry> + </row> + <row> + <entry spanname="example"><literal>date '2001-09-28' + time '03:00'</literal></entry> + <entry spanname="exresult"><literal>2001-09-28 03:00:00</literal></entry> </row> <row> - <entry> <literal>+</literal> </entry> - <entry><literal>time '01:00' + interval '3 hours'</literal></entry> - <entry><literal>time '04:00:00'</literal></entry> + <entry spanname="name" morerows="2"> <literal>+</literal> </entry> + <entry spanname="sig"><type>interval</type> <literal>+</literal> <type>interval</type> + &returns; <type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Add intervals</entry> + </row> + <row> + <entry spanname="example"><literal>interval '1 day' + interval '1 hour'</literal></entry> + <entry spanname="exresult"><literal>1 day 01:00:00</literal></entry> </row> <row> - <entry> <literal>-</literal> </entry> - <entry><literal>- interval '23 hours'</literal></entry> - <entry><literal>interval '-23:00:00'</literal></entry> + <entry spanname="name" morerows="2"> <literal>+</literal> </entry> + <entry spanname="sig"><type>timestamp</type> <literal>+</literal> <type>interval</type> + &returns; <type>timestamp</type></entry> + </row> + <row> + <entry spanname="desc">Add an interval to a timestamp</entry> + </row> + <row> + <entry spanname="example"><literal>timestamp '2001-09-28 01:00' + interval '23 hours'</literal></entry> + <entry spanname="exresult"><literal>2001-09-29 00:00:00</literal></entry> </row> <row> - <entry> <literal>-</literal> </entry> - <entry><literal>date '2001-10-01' - date '2001-09-28'</literal></entry> - <entry><literal>integer '3'</literal> (days)</entry> + <entry spanname="name" morerows="2"> <literal>+</literal> </entry> + <entry spanname="sig"><type>time</type> <literal>+</literal> <type>interval</type> + &returns; <type>time</type></entry> + </row> + <row> + <entry spanname="desc">Add an interval to a time</entry> + </row> + <row> + <entry spanname="example"><literal>time '01:00' + interval '3 hours'</literal></entry> + <entry spanname="exresult"><literal>04:00:00</literal></entry> </row> <row> - <entry> <literal>-</literal> </entry> - <entry><literal>date '2001-10-01' - integer '7'</literal></entry> - <entry><literal>date '2001-09-24'</literal></entry> + <entry spanname="name" morerows="2"> <literal>-</literal> </entry> + <entry spanname="sig"><literal>-</literal> <type>interval</type> + &returns; <type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Negate an interval</entry> + </row> + <row> + <entry spanname="example"><literal>- interval '23 hours'</literal></entry> + <entry spanname="exresult"><literal>-23:00:00</literal></entry> </row> <row> - <entry> <literal>-</literal> </entry> - <entry><literal>date '2001-09-28' - interval '1 hour'</literal></entry> - <entry><literal>timestamp '2001-09-27 23:00:00'</literal></entry> + <entry spanname="name" morerows="2"> <literal>-</literal> </entry> + <entry spanname="sig"><type>date</type> <literal>-</literal> <type>date</type> + &returns; <type>integer</type></entry> + </row> + <row> + <entry spanname="desc">Subtract dates</entry> + </row> + <row> + <entry spanname="example"><literal>date '2001-10-01' - date '2001-09-28'</literal></entry> + <entry spanname="exresult"><literal>3</literal></entry> </row> <row> - <entry> <literal>-</literal> </entry> - <entry><literal>time '05:00' - time '03:00'</literal></entry> - <entry><literal>interval '02:00:00'</literal></entry> + <entry spanname="name" morerows="2"> <literal>-</literal> </entry> + <entry spanname="sig"><type>date</type> <literal>-</literal> <type>integer</type> + &returns; <type>date</type></entry> + </row> + <row> + <entry spanname="desc">Subtract a number of days from a date</entry> + </row> + <row> + <entry spanname="example"><literal>date '2001-10-01' - 7</literal></entry> + <entry spanname="exresult"><literal>2001-09-24</literal></entry> </row> <row> - <entry> <literal>-</literal> </entry> - <entry><literal>time '05:00' - interval '2 hours'</literal></entry> - <entry><literal>time '03:00:00'</literal></entry> + <entry spanname="name" morerows="2"> <literal>-</literal> </entry> + <entry spanname="sig"><type>date</type> <literal>-</literal> <type>interval</type> + &returns; <type>timestamp</type></entry> + </row> + <row> + <entry spanname="desc">Subtract an interval from a date</entry> + </row> + <row> + <entry spanname="example"><literal>date '2001-09-28' - interval '1 hour'</literal></entry> + <entry spanname="exresult"><literal>2001-09-27 23:00:00</literal></entry> </row> <row> - <entry> <literal>-</literal> </entry> - <entry><literal>timestamp '2001-09-28 23:00' - interval '23 hours'</literal></entry> - <entry><literal>timestamp '2001-09-28 00:00:00'</literal></entry> + <entry spanname="name" morerows="2"> <literal>-</literal> </entry> + <entry spanname="sig"><type>time</type> <literal>-</literal> <type>time</type> + &returns; <type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Subtract times</entry> + </row> + <row> + <entry spanname="example"><literal>time '05:00' - time '03:00'</literal></entry> + <entry spanname="exresult"><literal>02:00:00</literal></entry> </row> <row> - <entry> <literal>-</literal> </entry> - <entry><literal>interval '1 day' - interval '1 hour'</literal></entry> - <entry><literal>interval '1 day -01:00:00'</literal></entry> + <entry spanname="name" morerows="2"> <literal>-</literal> </entry> + <entry spanname="sig"><type>time</type> <literal>-</literal> <type>interval</type> + &returns; <type>time</type></entry> + </row> + <row> + <entry spanname="desc">Subtract an interval from a time</entry> + </row> + <row> + <entry spanname="example"><literal>time '05:00' - interval '2 hours'</literal></entry> + <entry spanname="exresult"><literal>03:00:00</literal></entry> </row> <row> - <entry> <literal>-</literal> </entry> - <entry><literal>timestamp '2001-09-29 03:00' - timestamp '2001-09-27 12:00'</literal></entry> - <entry><literal>interval '1 day 15:00:00'</literal></entry> + <entry spanname="name" morerows="2"> <literal>-</literal> </entry> + <entry spanname="sig"><type>timestamp</type> <literal>-</literal> <type>interval</type> + &returns; <type>timestamp</type></entry> + </row> + <row> + <entry spanname="desc">Subtract an interval from a timestamp</entry> + </row> + <row> + <entry spanname="example"><literal>timestamp '2001-09-28 23:00' - interval '23 hours'</literal></entry> + <entry spanname="exresult"><literal>2001-09-28 00:00:00</literal></entry> </row> <row> - <entry> <literal>*</literal> </entry> - <entry><literal>900 * interval '1 second'</literal></entry> - <entry><literal>interval '00:15:00'</literal></entry> + <entry spanname="name" morerows="2"> <literal>-</literal> </entry> + <entry spanname="sig"><type>interval</type> <literal>-</literal> <type>interval</type> + &returns; <type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Subtract intervals</entry> + </row> + <row> + <entry spanname="example"><literal>interval '1 day' - interval '1 hour'</literal></entry> + <entry spanname="exresult"><literal>1 day -01:00:00</literal></entry> </row> <row> - <entry> <literal>*</literal> </entry> - <entry><literal>21 * interval '1 day'</literal></entry> - <entry><literal>interval '21 days'</literal></entry> + <entry spanname="name" morerows="2"> <literal>-</literal> </entry> + <entry spanname="sig"><type>timestamp</type> <literal>-</literal> <type>timestamp</type> + &returns; <type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Subtract timestamps</entry> + </row> + <row> + <entry spanname="example"><literal>timestamp '2001-09-29 03:00' - timestamp '2001-09-27 12:00'</literal></entry> + <entry spanname="exresult"><literal>1 day 15:00:00</literal></entry> </row> <row> - <entry> <literal>*</literal> </entry> - <entry><literal>double precision '3.5' * interval '1 hour'</literal></entry> - <entry><literal>interval '03:30:00'</literal></entry> + <entry spanname="name" morerows="4"> <literal>*</literal> </entry> + <entry spanname="sig"><type>double precision</type> <literal>*</literal> <type>interval</type> + &returns; <type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Multiply an interval by a scalar</entry> + </row> + <row> + <entry spanname="example"><literal>900 * interval '1 second'</literal></entry> + <entry spanname="exresult"><literal>00:15:00</literal></entry> + </row> + <row> + <entry spanname="example"><literal>21 * interval '1 day'</literal></entry> + <entry spanname="exresult"><literal>21 days</literal></entry> + </row> + <row> + <entry spanname="example"><literal>3.5 * interval '1 hour'</literal></entry> + <entry spanname="exresult"><literal>03:30:00</literal></entry> </row> <row> - <entry> <literal>/</literal> </entry> - <entry><literal>interval '1 hour' / double precision '1.5'</literal></entry> - <entry><literal>interval '00:40:00'</literal></entry> + <entry spanname="name" morerows="2"> <literal>/</literal> </entry> + <entry spanname="sig"><type>interval</type> <literal>/</literal> <type>double precision</type> + &returns; <type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Divide an interval by a scalar</entry> + </row> + <row> + <entry spanname="example"><literal>interval '1 hour' / 1.5</literal></entry> + <entry spanname="exresult"><literal>00:40:00</literal></entry> </row> </tbody> </tgroup> @@ -6798,471 +6927,614 @@ SELECT regexp_match('abc01234xyz', '(?:(.*?)(\d+)(.*)){1,1}'); <table id="functions-datetime-table"> <title>Date/Time Functions</title> - <tgroup cols="5"> + <tgroup cols="3"> + <colspec colnum="1" colname="col1" colwidth="1*"/> + <colspec colnum="2" colname="col2" colwidth="1*"/> + <colspec colnum="3" colname="col3" colwidth="1*"/> + <spanspec spanname="name" namest="col1" nameend="col1" align="left"/> + <spanspec spanname="sig" namest="col2" nameend="col3" align="left"/> + <spanspec spanname="desc" namest="col2" nameend="col3" align="left"/> + <spanspec spanname="example" namest="col2" nameend="col2" align="left"/> + <spanspec spanname="exresult" namest="col3" nameend="col3" align="left"/> <thead> <row> - <entry>Function</entry> - <entry>Return Type</entry> - <entry>Description</entry> - <entry>Example</entry> - <entry>Result</entry> + <entry spanname="name" align="center" morerows="2">Function</entry> + <entry spanname="sig" align="center">Signature</entry> + </row> + <row> + <entry spanname="desc" align="center">Description</entry> + </row> + <row> + <entry spanname="example" align="center">Example</entry> + <entry spanname="exresult" align="center">Example Result</entry> </row> </thead> <tbody> <row> - <entry> + <entry spanname="name" morerows="2"> <indexterm> <primary>age</primary> </indexterm> - <literal><function>age(<type>timestamp</type>, <type>timestamp</type>)</function></literal> + <function>age</function> </entry> - <entry><type>interval</type></entry> - <entry>Subtract arguments, producing a <quote>symbolic</quote> result that + <entry spanname="sig"><function>age</function>(<type>timestamp</type>, <type>timestamp</type>) + &returns; <type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Subtract arguments, producing a <quote>symbolic</quote> result that uses years and months, rather than just days</entry> - <entry><literal>age(timestamp '2001-04-10', timestamp '1957-06-13')</literal></entry> - <entry><literal>43 years 9 mons 27 days</literal></entry> + </row> + <row> + <entry spanname="example"><literal>age(timestamp '2001-04-10', timestamp '1957-06-13')</literal></entry> + <entry spanname="exresult"><literal>43 years 9 mons 27 days</literal></entry> </row> <row> - <entry><literal><function>age(<type>timestamp</type>)</function></literal></entry> - <entry><type>interval</type></entry> - <entry>Subtract from <function>current_date</function> (at midnight)</entry> - <entry><literal>age(timestamp '1957-06-13')</literal></entry> - <entry><literal>43 years 8 mons 3 days</literal></entry> + <entry spanname="name" morerows="2"><function>age</function></entry> + <entry spanname="sig"><function>age</function>(<type>timestamp</type>) + &returns; <type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Subtract from <function>current_date</function> (at midnight)</entry> + </row> + <row> + <entry spanname="example"><literal>age(timestamp '1957-06-13')</literal></entry> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="name" morerows="2"> <indexterm> <primary>clock_timestamp</primary> </indexterm> - <literal><function>clock_timestamp()</function></literal> + <function>clock_timestamp</function> </entry> - <entry><type>timestamp with time zone</type></entry> - <entry>Current date and time (changes during statement execution); + <entry spanname="sig"><function>clock_timestamp</function>() + &returns; <type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Current date and time (changes during statement execution); see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>clock_timestamp()</literal></entry> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="name" morerows="2"> <indexterm> <primary>current_date</primary> </indexterm> - <literal><function>current_date</function></literal> + <function>current_date</function> </entry> - <entry><type>date</type></entry> - <entry>Current date; + <entry spanname="sig"><function>current_date</function> + &returns; <type>date</type></entry> + </row> + <row> + <entry spanname="desc">Current date; see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>current_date</literal></entry> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="name" morerows="2"> <indexterm> <primary>current_time</primary> </indexterm> - <literal><function>current_time</function></literal> + <function>current_time</function> </entry> - <entry><type>time with time zone</type></entry> - <entry>Current time of day; + <entry spanname="sig"><function>current_time</function> + &returns; <type>time with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Current time of day; see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>current_time</literal></entry> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="name" morerows="2"> <indexterm> <primary>current_timestamp</primary> </indexterm> - <literal><function>current_timestamp</function></literal> + <function>current_timestamp</function> </entry> - <entry><type>timestamp with time zone</type></entry> - <entry>Current date and time (start of current transaction); + <entry spanname="sig"><function>current_timestamp</function> + &returns; <type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Current date and time (start of current transaction); see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>current_timestamp</literal></entry> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="name" morerows="2"> <indexterm> <primary>date_part</primary> </indexterm> - <literal><function>date_part(<type>text</type>, <type>timestamp</type>)</function></literal> + <function>date_part</function> </entry> - <entry><type>double precision</type></entry> - <entry>Get subfield (equivalent to <function>extract</function>); + <entry spanname="sig"><function>date_part</function>(<type>text</type>, <type>timestamp</type>) + &returns; <type>double precision</type></entry> + </row> + <row> + <entry spanname="desc">Get subfield (equivalent to <function>extract</function>); see <xref linkend="functions-datetime-extract"/> </entry> - <entry><literal>date_part('hour', timestamp '2001-02-16 20:38:40')</literal></entry> - <entry><literal>20</literal></entry> + </row> + <row> + <entry spanname="example"><literal>date_part('hour', timestamp '2001-02-16 20:38:40')</literal></entry> + <entry spanname="exresult"><literal>20</literal></entry> </row> <row> - <entry><literal><function>date_part(<type>text</type>, <type>interval</type>)</function></literal></entry> - <entry><type>double precision</type></entry> - <entry>Get subfield (equivalent to + <entry spanname="name" morerows="2"><function>date_part</function></entry> + <entry spanname="sig"><function>date_part</function>(<type>text</type>, <type>interval</type>) + &returns; <type>double precision</type></entry> + </row> + <row> + <entry spanname="desc">Get subfield (equivalent to <function>extract</function>); see <xref linkend="functions-datetime-extract"/> </entry> - <entry><literal>date_part('month', interval '2 years 3 months')</literal></entry> - <entry><literal>3</literal></entry> + </row> + <row> + <entry spanname="example"><literal>date_part('month', interval '2 years 3 months')</literal></entry> + <entry spanname="exresult"><literal>3</literal></entry> </row> <row> - <entry> + <entry spanname="name" morerows="2"> <indexterm> <primary>date_trunc</primary> </indexterm> - <literal><function>date_trunc(<type>text</type>, <type>timestamp</type>)</function></literal> + <function>date_trunc</function> </entry> - <entry><type>timestamp</type></entry> - <entry>Truncate to specified precision; see <xref linkend="functions-datetime-trunc"/> + <entry spanname="sig"><function>date_trunc</function>(<type>text</type>, <type>timestamp</type>) + &returns; <type>timestamp</type></entry> + </row> + <row> + <entry spanname="desc">Truncate to specified precision; see <xref linkend="functions-datetime-trunc"/> </entry> - <entry><literal>date_trunc('hour', timestamp '2001-02-16 20:38:40')</literal></entry> - <entry><literal>2001-02-16 20:00:00</literal></entry> + </row> + <row> + <entry spanname="example"><literal>date_trunc('hour', timestamp '2001-02-16 20:38:40')</literal></entry> + <entry spanname="exresult"><literal>2001-02-16 20:00:00</literal></entry> </row> <row> - <entry><literal><function>date_trunc(<type>text</type>, <type>timestamp with time zone</type>, <type>text</type>)</function></literal></entry> - <entry><type>timestamp with time zone</type></entry> - <entry>Truncate to specified precision in the specified time zone; see <xref linkend="functions-datetime-trunc"/> + <entry spanname="name" morerows="2"><function>date_trunc</function></entry> + <entry spanname="sig"><function>date_trunc</function>(<type>text</type>, <type>timestamp with time zone</type>,<type>text</type>) + &returns; <type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Truncate to specified precision in the specified time zone; see <xref linkend="functions-datetime-trunc"/> </entry> - <entry><literal>date_trunc('day', timestamptz '2001-02-16 20:38:40+00', 'Australia/Sydney')</literal></entry> - <entry><literal>2001-02-16 13:00:00+00</literal></entry> + </row> + <row> + <entry spanname="example"><literal>date_trunc('day', timestamptz '2001-02-16 20:38:40+00', 'Australia/Sydney')</literal></entry> + <entry spanname="exresult"><literal>2001-02-16 13:00:00+00</literal></entry> </row> <row> - <entry><literal><function>date_trunc(<type>text</type>, <type>interval</type>)</function></literal></entry> - <entry><type>interval</type></entry> - <entry>Truncate to specified precision; see <xref linkend="functions-datetime-trunc"/> + <entry spanname="name" morerows="2"><function>date_trunc</function></entry> + <entry spanname="sig"><function>date_trunc</function>(<type>text</type>, <type>interval</type>) + &returns; <type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Truncate to specified precision; see <xref linkend="functions-datetime-trunc"/> </entry> - <entry><literal>date_trunc('hour', interval '2 days 3 hours 40 minutes')</literal></entry> - <entry><literal>2 days 03:00:00</literal></entry> + </row> + <row> + <entry spanname="example"><literal>date_trunc('hour', interval '2 days 3 hours 40 minutes')</literal></entry> + <entry spanname="exresult"><literal>2 days 03:00:00</literal></entry> </row> <row> - <entry> + <entry spanname="name" morerows="2"> <indexterm> <primary>extract</primary> </indexterm> - <literal><function>extract</function>(<parameter>field</parameter> from - <type>timestamp</type>)</literal> + <function>extract</function> </entry> - <entry><type>double precision</type></entry> - <entry>Get subfield; see <xref linkend="functions-datetime-extract"/> + <entry spanname="sig"><function>extract</function>(<parameter>field</parameter> <literal>from</literal> <type>timestamp</type>) + &returns; <type>double precision</type></entry> + </row> + <row> + <entry spanname="desc">Get subfield; see <xref linkend="functions-datetime-extract"/> </entry> - <entry><literal>extract(hour from timestamp '2001-02-16 20:38:40')</literal></entry> - <entry><literal>20</literal></entry> + </row> + <row> + <entry spanname="example"><literal>extract(hour from timestamp '2001-02-16 20:38:40')</literal></entry> + <entry spanname="exresult"><literal>20</literal></entry> </row> <row> - <entry><literal><function>extract</function>(<parameter>field</parameter> from - <type>interval</type>)</literal></entry> - <entry><type>double precision</type></entry> - <entry>Get subfield; see <xref linkend="functions-datetime-extract"/> + <entry spanname="name" morerows="2"><function>extract</function></entry> + <entry spanname="sig"><function>extract</function>(<parameter>field</parameter> <literal>from</literal> <type>interval</type>) + &returns; <type>double precision</type></entry> + </row> + <row> + <entry spanname="desc">Get subfield; see <xref linkend="functions-datetime-extract"/> </entry> - <entry><literal>extract(month from interval '2 years 3 months')</literal></entry> - <entry><literal>3</literal></entry> + </row> + <row> + <entry spanname="example"><literal>extract(month from interval '2 years 3 months')</literal></entry> + <entry spanname="exresult"><literal>3</literal></entry> </row> <row> - <entry> + <entry spanname="name" morerows="8"> <indexterm> <primary>isfinite</primary> </indexterm> - <literal><function>isfinite(<type>date</type>)</function></literal> + <function>isfinite</function> </entry> - <entry><type>boolean</type></entry> - <entry>Test for finite date (not +/-infinity)</entry> - <entry><literal>isfinite(date '2001-02-16')</literal></entry> - <entry><literal>true</literal></entry> + <entry spanname="sig"><function>isfinite</function>(<type>date</type>) + &returns; <type>boolean</type></entry> + </row> + <row> + <entry spanname="desc">Test for finite date (not +/-infinity)</entry> + </row> + <row> + <entry spanname="example"><literal>isfinite(date '2001-02-16')</literal></entry> + <entry spanname="exresult"><literal>true</literal></entry> </row> <row> - <entry><literal><function>isfinite(<type>timestamp</type>)</function></literal></entry> - <entry><type>boolean</type></entry> - <entry>Test for finite time stamp (not +/-infinity)</entry> - <entry><literal>isfinite(timestamp '2001-02-16 21:28:30')</literal></entry> - <entry><literal>true</literal></entry> + <entry spanname="sig"><function>isfinite</function>(<type>timestamp</type>) + &returns; <type>boolean</type></entry> + </row> + <row> + <entry spanname="desc">Test for finite time stamp (not +/-infinity)</entry> + </row> + <row> + <entry spanname="example"><literal>isfinite(timestamp '2001-02-16 21:28:30')</literal></entry> + <entry spanname="exresult"><literal>true</literal></entry> </row> <row> - <entry><literal><function>isfinite(<type>interval</type>)</function></literal></entry> - <entry><type>boolean</type></entry> - <entry>Test for finite interval</entry> - <entry><literal>isfinite(interval '4 hours')</literal></entry> - <entry><literal>true</literal></entry> + <entry spanname="sig"><function>isfinite</function>(<type>interval</type>) + &returns; <type>boolean</type></entry> + </row> + <row> + <entry spanname="desc">Test for finite interval</entry> + </row> + <row> + <entry spanname="example"><literal>isfinite(interval '4 hours')</literal></entry> + <entry spanname="exresult"><literal>true</literal></entry> </row> <row> - <entry> + <entry spanname="name" morerows="2"> <indexterm> <primary>justify_days</primary> </indexterm> - <literal><function>justify_days(<type>interval</type>)</function></literal> + <function>justify_days</function> </entry> - <entry><type>interval</type></entry> - <entry>Adjust interval so 30-day time periods are represented as months</entry> - <entry><literal>justify_days(interval '35 days')</literal></entry> - <entry><literal>1 mon 5 days</literal></entry> + <entry spanname="sig"><function>justify_days</function>(<type>interval</type>) + &returns; <type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Adjust interval so 30-day time periods are represented as months</entry> + </row> + <row> + <entry spanname="example"><literal>justify_days(interval '35 days')</literal></entry> + <entry spanname="exresult"><literal>1 mon 5 days</literal></entry> </row> <row> - <entry> + <entry spanname="name" morerows="2"> <indexterm> <primary>justify_hours</primary> </indexterm> - <literal><function>justify_hours(<type>interval</type>)</function></literal> + <function>justify_hours</function> </entry> - <entry><type>interval</type></entry> - <entry>Adjust interval so 24-hour time periods are represented as days</entry> - <entry><literal>justify_hours(interval '27 hours')</literal></entry> - <entry><literal>1 day 03:00:00</literal></entry> + <entry spanname="sig"><function>justify_hours</function>(<type>interval</type>) + &returns; <type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Adjust interval so 24-hour time periods are represented as days</entry> + </row> + <row> + <entry spanname="example"><literal>justify_hours(interval '27 hours')</literal></entry> + <entry spanname="exresult"><literal>1 day 03:00:00</literal></entry> </row> <row> - <entry> + <entry spanname="name" morerows="2"> <indexterm> <primary>justify_interval</primary> </indexterm> - <literal><function>justify_interval(<type>interval</type>)</function></literal> + <function>justify_interval</function> </entry> - <entry><type>interval</type></entry> - <entry>Adjust interval using <function>justify_days</function> and <function>justify_hours</function>, with additionalsign adjustments</entry> - <entry><literal>justify_interval(interval '1 mon -1 hour')</literal></entry> - <entry><literal>29 days 23:00:00</literal></entry> + <entry spanname="sig"><function>justify_interval</function>(<type>interval</type>) + &returns; <type>interval</type></entry> + </row> + <row> + <entry spanname="desc">Adjust interval using <function>justify_days</function> and <function>justify_hours</function>,with additional sign adjustments</entry> + </row> + <row> + <entry spanname="example"><literal>justify_interval(&break;interval '1 mon -1 hour')</literal></entry> + <entry spanname="exresult"><literal>29 days 23:00:00</literal></entry> </row> <row> - <entry> + <entry spanname="name" morerows="2"> <indexterm> <primary>localtime</primary> </indexterm> - <literal><function>localtime</function></literal> + <function>localtime</function> </entry> - <entry><type>time</type></entry> - <entry>Current time of day; + <entry spanname="sig"><function>localtime</function> + &returns; <type>time</type></entry> + </row> + <row> + <entry spanname="desc">Current time of day; see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>localtime</literal></entry> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="name" morerows="2"> <indexterm> <primary>localtimestamp</primary> </indexterm> - <literal><function>localtimestamp</function></literal> + <function>localtimestamp</function> </entry> - <entry><type>timestamp</type></entry> - <entry>Current date and time (start of current transaction); + <entry spanname="sig"><function>localtimestamp</function> + &returns; <type>timestamp</type></entry> + </row> + <row> + <entry spanname="desc">Current date and time (start of current transaction); see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>localtimestamp</literal></entry> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="name" morerows="2"> <indexterm> <primary>make_date</primary> </indexterm> - <literal> - <function> - make_date(<parameter>year</parameter> <type>int</type>, - <parameter>month</parameter> <type>int</type>, - <parameter>day</parameter> <type>int</type>) - </function> - </literal> + <function>make_date</function> </entry> - <entry><type>date</type></entry> - <entry> + <entry spanname="sig"><function>make_date</function>(<parameter>year</parameter> <type>int</type>, + <parameter>month</parameter> <type>int</type>, + <parameter>day</parameter> <type>int</type>) + &returns; <type>date</type></entry> + </row> + <row> + <entry spanname="desc"> Create date from year, month and day fields </entry> - <entry><literal>make_date(2013, 7, 15)</literal></entry> - <entry><literal>2013-07-15</literal></entry> + </row> + <row> + <entry spanname="example"><literal>make_date(2013, 7, 15)</literal></entry> + <entry spanname="exresult"><literal>2013-07-15</literal></entry> </row> <row> - <entry> - <indexterm> + <entry spanname="name" morerows="2"><indexterm> <primary>make_interval</primary> </indexterm> - <literal> - <function> - make_interval(<parameter>years</parameter> <type>int</type> DEFAULT 0, - <parameter>months</parameter> <type>int</type> DEFAULT 0, - <parameter>weeks</parameter> <type>int</type> DEFAULT 0, - <parameter>days</parameter> <type>int</type> DEFAULT 0, - <parameter>hours</parameter> <type>int</type> DEFAULT 0, - <parameter>mins</parameter> <type>int</type> DEFAULT 0, - <parameter>secs</parameter> <type>double precision</type> DEFAULT 0.0) - </function> - </literal> + <function>make_interval</function> </entry> - <entry><type>interval</type></entry> - <entry> + <entry spanname="sig"><function>make_interval</function>(<optional> <parameter>year</parameter> <type>int</type> + <optional>, <parameter>month</parameter> <type>int</type> + <optional>, <parameter>week</parameter> <type>int</type> + <optional>, <parameter>day</parameter> <type>int</type> + <optional>, <parameter>hour</parameter> <type>int</type> + <optional>, <parameter>min</parameter> <type>int</type> + <optional>, <parameter>sec</parameter> <type>double precision</type> + </optional></optional></optional></optional></optional></optional></optional>) + &returns; <type>interval</type></entry> + </row> + <row> + <entry spanname="desc"> Create interval from years, months, weeks, days, hours, minutes and - seconds fields + seconds fields, each of which can default to zero </entry> - <entry><literal>make_interval(days => 10)</literal></entry> - <entry><literal>10 days</literal></entry> + </row> + <row> + <entry spanname="example"><literal>make_interval(days => 10)</literal></entry> + <entry spanname="exresult"><literal>10 days</literal></entry> </row> <row> - <entry> + <entry spanname="name" morerows="2"> <indexterm> <primary>make_time</primary> </indexterm> - <literal> - <function> - make_time(<parameter>hour</parameter> <type>int</type>, - <parameter>min</parameter> <type>int</type>, - <parameter>sec</parameter> <type>double precision</type>) - </function> - </literal> + <function>make_time</function> </entry> - <entry><type>time</type></entry> - <entry> + <entry spanname="sig"><function>make_time</function>(<parameter>hour</parameter> <type>int</type>, + <parameter>min</parameter> <type>int</type>, + <parameter>sec</parameter> <type>double precision</type>) + &returns; <type>time</type></entry> + </row> + <row> + <entry spanname="desc"> Create time from hour, minute and seconds fields </entry> - <entry><literal>make_time(8, 15, 23.5)</literal></entry> - <entry><literal>08:15:23.5</literal></entry> + </row> + <row> + <entry spanname="example"><literal>make_time(8, 15, 23.5)</literal></entry> + <entry spanname="exresult"><literal>08:15:23.5</literal></entry> </row> <row> - <entry> + <entry spanname="name" morerows="2"> <indexterm> <primary>make_timestamp</primary> </indexterm> - <literal> - <function> - make_timestamp(<parameter>year</parameter> <type>int</type>, - <parameter>month</parameter> <type>int</type>, - <parameter>day</parameter> <type>int</type>, - <parameter>hour</parameter> <type>int</type>, - <parameter>min</parameter> <type>int</type>, - <parameter>sec</parameter> <type>double precision</type>) - </function> - </literal> + <function>make_timestamp</function> </entry> - <entry><type>timestamp</type></entry> - <entry> + <entry spanname="sig"><function>make_timestamp</function>(<parameter>year</parameter> <type>int</type>, + <parameter>month</parameter> <type>int</type>, + <parameter>day</parameter> <type>int</type>, + <parameter>hour</parameter> <type>int</type>, + <parameter>min</parameter> <type>int</type>, + <parameter>sec</parameter> <type>double precision</type>) + &returns; <type>timestamp</type></entry> + </row> + <row> + <entry spanname="desc"> Create timestamp from year, month, day, hour, minute and seconds fields </entry> - <entry><literal>make_timestamp(2013, 7, 15, 8, 15, 23.5)</literal></entry> - <entry><literal>2013-07-15 08:15:23.5</literal></entry> + </row> + <row> + <entry spanname="example"><literal>make_timestamp(2013, 7, 15, 8, 15, 23.5)</literal></entry> + <entry spanname="exresult"><literal>2013-07-15 08:15:23.5</literal></entry> </row> <row> - <entry> + <entry spanname="name" morerows="2"> <indexterm> <primary>make_timestamptz</primary> </indexterm> - <literal> - <function> - make_timestamptz(<parameter>year</parameter> <type>int</type>, - <parameter>month</parameter> <type>int</type>, - <parameter>day</parameter> <type>int</type>, - <parameter>hour</parameter> <type>int</type>, - <parameter>min</parameter> <type>int</type>, - <parameter>sec</parameter> <type>double precision</type>, - <optional> <parameter>timezone</parameter> <type>text</type> </optional>) - </function> - </literal> + <function>make_timestamptz</function> </entry> - <entry><type>timestamp with time zone</type></entry> - <entry> + <entry spanname="sig"><function>make_timestamptz</function>(<parameter>year</parameter> <type>int</type>, + <parameter>month</parameter> <type>int</type>, + <parameter>day</parameter> <type>int</type>, + <parameter>hour</parameter> <type>int</type>, + <parameter>min</parameter> <type>int</type>, + <parameter>sec</parameter> <type>double precision</type> + <optional>, <parameter>timezone</parameter> <type>text</type> </optional>) + &returns; <type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc"> Create timestamp with time zone from year, month, day, hour, minute and seconds fields; if <parameter>timezone</parameter> is not specified, the current time zone is used </entry> - <entry><literal>make_timestamptz(2013, 7, 15, 8, 15, 23.5)</literal></entry> - <entry><literal>2013-07-15 08:15:23.5+01</literal></entry> + </row> + <row> + <entry spanname="example"><literal>make_timestamptz(2013, 7, 15, 8, 15, 23.5)</literal></entry> + <entry spanname="exresult"><literal>2013-07-15 08:15:23.5+01</literal></entry> </row> <row> - <entry> + <entry spanname="name" morerows="2"> <indexterm> <primary>now</primary> </indexterm> - <literal><function>now()</function></literal> + <function>now</function> </entry> - <entry><type>timestamp with time zone</type></entry> - <entry>Current date and time (start of current transaction); + <entry spanname="sig"><function>now</function>() + &returns; <type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Current date and time (start of current transaction); see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>now()</literal></entry> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="name" morerows="2"> <indexterm> <primary>statement_timestamp</primary> </indexterm> - <literal><function>statement_timestamp()</function></literal> + <function>statement_timestamp</function> </entry> - <entry><type>timestamp with time zone</type></entry> - <entry>Current date and time (start of current statement); + <entry spanname="sig"><function>statement_timestamp</function>() + &returns; <type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Current date and time (start of current statement); see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>statement_timestamp()</literal></entry> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="name" morerows="2"> <indexterm> <primary>timeofday</primary> </indexterm> - <literal><function>timeofday()</function></literal> + <function>timeofday</function> </entry> - <entry><type>text</type></entry> - <entry>Current date and time + <entry spanname="sig"><function>timeofday</function>() + &returns; <type>text</type></entry> + </row> + <row> + <entry spanname="desc">Current date and time (like <function>clock_timestamp</function>, but as a <type>text</type> string); see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> + </row> + <row> + <entry spanname="example"><literal>timeofday()</literal></entry> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> </row> <row> - <entry> + <entry spanname="name" morerows="2"> <indexterm> <primary>transaction_timestamp</primary> </indexterm> - <literal><function>transaction_timestamp()</function></literal> + <function>transaction_timestamp</function> </entry> - <entry><type>timestamp with time zone</type></entry> - <entry>Current date and time (start of current transaction); + <entry spanname="sig"><function>transaction_timestamp</function>() + &returns; <type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Current date and time (start of current transaction); see <xref linkend="functions-datetime-current"/> </entry> - <entry></entry> - <entry></entry> </row> <row> - <entry> + <entry spanname="example"><literal>transaction_&break;timestamp()</literal></entry> + <entry spanname="exresult"><replaceable>variable</replaceable></entry> + </row> + <row> + <entry spanname="name" morerows="2"> <indexterm> <primary>to_timestamp</primary> </indexterm> - <literal><function>to_timestamp(<type>double precision</type>)</function></literal> + <function>to_timestamp</function> </entry> - <entry><type>timestamp with time zone</type></entry> - <entry>Convert Unix epoch (seconds since 1970-01-01 00:00:00+00) to + <entry spanname="sig"><function>to_timestamp</function>(<type>double precision</type>) + &returns; <type>timestamp with time zone</type></entry> + </row> + <row> + <entry spanname="desc">Convert Unix epoch (seconds since 1970-01-01 00:00:00+00) to timestamp</entry> - <entry><literal>to_timestamp(1284352323)</literal></entry> - <entry><literal>2010-09-13 04:32:03+00</literal></entry> + </row> + <row> + <entry spanname="example"><literal>to_timestamp(&break;1284352323)</literal></entry> + <entry spanname="exresult"><literal>2010-09-13 04:32:03+00</literal></entry> </row> </tbody> </tgroup> @@ -8236,52 +8508,83 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple <table id="functions-enum-table"> <title>Enum Support Functions</title> - <tgroup cols="4"> + <tgroup cols="3"> + <colspec colnum="1" colname="col1" colwidth="0.5*"/> + <colspec colnum="2" colname="col2" colwidth="1*"/> + <colspec colnum="3" colname="col3" colwidth="1*"/> + <spanspec spanname="name" namest="col1" nameend="col1" align="left"/> + <spanspec spanname="sig" namest="col2" nameend="col3" align="left"/> + <spanspec spanname="desc" namest="col2" nameend="col3" align="left"/> + <spanspec spanname="example" namest="col2" nameend="col2" align="left"/> + <spanspec spanname="exresult" namest="col3" nameend="col3" align="left"/> <thead> <row> - <entry>Function</entry> - <entry>Description</entry> - <entry>Example</entry> - <entry>Example Result</entry> + <entry spanname="name" align="center" morerows="2">Function</entry> + <entry spanname="sig" align="center">Signature</entry> + </row> + <row> + <entry spanname="desc" align="center">Description</entry> + </row> + <row> + <entry spanname="example" align="center">Example</entry> + <entry spanname="exresult" align="center">Example Result</entry> </row> </thead> <tbody> <row> - <entry> - <indexterm> - <primary>enum_first</primary> - </indexterm> - <literal>enum_first(anyenum)</literal> + <entry spanname="name" morerows="2"> + <indexterm> + <primary>enum_first</primary> + </indexterm> + <function>enum_first</function> </entry> - <entry>Returns the first value of the input enum type</entry> - <entry><literal>enum_first(null::rainbow)</literal></entry> - <entry><literal>red</literal></entry> + <entry spanname="sig"><function>enum_first</function>(<type>anyenum</type>) &returns; <type>anyenum</type></entry> </row> <row> - <entry> - <indexterm> - <primary>enum_last</primary> - </indexterm> - <literal>enum_last(anyenum)</literal> + <entry spanname="desc">Returns the first value of the input enum type</entry> + </row> + <row> + <entry spanname="example"><literal>enum_first(&break;null::rainbow)</literal></entry> + <entry spanname="exresult"><literal>red</literal></entry> + </row> + <row> + <entry spanname="name" morerows="2"> + <indexterm> + <primary>enum_last</primary> + </indexterm> + <function>enum_last</function> </entry> - <entry>Returns the last value of the input enum type</entry> - <entry><literal>enum_last(null::rainbow)</literal></entry> - <entry><literal>purple</literal></entry> + <entry spanname="sig"><function>enum_last</function>(<type>anyenum</type>) &returns; <type>anyenum</type></entry> </row> <row> - <entry> - <indexterm> - <primary>enum_range</primary> - </indexterm> - <literal>enum_range(anyenum)</literal> + <entry spanname="desc">Returns the last value of the input enum type</entry> + </row> + <row> + <entry spanname="example"><literal>enum_last(&break;null::rainbow)</literal></entry> + <entry spanname="exresult"><literal>purple</literal></entry> + </row> + <row> + <entry spanname="name" morerows="2"> + <indexterm> + <primary>enum_range</primary> + </indexterm> + <function>enum_range</function> </entry> - <entry>Returns all values of the input enum type in an ordered array</entry> - <entry><literal>enum_range(null::rainbow)</literal></entry> - <entry><literal>{red,orange,yellow,green,blue,purple}</literal></entry> + <entry spanname="sig"><function>enum_range</function>(<type>anyenum</type>) &returns; <type>anyarray</type></entry> + </row> + <row> + <entry spanname="desc">Returns all values of the input enum type in an ordered array</entry> + </row> + <row> + <entry spanname="example"><literal>enum_range(&break;null::rainbow)</literal></entry> + <entry spanname="exresult"><literal>{red,orange,yellow,&break;green,blue,purple}</literal></entry> + </row> + <row> + <entry spanname="name" morerows="4"><function>enum_range</function></entry> + <entry spanname="sig"><function>enum_range</function>(<type>anyenum</type>, <type>anyenum</type>) &returns; <type>anyarray</type></entry> </row> <row> - <entry morerows="2"><literal>enum_range(anyenum, anyenum)</literal></entry> - <entry morerows="2"> + <entry spanname="desc"> Returns the range between the two given enum values, as an ordered array. The values must be from the same enum type. If the first parameter is null, the result will start with the first value of @@ -8289,16 +8592,18 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple If the second parameter is null, the result will end with the last value of the enum type. </entry> - <entry><literal>enum_range('orange'::rainbow, 'green'::rainbow)</literal></entry> - <entry><literal>{orange,yellow,green}</literal></entry> </row> <row> - <entry><literal>enum_range(NULL, 'green'::rainbow)</literal></entry> - <entry><literal>{red,orange,yellow,green}</literal></entry> + <entry spanname="example"><literal>enum_range(&break;'orange'::rainbow, 'green'::rainbow)</literal></entry> + <entry spanname="exresult"><literal>{orange,yellow,green}</literal></entry> + </row> + <row> + <entry spanname="example"><literal>enum_range(NULL, 'green'::rainbow)</literal></entry> + <entry spanname="exresult"><literal>{red,orange,yellow,&break;green}</literal></entry> </row> <row> - <entry><literal>enum_range('orange'::rainbow, NULL)</literal></entry> - <entry><literal>{orange,yellow,green,blue,purple}</literal></entry> + <entry spanname="example"><literal>enum_range(&break;'orange'::rainbow, NULL)</literal></entry> + <entry spanname="exresult"><literal>{orange,yellow,green,&break;blue,purple}</literal></entry> </row> </tbody> </tgroup> diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml index e59cba7..bfe5661 100644 --- a/doc/src/sgml/postgres.sgml +++ b/doc/src/sgml/postgres.sgml @@ -11,6 +11,12 @@ <!ENTITY reference SYSTEM "reference.sgml"> +<!-- zero-width space; use this to allow line breaks within table cells --> +<!ENTITY break ""> + +<!-- right arrow; use this to introduce function/operator return types --> +<!ENTITY returns "→"> + ]> <book id="postgres">
Attachment
12.02.2020 23:58, Tom Lane wrote: > Alexander Lakhin <exclusion@gmail.com> writes: >> Please look at a less invasive approach that we use at Postgres Pro for >> some time (mainly for improving the translated documentation, but it >> works for the original one too). The idea is to add zero-width spaces >> after/before some chars ('(', ',', '[', etc) to let fop split lines >> where desired. It has one disadvantage - it's not search-friendly >> (though maybe that is application-dependent). >> But if it's feasible, I think this approach can at least complement a >> manual tables reformatting. Decreasing a font size in the tables seems >> appropriate to me too. > Hmm, interesting proposal. I experimented and verified that injecting > zero-width space () does allow line breaking to occur in both > HTML and PDF output, so this could be a route to improving the situation > for overlength example texts. I do not think I like the idea of > automatically injecting tons of them, though. As you say, it might > hinder searching; and it would allow some silly breaks; and there are > cases where it still wouldn't find a break, such as the examples for > sha256() et al. I'd be happier about manually inserting breaks just > in the places we really need them. To keep the source readable, I'd > want to write something like "&zwsp;" not a numeric entity code, > but it looks like we can define custom entities if we want. Yes, I was starting with manual &zwsp; insertions into the translation, but later I reduced such insertions just to several dozens. (For example, we still have "3.1415926535&zwsp;8979323846" in the translation.) The main issue of the manual approach was that I needed to recheck that zwsp placement on updates, and I can't see where it's desired until I generate pdf. Fortunately, fop prints warning like that: [WARN] FOUserAgent - The contents of fo:block line 2 exceed the available area in the inline-progression direction by 22725 millipoints. (See position 127769:983) It's not very user-friendly, but still useful when we have a pair or two of them. (For now, I see 559 such warnings in REL_12_STABLE.) Second issue is that the placement can depend on the page size and in fact most of that zwsps are not needed for html or other formats (moreover, some formats can require different placements (if we're not just implementing some common rules)). Third (minor) issue is with translation - when I will see some break in the English source, e.g. "split_part('abc~@~def&zwsp;~@~ghi', '~@~', 2)", should I leave the break in the same place, or it's better to move it because adjacent text has different length and the table columns have different width? For me this approach expresses a belief that the line breaking rules should be slightly different in our context. For example, having line break after an opening bracket is feasible and common in function calls and declarations. Maybe the rules in the proposed xslt could be improved/restricted, but I think that if fop would allow us to enable an imaginary 'programming language line breaking rules' mode, we would use it for our tables (some or all). Maybe some of the rules can be implemented explicitly in the DocBook source, just to reduce tons of zwsp in the generated output, or the "fo:table-cell/fo:block//text()" condition can be improved to filter some (text-only?) tables out, but I think that the idea of our specific line breaking rules could work. Best regards, Alexander
On 2020-Feb-13, Alexander Lakhin wrote: > Yes, I was starting with manual &zwsp; insertions into the translation, > but later I reduced such insertions just to several dozens. (For > example, we still have "3.1415926535&zwsp;8979323846" in the translation.) > The main issue of the manual approach was that I needed to recheck that > zwsp placement on updates, and I can't see where it's desired until I > generate pdf. Fortunately, fop prints warning like that: > [WARN] FOUserAgent - The contents of fo:block line 2 exceed the > available area in the inline-progression direction by 22725 millipoints. > (See position 127769:983) > It's not very user-friendly, but still useful when we have a pair or two > of them. It seems to me that a productive way forward would be to fix the layout to make these warning disappear. Then it will be relatively easy to find where to fix, if new ones appear. Now I suppose you're complaining about the "position 127769:983" part of the error message which tells you with zero clarity where the problem is. Maybe what we need is to figure out what the numbers mean, and how to use them; for example if they are byte offsets into the file, then it should be possible to tell your editor to go to that byte in the complete XML file. > Second issue is that the placement can depend on the page size and in > fact most of that zwsps are not needed for html or other formats > (moreover, some formats can require different placements (if we're not > just implementing some common rules)). I suppose A4 page size is going to show slightly different warnings than Letter page size in the PDF output. Perhaps we can say that we only care about warnings in one of them, for these purposes. Having to touch 500+ places does not sound very appetizing, for sure. > Third (minor) issue is with translation - when I will see some break in > the English source, e.g. "split_part('abc~@~def&zwsp;~@~ghi', '~@~', > 2)", should I leave the break in the same place, or it's better to move > it because adjacent text has different length and the table columns have > different width? If the English version is warning-clean, then it should be possible to keep the zwsps in the same location in the translation, and then tweak the translation according to any new warnings that appear there. My guess is that the majority of zwsps are going to want to stay in the same place. > Maybe some of the rules can be implemented explicitly in the DocBook > source, just to reduce tons of zwsp in the generated output, or the > "fo:table-cell/fo:block//text()" condition can be improved to filter > some (text-only?) tables out, but I think that the idea of our specific > line breaking rules could work. Maybe we can mark-up specific table cells/columns as being subject to the special line breaking rules. -- Álvaro Herrera https://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
Hello Alvaro,
14.02.2020 23:16, Alvaro Herrera wrote:
14.02.2020 23:16, Alvaro Herrera wrote:
I'm not complaining about the cryptic position of the problems, I'm concerned with their number.On 2020-Feb-13, Alexander Lakhin wrote:Yes, I was starting with manual &zwsp; insertions into the translation, but later I reduced such insertions just to several dozens. (For example, we still have "3.1415926535&zwsp;8979323846" in the translation.) The main issue of the manual approach was that I needed to recheck that zwsp placement on updates, and I can't see where it's desired until I generate pdf. Fortunately, fop prints warning like that: [WARN] FOUserAgent - The contents of fo:block line 2 exceed the available area in the inline-progression direction by 22725 millipoints. (See position 127769:983) It's not very user-friendly, but still useful when we have a pair or two of them.It seems to me that a productive way forward would be to fix the layout to make these warning disappear. Then it will be relatively easy to find where to fix, if new ones appear. Now I suppose you're complaining about the "position 127769:983" part of the error message which tells you with zero clarity where the problem is. Maybe what we need is to figure out what the numbers mean, and how to use them; for example if they are byte offsets into the file, then it should be possible to tell your editor to go to that byte in the complete XML file.
The position is specified as {line_number}:{character_postition} in postgres-*.fo (not in the DocBook source).
For example, when performing `make postgres-A4.pdf` on REL_12_STABLE I get:
[WARN] FOUserAgent - The contents of fo:block line 1 exceed the available area in the inline-progression direction by more than 50 points. (See position 28808:374)
To find an exact problematic text you can look at the specified line(s) of postgres-A4.fo:
$ sed -n '28808,28811p' postgres-A4.fo
<fo:block id="id-1.5.13.4.7.12.1" wrap-option="wrap" text-align="start" space-before.minimum="0.8em" space-before.optimum="1em" space-before.maximum="1.2em" space-after.minimum="0.8em" space-after.optimum="1em" space-after.maximum="1.2em" hyphenate="false" white-space-collapse="false" white-space-treatment="preserve" linefeed-treatment="preserve" font-family="monospace">
EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 100;
Searching this text in pdf gets you to page 467 where you can see a long line of '---' going of the page...
Yes, that's why I consider this as minor issue, but some kind of an automatic solution can eliminate it at all.Third (minor) issue is with translation - when I will see some break in the English source, e.g. "split_part('abc~@~def&zwsp;~@~ghi', '~@~', 2)", should I leave the break in the same place, or it's better to move it because adjacent text has different length and the table columns have different width?If the English version is warning-clean, then it should be possible to keep the zwsps in the same location in the translation, and then tweak the translation according to any new warnings that appear there. My guess is that the majority of zwsps are going to want to stay in the same place.
Things made complicated by the xslt preprocessor, because you can't see Docbook tags and attributes on a FOP level, but I can explore possible resolutions if we choose to go this way.Maybe some of the rules can be implemented explicitly in the DocBook source, just to reduce tons of zwsp in the generated output, or the "fo:table-cell/fo:block//text()" condition can be improved to filter some (text-only?) tables out, but I think that the idea of our specific line breaking rules could work.Maybe we can mark-up specific table cells/columns as being subject to the special line breaking rules.
Best regards,
Alexander
Alvaro Herrera <alvherre@2ndquadrant.com> writes: > On 2020-Feb-13, Alexander Lakhin wrote: >> Third (minor) issue is with translation - when I will see some break in >> the English source, e.g. "split_part('abc~@~def&zwsp;~@~ghi', '~@~', >> 2)", should I leave the break in the same place, or it's better to move >> it because adjacent text has different length and the table columns have >> different width? > If the English version is warning-clean, then it should be possible to > keep the zwsps in the same location in the translation, and then tweak > the translation according to any new warnings that appear there. > My guess is that the majority of zwsps are going to want to stay in the > same place. So far as I've seen, the majority of places where we'll still need to insert break opportunities are in examples and example results, which don't seem like they'd be subject to translation. I'm really not eager to turn loose an automatic-zwsp-inserter for a problem that might be mostly hypothetical once we have a more forgiving table layout in place. regards, tom lane
I wrote: > One problem with the rightarrow idea is that it's not rendering quite > right for me: it looks great in HTML, but in PDF it comes out flush > with the baseline, as you can see in the screenshot. Hopefully > there's a way to fix that that we can hide in the custom entity ... > but I have no idea how. I poked at this a little bit, and found that I could get a pretty decent-looking result if I hacked the .fo file to contain "<fo:inline baseline-shift="10%">→</fo:inline>" rather than a bare right arrow. (See attached screenshot, wherein the last rightarrow was fixed this way but the others weren't.) However, I do not have much of a clue as to how such a fix might be injected into our stylesheets --- anybody have a suggestion? regards, tom lane
Attachment
Hello Tom, > 16.02.2020 23:07, Tom Lane wrote: > > > I poked at this a little bit, and found that I could get a pretty > decent-looking result if I hacked the .fo file to contain > "<fo:inline baseline-shift="10%">→</fo:inline>" rather than a bare > right arrow. (See attached screenshot, wherein the last rightarrow > was fixed this way but the others weren't.) However, I do not > have much of a clue as to how such a fix might be injected into > our stylesheets --- anybody have a suggestion? Please look at the XSLT template for processing .fo before calling fop. Maybe this can be done with just the existing stylesheet-fo.xsl, I'll try to research this later. Best regards, Alexander
Attachment
17.02.2020 00:21, Alexander Lakhin wrote: > Hello Tom, >> 16.02.2020 23:07, Tom Lane wrote: >> >> >> I poked at this a little bit, and found that I could get a pretty >> decent-looking result if I hacked the .fo file to contain >> "<fo:inline baseline-shift="10%">→</fo:inline>" rather than a bare >> right arrow. (See attached screenshot, wherein the last rightarrow >> was fixed this way but the others weren't.) However, I do not >> have much of a clue as to how such a fix might be injected into >> our stylesheets --- anybody have a suggestion? > Please look at the XSLT template for processing .fo before calling fop. > Maybe this can be done with just the existing stylesheet-fo.xsl, I'll > try to research this later. I've managed to simplify the patch a little by incorporating those templates in stylesheet-fo.xsl. Maybe it's better to use the same formatting as in the docbook xsl template (see docbook/stylesheet/docbook-xsl/xhtml-1_1/inline.xsl). There "$menuchoice.menu.separator" is enclosed in <fo:inline font-size=".75em" font-family="{$symbol.font.family}">...</fo:inline> and you can see the effect on page 536 (IPC parameters can be set in the System Administration Manager (SAM) under Kernel Configu- ration → Configurable Parameters.) Yet another possibility is to use the docbook tags: <funcdef><function>func()</function> <returnvalue>int</returnvalue></funcdef>. Then we can define the desired formatting for such markup (similar to <menuchoice><guimenu>...</guimenu><guimenuitem>...</guimenuitem></menuchoice>). Best regards, Alexander
Attachment
I set this idea aside during the final v13 commitfest, but I figure that it's fine to work on documentation improvements during feature freeze, so I'm going to try to push it forward over the next few weeks. Barring objections, I want to commit more or less what I posted at [1], verify that it looks decent on the website, and then incrementally convert the rest of our function/operator tables to the new style. It's too big a job to get done in one commit, but a table or two at a time seems like a reasonable approach. After the table format conversion is finished we can take a look at how much of a bad-line-breaks issue we still have, and decide what to do about that. First though, we need to nail down exactly what markup to use. Alexander Lakhin <exclusion@gmail.com> writes: > Maybe it's better to use the same formatting as in the docbook xsl > template (see docbook/stylesheet/docbook-xsl/xhtml-1_1/inline.xsl). > There "$menuchoice.menu.separator" is enclosed in <fo:inline > font-size=".75em" font-family="{$symbol.font.family}">...</fo:inline> > and you can see the effect on page 536 (IPC parameters can be set in the > System Administration Manager (SAM) under Kernel Configu- > ration → Configurable Parameters.) Yeah, I see that that uses a right-arrow and it looks quite decent in both HTML and PDF renderings. So we ought to borrow those markup details rather than solving the problem from scratch. > Yet another possibility is to use the docbook tags: > <funcdef><function>func()</function> > <returnvalue>int</returnvalue></funcdef>. > Then we can define the desired formatting for such markup (similar to > <menuchoice><guimenu>...</guimenu><guimenuitem>...</guimenuitem></menuchoice>). I looked into this. It appears that <funcdef> is fairly tightly tied to C function declaration syntax, plus it sounds like it might get deprecated in future docbook versions. So I don't want to use that. But we could use <returnvalue> which seems to be defined independently of <funcdef>, and isn't being used in our docs at present. I found by experimentation that this doesn't work: <returnvalue><type>date</type></returnvalue> (it complains that these two tag types can't be nested); but this does: <returnvalue>date</returnvalue> So if we can get <returnvalue> to both insert a right arrow and switch the font to match <type>'s choice, this would work more or less decently, and it's probably cleaner than the bare-entity-reference approach I posted before. I don't have the XSL skills to get that to work though. Anyone want to help out? regards, tom lane [1] https://www.postgresql.org/message-id/23574.1581555393%40sss.pgh.pa.us
On Sat, Apr 11, 2020 at 4:51 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
I set this idea aside during the final v13 commitfest, but I figure that
it's fine to work on documentation improvements during feature freeze,
so I'm going to try to push it forward over the next few weeks.
If it's ok to work on doc patches during the feature freeze, and if we're already tweaking function documentation, would it be possible to add in anchor ids to function definitions so that we could reference specific functions (or rather the family of functions that share a name like this: https://www.postgresql.org/docs/devel/functions-datetime.html#FUNCTION-DATE-PART or similar. I tried it out just now, and the anchoring works, but there's no obvious place to acquire the anchored link, so presumably we'd anchor-ize the function name itself.
Corey Huinker <corey.huinker@gmail.com> writes: > If it's ok to work on doc patches during the feature freeze, and if we're > already tweaking function documentation, would it be possible to add in > anchor ids to function definitions so that we could reference specific > functions (or rather the family of functions that share a name like this: > https://www.postgresql.org/docs/devel/functions-datetime.html#FUNCTION-DATE-PART > or similar. I tried it out just now, and the anchoring works, but there's > no obvious place to acquire the anchored link, so presumably we'd > anchor-ize the function name itself. Don't have a strong opinion about that, but it'd sure be a lot of new anchors. Is that going to be a problem for the docs toolchain? If the anchors are attached to individual function names rather than sections or paragraphs, do they actually work well as link references? (I'm particularly wondering how an <xref> would render.) regards, tom lane
On Sat, Apr 11, 2020 at 6:41 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
Corey Huinker <corey.huinker@gmail.com> writes:
> If it's ok to work on doc patches during the feature freeze, and if we're
> already tweaking function documentation, would it be possible to add in
> anchor ids to function definitions so that we could reference specific
> functions (or rather the family of functions that share a name like this:
> https://www.postgresql.org/docs/devel/functions-datetime.html#FUNCTION-DATE-PART
> or similar. I tried it out just now, and the anchoring works, but there's
> no obvious place to acquire the anchored link, so presumably we'd
> anchor-ize the function name itself.
Don't have a strong opinion about that, but it'd sure be a lot of new
anchors.
True, but it'd would be a lot better than pointing a person to a page that has 20+ functions defined on it.
Is that going to be a problem for the docs toolchain? If
the anchors are attached to individual function names rather than
sections or paragraphs, do they actually work well as link references?
(I'm particularly wondering how an <xref> would render.)
So I can't speak to any scalability issues for adding a bunch of refs, but I did try this out for justify_days() (diff attached) and here's what I found:
* <link linkend="function-justify-days">justify_days</link>
This made a link, in the same font as any other link ref.
* <xref linkend="function-justify-days"/>
This made a link that looks exactly like the previous one, with the text "justify_days", so if we're fine with the font change, we could use that
* <link linkend="function-justify-days"><function>justify_days</function></link>
This made the link we want in the function font.
The docbook spec doesn't allow an xref inside a function tag, and no tags at all can be inside an xref.
* <link linkend="function-justify-days">justify_days</link>
This made a link, in the same font as any other link ref.
* <xref linkend="function-justify-days"/>
This made a link that looks exactly like the previous one, with the text "justify_days", so if we're fine with the font change, we could use that
* <link linkend="function-justify-days"><function>justify_days</function></link>
This made the link we want in the function font.
The docbook spec doesn't allow an xref inside a function tag, and no tags at all can be inside an xref.
Attachment
On 11.04.20 22:51, Tom Lane wrote:
Yet another possibility is to use the docbook tags: <funcdef><function>func()</function> <returnvalue>int</returnvalue></funcdef>. Then we can define the desired formatting for such markup (similar to <menuchoice><guimenu>...</guimenu><guimenuitem>...</guimenuitem></menuchoice>).I looked into this. It appears that <funcdef> is fairly tightly tied to C function declaration syntax, plus it sounds like it might get deprecated in future docbook versions.
funcsynopsis, funcdef, function, ... keeps valid in Docbook 5, see: https://tdg.docbook.org/tdg/5.1/funcsynopsis.html . There is even an option to distinguish between K&R and ANSI style during rendering: <?dbhtml funcsynopsis-style='kr'?>
Kind regards, Jürgen Purtz
I wrote: > So if we can get <returnvalue> to both insert a right arrow and switch the > font to match <type>'s choice, this would work more or less decently, and > it's probably cleaner than the bare-entity-reference approach I posted > before. I don't have the XSL skills to get that to work though. > Anyone want to help out? I educated myself a teensy bit about XSL, and unless I'm missing something, this is really pretty darn trivial; the attached seems to do the trick. I experimented with the markup from <guimenuitem> and decided that I didn't like their choice of a smaller font size in this context; it looks better to me to leave the arrow full-size. The important thing to learn from that precedent seems to be that we have to specify the font correctly, as indeed is mentioned in the docbook documentation. So it seems to work well to just use <fo:inline font-family="{$symbol.font.family}">→ </fo:inline> (The extra space seems to be necessary, else the arrow ends up adjacent to the type name.) So I'm pretty happy with this implementation and will push forward. regards, tom lane diff --git a/doc/src/sgml/stylesheet-common.xsl b/doc/src/sgml/stylesheet-common.xsl index e148c90..5936d9a 100644 --- a/doc/src/sgml/stylesheet-common.xsl +++ b/doc/src/sgml/stylesheet-common.xsl @@ -49,6 +49,11 @@ <xsl:call-template name="inline.charseq"/> </xsl:template> +<xsl:template match="returnvalue"> + → + <xsl:call-template name="inline.monoseq"/> +</xsl:template> + <xsl:template match="structfield"> <xsl:call-template name="inline.monoseq"/> </xsl:template> diff --git a/doc/src/sgml/stylesheet-fo.xsl b/doc/src/sgml/stylesheet-fo.xsl index ea75408..a3b6463 100644 --- a/doc/src/sgml/stylesheet-fo.xsl +++ b/doc/src/sgml/stylesheet-fo.xsl @@ -63,6 +63,12 @@ </fo:inline> </xsl:template> +<!-- overrides stylesheet-common.xsl --> +<xsl:template match="returnvalue"> + <fo:inline font-family="{$symbol.font.family}">→ </fo:inline> + <xsl:call-template name="inline.monoseq"/> +</xsl:template> + <!-- bug fix from <https://sourceforge.net/p/docbook/bugs/1360/#831b> --> <xsl:template match="varlistentry/term" mode="xref-to">
Hello Tom, 12.04.2020 20:33, Tom Lane wrote: > I wrote: >> So if we can get <returnvalue> to both insert a right arrow and switch the >> font to match <type>'s choice, this would work more or less decently, and >> it's probably cleaner than the bare-entity-reference approach I posted >> before. I don't have the XSL skills to get that to work though. >> Anyone want to help out? > I educated myself a teensy bit about XSL, and unless I'm missing > something, this is really pretty darn trivial; the attached seems > to do the trick. I've come to almost the same solution simultaneously. I think this should work for us. Best regards, Alexander
Alexander Lakhin <exclusion@gmail.com> writes: > 12.04.2020 20:33, Tom Lane wrote: >> I educated myself a teensy bit about XSL, and unless I'm missing >> something, this is really pretty darn trivial; the attached seems >> to do the trick. > I've come to almost the same solution simultaneously. I think this > should work for us. Thanks for looking at it! I did some more polishing on the first batch of tables and pushed it --- see what you think. regards, tom lane
Corey Huinker <corey.huinker@gmail.com> writes: > On Sat, Apr 11, 2020 at 6:41 PM Tom Lane <tgl@sss.pgh.pa.us> wrote: >> Is that going to be a problem for the docs toolchain? If >> the anchors are attached to individual function names rather than >> sections or paragraphs, do they actually work well as link references? >> (I'm particularly wondering how an <xref> would render.) > So I can't speak to any scalability issues for adding a bunch of refs, but > I did try this out for justify_days() (diff attached) and here's what I > found: > * <link linkend="function-justify-days">justify_days</link> > This made a link, in the same font as any other link ref. > * <xref linkend="function-justify-days"/> > This made a link that looks exactly like the previous one, with the text > "justify_days", so if we're fine with the font change, we could use that > * <link > linkend="function-justify-days"><function>justify_days</function></link> > This made the link we want in the function font. Hm. Attaching the link ID to an <indexterm> is an interesting hack. It makes me nervous, because it's not immediately obvious that that won't cause links to lead to someplace in the index. Still, it does seem to work the way we want in both HTML and PDF output, so maybe we can get away with it. We've previously found that attaching an ID to a <row> does *not* work, at least not in PDF --- see the existing attempts for function-encode and function-decode, which give rise to PDF build warnings and no functioning links. I checked just now and attaching the ID to the <entry> acts the same, so it seems it's <indexterm> or nothing. My inclination is to standardize on using <xref> for references and just accept the lack of a special font. It's not worth the notational pain to use both <link> and <function>, especially not in HTML output where links will probably get rendered specially anyway. We previously made the same tradeoff with respect to GUC variables, and I've not seen many complaints. (I experimented with putting <function> into the indexterm text, but that did not help.) I'd be a bit inclined to shorten the ID prefix to "func-", just in the interests of carpal tunnel avoidance. regards, tom lane
On Sun, Apr 12, 2020 at 8:38 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
Corey Huinker <corey.huinker@gmail.com> writes:
> On Sat, Apr 11, 2020 at 6:41 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
>> Is that going to be a problem for the docs toolchain? If
>> the anchors are attached to individual function names rather than
>> sections or paragraphs, do they actually work well as link references?
>> (I'm particularly wondering how an <xref> would render.)
> So I can't speak to any scalability issues for adding a bunch of refs, but
> I did try this out for justify_days() (diff attached) and here's what I
> found:
> * <link linkend="function-justify-days">justify_days</link>
> This made a link, in the same font as any other link ref.
> * <xref linkend="function-justify-days"/>
> This made a link that looks exactly like the previous one, with the text
> "justify_days", so if we're fine with the font change, we could use that
> * <link
> linkend="function-justify-days"><function>justify_days</function></link>
> This made the link we want in the function font.
Hm. Attaching the link ID to an <indexterm> is an interesting hack.
it worked for glossterms, I figured an indexterm is just another 'term.
My inclination is to standardize on using <xref> for references and
just accept the lack of a special font. It's not worth the notational
pain to use both <link> and <function>, especially not in HTML output
where links will probably get rendered specially anyway. We
previously made the same tradeoff with respect to GUC variables,
and I've not seen many complaints. (I experimented with putting
<function> into the indexterm text, but that did not help.)
I'd be a bit inclined to shorten the ID prefix to "func-", just
in the interests of carpal tunnel avoidance.
xref it is. I'll take a shot and scripting the necessary changes.
Corey Huinker <corey.huinker@gmail.com> writes: > On Sat, Apr 11, 2020 at 6:41 PM Tom Lane <tgl@sss.pgh.pa.us> wrote: >> Don't have a strong opinion about that, but it'd sure be a lot of new >> anchors. > So I can't speak to any scalability issues for adding a bunch of refs, I did a quick check by adding id tags to all 700-or-so <indexterm>s in func.sgml (don't get excited, it was a perl one-liner that just added random id strings). The runtime difference for building the HTML docs seems to be under 1%, and negligible for PDF output. So it looks like we don't have to worry about scalability of tagging all the functions. regards, tom lane
I did a quick check by adding id tags to all 700-or-so <indexterm>s in
func.sgml (don't get excited, it was a perl one-liner that just added
random id strings).
I did, actually, get excited for a second.
The runtime difference for building the HTML docs
seems to be under 1%, and negligible for PDF output. So it looks like
we don't have to worry about scalability of tagging all the functions.
Ok, so that's the function anchors.
So some references to functions are just the name, and xrefs will work fine for those.
I was thinking that there were references that included parameters, but I'm not finding any with actual parameter values, so at most we'd lose the "()" of a reference.
Assuming we want to make the anchors visible, we need a way for people to discover the anchors we've made, and my thought there is that we make the first definition a non-xref link to the indexterm just above it. Any thoughts on what the best way to do that is?
Corey Huinker <corey.huinker@gmail.com> writes: > I was thinking that there were references that included parameters, but I'm > not finding any with actual parameter values, so at most we'd lose the "()" > of a reference. We could possibly stick the parens into the indexterm text. Arguably that's an improvement on its own merits, since it'd become clearer which index entries are function names. If you don't want that, another idea is to put xreflabel options that include the parens into the indexterm tags. Or we can just standardize on not having parens, but personally I like them. Without parens, for clarity you really have to write "function <function>foo</function>" which is redundant-looking in the XML and hence easy to get wrong. > Assuming we want to make the anchors visible, we need a way for people to > discover the anchors we've made, and my thought there is that we make the > first definition a non-xref link to the indexterm just above it. Any > thoughts on what the best way to do that is? I'm not really buying into that as a requirement. For one thing, the anchor name will be 100% predictable. One thing that I noticed while playing with this last night is that even though <xref> or <link> links will take you right to the exact table entry, the index entries generated from the indexterms only point to the page. That seems pretty sad, why isn't it better? regards, tom lane
On Mon, Apr 13, 2020 at 12:28 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
Corey Huinker <corey.huinker@gmail.com> writes:
> I was thinking that there were references that included parameters, but I'm
> not finding any with actual parameter values, so at most we'd lose the "()"
> of a reference.
We could possibly stick the parens into the indexterm text. Arguably
that's an improvement on its own merits, since it'd become clearer which
index entries are function names. If you don't want that, another idea is
to put xreflabel options that include the parens into the indexterm tags.
Or we can just standardize on not having parens, but personally I like
them. Without parens, for clarity you really have to write "function
<function>foo</function>" which is redundant-looking in the XML and hence
easy to get wrong.
That makes sense to me. There may be some hope for the font via the xrefstyle attribute, but I'm not educated well enough on docbook to know for sure.
> Assuming we want to make the anchors visible, we need a way for people to
> discover the anchors we've made, and my thought there is that we make the
> first definition a non-xref link to the indexterm just above it. Any
> thoughts on what the best way to do that is?
I'm not really buying into that as a requirement. For one thing, the
anchor name will be 100% predictable.
The anchor name is deterministic (or I intend it to be) but the existence of the link is not predictable. So while having no visible link is fine for internal links which we create, I'm envisioning a not-very-experienced reader wanting to help an even-less-experienced person. If they find the date_part function, and they see that the word "date_part" is itself clickable, they'll probably click it once, see that it's a link, and send the less-experienced person the anchored link instead of the broader page link. They're very unlikely to try to forge their own anchor link in the hopes that it already exists.
One thing that I noticed while playing with this last night is that
even though <xref> or <link> links will take you right to the exact
table entry, the index entries generated from the indexterms only
point to the page. That seems pretty sad, why isn't it better?
As you've described it it does seem very odd, but maybe I'm just misunderstanding.
Corey Huinker <corey.huinker@gmail.com> writes: > On Mon, Apr 13, 2020 at 12:28 PM Tom Lane <tgl@sss.pgh.pa.us> wrote: >> I'm not really buying into that as a requirement. For one thing, the >> anchor name will be 100% predictable. > The anchor name is deterministic (or I intend it to be) but > the existence of the link is not predictable. So while having no visible > link is fine for internal links which we create, I'm envisioning a > not-very-experienced reader wanting to help an even-less-experienced > person. If they find the date_part function, and they see that the word > "date_part" is itself clickable, they'll probably click it once, see that > it's a link, and send the less-experienced person the anchored link instead > of the broader page link. They're very unlikely to try to forge their own > anchor link in the hopes that it already exists. Meh. I think people are going to think that a link that points at itself is pretty silly. Now, if the link appearing in the index were precise, people might copy that one and use it ... BTW, I just noticed that the way that the index is rendered on the website is beyond awful. The sub-items of an index entry are left-justified instead of being indented as they ought to be (and are, if you build the docs locally without using the website style). This makes it look like the sub-entries are main entries which is totally confusing. Can somebody fix that? regards, tom lane