Tarantool development patches archive
 help / color / mirror / Atom feed
From: "n.pettik" <korablev@tarantool.org>
To: tarantool-patches@freelists.org
Cc: Kirill Shcherbatov <kshcherbatov@tarantool.org>
Subject: [tarantool-patches] Re: [PATCH v1 1/1] sql: support HAVING without GROUP BY clause
Date: Mon, 3 Sep 2018 16:23:10 +0300	[thread overview]
Message-ID: <99A1FBB4-3831-4BB6-A1D6-505D09F792AD@tarantool.org> (raw)
In-Reply-To: <5f602cc5-9617-6717-c13a-4d5595c23422@tarantool.org>


> On 29 Aug 2018, at 16:29, Kirill Shcherbatov <kshcherbatov@tarantool.org> wrote:
> 
>> Please, make it behave the same way as other DBs
>> and resend patch.

Still your patch doesn’t handle some cases. Example:

Postgres:

drop table if exists t1 \\
create table t1(id int primary key, a int, b int) \\
insert into t1 values(1, -2,3), (4,5,6), (7,8,9) \\
SELECT SUM(a),a FROM t1 HAVING sum(a) > 0 \\

42803: column "t1.a" must appear in the GROUP BY clause or be used in an aggregate function

db2:

db2 => SELECT SUM(a), a from t1 having sum(a) > 0
SQL0119N  An expression starting with "A" specified in a SELECT clause, HAVING 
clause, or ORDER BY clause is not specified in the GROUP BY clause or it is in 
a SELECT clause, HAVING clause, or ORDER BY clause with a column function and 
no GROUP BY clause is specified.  SQLSTATE=42803

Oracle:

ORA-00937: not a single-group group function

Tarantool:

tarantool> SELECT SUM(a),a FROM t1 HAVING sum(a) > 0
---
- - [11, 8]
...

> 
> ====================================
> 
> Allowed to use HAVING without GROUP BY when both select list
> and having clause have aggregate function.
> 
> Closes 2364.
> 
> @TarantoolBot document
> Title: HAVING without GROUP BY clause
> A query with a having clause should also have a group by clause.

Nit: outline also here HAVING and GROUP BY with capital letters pls. 

> Another ability is to use aggregate function both in select list
> and having clause.

I would re-phrase it like:

However, it is still possible to drop GROUP BY clause in case both SELECT
and HAVING arguments are aggregate functions

