Re: Relax requirement for INTO with SELECT in pl/pgsql

From: Pavel Stehule <pavel(dot)stehule(at)gmail(dot)com>
To: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>
Cc: Merlin Moncure <mmoncure(at)gmail(dot)com>, Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, Jim Nasby <Jim(dot)Nasby(at)bluetreble(dot)com>, PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org>, Peter Eisentraut <peter(dot)eisentraut(at)2ndquadrant(dot)com>
Subject: Re: Relax requirement for INTO with SELECT in pl/pgsql
Date: 2016-06-06 05:11:17
Message-ID: CAFj8pRDaf48eZ9L1Z8SqCPKiRvxqePeR+O-VeCY_RCCYr1=wjA@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

2016-06-05 5:45 GMT+02:00 David G. Johnston <david(dot)g(dot)johnston(at)gmail(dot)com>:

> On Tuesday, March 22, 2016, Merlin Moncure <mmoncure(at)gmail(dot)com> wrote:
>
>>
>> Anyways, here's the patch with documentation adjustments as promised.
>> I ended up keeping the 'without result' section because it contained
>> useful information about plan caching,
>>
>> merlin
>>
>> diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml
>> new file mode 100644
>> index 9786242..512eaa7
>> *** a/doc/src/sgml/plpgsql.sgml
>> --- b/doc/src/sgml/plpgsql.sgml
>> *************** my_record.user_id := 20;
>> *** 904,910 ****
>> <title>Executing a Command With No Result</title>
>>
>> <para>
>> ! For any SQL command that does not return rows, for example
>> <command>INSERT</> without a <literal>RETURNING</> clause, you can
>> execute the command within a <application>PL/pgSQL</application>
>> function
>> just by writing the command.
>> --- 904,910 ----
>> <title>Executing a Command With No Result</title>
>>
>> <para>
>> ! For any SQL command, for example
>> <command>INSERT</> without a <literal>RETURNING</> clause, you can
>> execute the command within a <application>PL/pgSQL</application>
>> function
>> just by writing the command.
>> *************** my_record.user_id := 20;
>
>
> This just seems odd...a bit broader approach here would be nice.
> Especially since now it's not the command that doesn't have a result but
> the user decision to not capture any result that may be present. Using
> insert returning for the example here is just, again, odd...
>
> Removing PERFORM requires a bit more reframing of the docs than you've
> done here; too much was influenced by its presence.
>
>
>> *** 925,972 ****
>> <xref linkend="plpgsql-plan-caching">.
>> </para>
>>
>> - <para>
>> - Sometimes it is useful to evaluate an expression or
>> <command>SELECT</>
>> - query but discard the result, for example when calling a function
>> - that has side-effects but no useful result value. To do
>> - this in <application>PL/pgSQL</application>, use the
>> - <command>PERFORM</command> statement:
>> -
>> - <synopsis>
>> - PERFORM <replaceable>query</replaceable>;
>> - </synopsis>
>> -
>> - This executes <replaceable>query</replaceable> and discards the
>> - result. Write the <replaceable>query</replaceable> the same
>> - way you would write an SQL <command>SELECT</> command, but replace
>> the
>> - initial keyword <command>SELECT</> with <command>PERFORM</command>.
>> - For <command>WITH</> queries, use <command>PERFORM</> and then
>> - place the query in parentheses. (In this case, the query can only
>> - return one row.)
>> - <application>PL/pgSQL</application> variables will be
>> - substituted into the query just as for commands that return no
>> result,
>> - and the plan is cached in the same way. Also, the special variable
>> - <literal>FOUND</literal> is set to true if the query produced at
>> - least one row, or false if it produced no rows (see
>> - <xref linkend="plpgsql-statements-diagnostics">).
>> - </para>
>> -
>> <note>
>> <para>
>> ! One might expect that writing <command>SELECT</command> directly
>> ! would accomplish this result, but at
>> ! present the only accepted way to do it is
>> ! <command>PERFORM</command>. A SQL command that can return rows,
>> ! such as <command>SELECT</command>, will be rejected as an error
>> ! unless it has an <literal>INTO</> clause as discussed in the
>> ! next section.
>> </para>
>> </note>
>>
>> <para>
>> An example:
>> <programlisting>
>> ! PERFORM create_mv('cs_session_page_requests_mv', my_query);
>> </programlisting>
>> </para>
>> </sect2>
>> --- 925,944 ----
>> <xref linkend="plpgsql-plan-caching">.
>> </para>
>>
>> <note>
>> <para>
>> ! In older versions of PostgreSQL, it was mandatory to use
>> ! <command>PERFORM</command> instead of <command>SELECT</command>
>> ! when the query could return data that was not captured into
>> ! variables. This requirement has been relaxed and usage of
>> ! <command>PERFORM</command> has been deprecated.
>> </para>
>> </note>
>>
>> <para>
>> An example:
>> <programlisting>
>> ! SELECT create_mv('cs_session_page_requests_mv', my_query);
>
>
> I'd consider making the note into a paragraph and then saying that the
> select form and perform form are equivalent by writing both out one after
> the other. The note brings emphasis that is not necessary if we want to
> de-emphasize perform.
>
> </programlisting>
>> </para>
>> </sect2>
>> *************** GET DIAGNOSTICS integer_var = ROW_COUNT;
>> *** 1480,1491 ****
>> </listitem>
>> <listitem>
>> <para>
>> ! A <command>PERFORM</> statement sets
>> <literal>FOUND</literal>
>> true if it produces (and discards) one or more rows, false
>> if
>> no row is produced.
>> </para>
>> </listitem>
>> <listitem>
>> <para>
>> <command>UPDATE</>, <command>INSERT</>, and
>> <command>DELETE</>
>> statements set <literal>FOUND</literal> true if at least one
>> --- 1452,1471 ----
>> </listitem>
>> <listitem>
>> <para>
>> ! A <command>SELECT</> statement sets <literal>FOUND</literal>
>> true if it produces (and discards) one or more rows, false
>> if
>> no row is produced.
>> </para>
>
>
> This could be worded better. It will return true regardless of whether the
> result is discarded.
>
>
>> </listitem>
>> <listitem>
>> + <para>
>> + A <command>PERFORM</> statement sets
>> <literal>FOUND</literal>
>> + true if it produces (and discards) one or more rows, false
>> if
>> + no row is produced. This statement is equivalent to
>> + <command>SELECT</> without INTO.
>> + </para>
>> + </listitem>
>> + <listitem>
>> diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml
>> new file mode 100644
>> index 9786242..512eaa7
>
>
> Duplicate (x2)? copy-paste elided
>
>
>> diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
>> new file mode 100644
>> index b63ecac..975e8fe
>> *** a/src/pl/plpgsql/src/pl_exec.c
>> --- b/src/pl/plpgsql/src/pl_exec.c
>> *************** exec_stmt_assign(PLpgSQL_execstate *esta
>> *** 1557,1562 ****
>> --- 1557,1563 ----
>> * exec_stmt_perform Evaluate query and discard result (but set
>> * FOUND depending on whether at least one
>> row
>> * was returned).
>> + * This syntax is deprecated.
>> * ----------
>> */
>> static int
>> *************** exec_stmt_execsql(PLpgSQL_execstate *est
>> *** 3647,3658 ****
>> }
>> else
>> {
>> ! /* If the statement returned a tuple table, complain */
>> if (SPI_tuptable != NULL)
>> ! ereport(ERROR,
>> ! (errcode(ERRCODE_SYNTAX_ERROR),
>> ! errmsg("query has no destination for result data"),
>> ! (rc == SPI_OK_SELECT) ? errhint("If you want to
>> discard the results of a SELECT, use PERFORM instead.") : 0));
>> }
>>
>> return PLPGSQL_RC_OK;
>> --- 3648,3656 ----
>> }
>> else
>> {
>> ! /* If the statement returned a tuple table without INTO, free it.
>> */
>> if (SPI_tuptable != NULL)
>> ! SPI_freetuptable(SPI_tuptable);
>> }
>>
>> return PLPGSQL_RC_OK;
>>
>>
> It should include at least one new test.
>
> The discussion talked about insert/returning behavior with respect to
> into. Not necessarily for this patch related but how does that fit in?
>
> +1 from Jim, Merlin, Robert, Tom and myself. I think the docs need work -
> and the code looks ok though lacks at least one required test.
>
> -1 from Pavel
>

I didn't change my opinion - but I accepting so my opinion is minor

Regards

Pavel

>
> Peter E. - you haven't commented but are on this as a reviewer...
>
> Merlin, back in your court for polishing.
>
> Adding myself as reviewer but leaving it in needs review for the moment.
>
> David J.
>

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Albe Laurenz 2016-06-06 07:19:37 Re: Prepared statements and generic plans
Previous Message Thomas Munro 2016-06-06 03:53:41 Reference to UT1