> Example:
> SELECT SUM(s1) FROM te40 HAVING SUM(s1) > 0;
> ---
> src/box/sql/resolve.c         | 30 +++++++++++++++----
> test/sql-tap/count.test.lua   |  8 ++---
> test/sql-tap/select3.test.lua |  2 +-
> test/sql-tap/select5.test.lua | 68 ++++++++++++++++++++++++++++++++++++++++++-
> 4 files changed, 97 insertions(+), 11 deletions(-)
> 
> diff --git a/src/box/sql/resolve.c b/src/box/sql/resolve.c
> index 280ecd9..9d28089 100644
> --- a/src/box/sql/resolve.c
> +++ b/src/box/sql/resolve.c
> @@ -1304,12 +1304,32 @@ resolveSelectStep(Walker * pWalker, Select * p)
> 			sNC.ncFlags &= ~NC_AllowAgg;
> 		}
> 
> -		/* If a HAVING clause is present, then there must be a GROUP BY clause.
> +		/*
> +		 * If a HAVING clause is present, then there must
> +		 * be a GROUP BY clause or aggregate function
> +		 * should be specified.
> 		 */
> -		if (p->pHaving && !pGroupBy) {
> -			sqlite3ErrorMsg(pParse,
> -					"a GROUP BY clause is required before HAVING");
> -			return WRC_Abort;
> +		if (p->pHaving != NULL && pGroupBy == NULL) {
> +			struct NameContext having_nc;
> +			memset(&having_nc, 0, sizeof(having_nc));
> +			having_nc.pParse = pParse;
> +			having_nc.ncFlags = NC_AllowAgg;
> +			having_nc.pSrcList = p->pSrc;
> +			if ((p->selFlags & SF_Aggregate) != 0 &&
> +				sqlite3ResolveExprNames(&having_nc,
> +							p->pHaving) != 0)
> +				return WRC_Abort;
> +			if ((having_nc.ncFlags & NC_HasAgg) == 0) {
> +				const char *err_msg =
> +					tt_sprintf("HAVING expression must “

Nit: HAVING is rather clause, than expression. Overall, this msg looks
a little bit weird. In Postgres it is like:

column "t1.a" must appear in the GROUP BY clause or be used in an aggregate function

So, not HAVING clause must appear, but HAVING argument.

> +						   "appear in the GROUP BY "
> +						   "clause or be used in an "
> +						   "aggregate function");
> +				diag_set(ClientError, ER_SQL, err_msg);
> +				pParse->nErr++;
> +				pParse->rc = SQL_TARANTOOL_ERROR;
> +				return WRC_Abort;
> +			}
> 		}
> 
> 		/* Add the output column list to the name-context before parsing the
> 
> 
> diff --git a/test/sql-tap/select5.test.lua b/test/sql-tap/select5.test.lua
> index 7ca25ae..db3f447 100755
> --- a/test/sql-tap/select5.test.lua
> +++ b/test/sql-tap/select5.test.lua
> @@ -1,6 +1,6 @@
> #!/usr/bin/env tarantool
> test = require("sqltester")
> -test:plan(32)
> +test:plan(38)
> 
> --!./tcltestrunner.lua
> -- 2001 September 15
> @@ -412,5 +412,71 @@ test:do_execsql_test(
>         -- </select5-8.8>
>     })
> 
> +--
> +-- gh-2364: Support HAVING without GROUP BY clause.
> +--
> +test:do_catchsql_test(
> +    "select6-1.1",
> +    [[
> +        CREATE TABLE te40 (s1 INT, s2 INT, PRIMARY KEY (s1,s2));
> +        INSERT INTO te40 VALUES (1,1);
> +        INSERT INTO te40 VALUES (2,2);
> +        SELECT s1 FROM te40 HAVING s1 = 1;
> +    ]], {
> +    -- <select6-1.1>
> +    1, "SQL error: HAVING expression must appear in the GROUP BY clause or be used in an aggregate function"
> +    -- <select6-1.1>
> +})
> +
> +test:do_catchsql_test(
> +    "select6-1.2",
> +    [[
> +        SELECT SUM(s1) FROM te40 HAVING s1 = 2;
> +    ]], {
> +    -- <select6-1.2>
> +    1, "SQL error: HAVING expression must appear in the GROUP BY clause or be used in an aggregate function"
> +    -- <select6-1.2>
> +})
> +
> +test:do_catchsql_test(
> +    "select6-1.3",
> +    [[
> +        SELECT s1 FROM te40 HAVING SUM(s1) = 2;
> +    ]], {
> +    -- <select6-1.3>
> +    1, "SQL error: HAVING expression must appear in the GROUP BY clause or be used in an aggregate function"
> +    -- <select6-1.3>
> +})
> +
> +test:do_execsql_test(
> +    "select6-1.4",
> +    [[
> +        SELECT SUM(s1) FROM te40 HAVING SUM(s1) > 0;
> +    ]], {
> +    -- <select6-1.4>
> +    3
> +    -- <select6-1.4>
> +})
> +
> +test:do_execsql_test(
> +    "select6-2.1”,

Why 2.1 and not 1.5? The same for tests below.

  parent reply	other threads:[~2018-09-03 14:15 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-08-28 16:39 [tarantool-patches] " Kirill Shcherbatov
2018-08-29 11:52 ` [tarantool-patches] " n.pettik
2018-08-29 13:29   ` Kirill Shcherbatov
2018-09-03 11:24     ` n.pettik
2018-09-03 13:23     ` n.pettik [this message]
2018-09-10  7:51       ` Kirill Shcherbatov
2018-09-10 21:43         ` n.pettik
2018-09-20 12:43           ` Kirill Shcherbatov
2018-10-01 16:37             ` n.pettik

Reply instructions:

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

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

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=99A1FBB4-3831-4BB6-A1D6-505D09F792AD@tarantool.org \
    --to=korablev@tarantool.org \
    --cc=kshcherbatov@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --subject='[tarantool-patches] Re: [PATCH v1 1/1] sql: support HAVING without GROUP BY clause' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox