Skip to content

Commit

Permalink
sql: remove one row limit in EXISTS subquery
Browse files Browse the repository at this point in the history
According to ANSI, EXISTS is a predicate that tests a given subquery and
returns true if it returns more than 0 rows, false otherwise. However,
before this patch, EXISTS worked correctly only if there were exactly 0
or 1 rows, and in all other cases it gave an error. This patch makes
EXITS work properly.

Closes tarantool#8676

@TarantoolBot document
Title: EXISTS predicate

The EXISTS predicate in SQL is a predicate that returns true if the
given SQL subquery returns at least one row, and false otherwise.

Example:
```
SELECT EXISTS(SELECT * FROM (VALUES(1), (2)));
```
  • Loading branch information
ImeevMA committed Jul 5, 2023
1 parent 852664b commit 9f04dab
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 21 deletions.
4 changes: 4 additions & 0 deletions changelogs/unreleased/gh-8676-fix-exists-predicate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
## bugfix/sql

* The `EXIST` predicate now returns true if the subquery returns more than 0
rows, and false otherwise (gh-8676).
3 changes: 2 additions & 1 deletion src/box/sql/expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -2801,7 +2801,8 @@ sqlCodeSubselect(Parse * pParse, /* Parsing context */
&sqlIntTokens[1]);
ExprSetProperty(pSel->pLimit, EP_System);
}
pSel->selFlags |= SF_SingleRow;
if (pExpr->op == TK_SELECT)
pSel->selFlags |= SF_SingleRow;
pSel->iLimit = 0;
pSel->selFlags &= ~SF_MultiValue;
if (sqlSelect(pParse, pSel, &dest)) {
Expand Down
20 changes: 20 additions & 0 deletions test/sql-luatest/gh_8676_fix_exists_test.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
local server = require('luatest.server')
local t = require('luatest')

local g = t.group()

g.before_all(function()
g.server = server:new({alias = 'master'})
g.server:start()
end)

g.after_all(function()
g.server:stop()
end)

g.test_exists = function()
g.server:exec(function()
local res = box.execute([[SELECT EXISTS (VALUES (1), (2));]])
t.assert_equals(res.rows, {{true}})
end)
end
40 changes: 20 additions & 20 deletions test/sql-tap/tkt1473.test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -199,14 +199,14 @@ test:do_execsql_test(
-- </tkt1473-2.9>
})

test:do_catchsql_test(
test:do_execsql_test(
"tkt1473-3.2",
[[
SELECT EXISTS
(SELECT 1 FROM t1 WHERE a=1 UNION ALL SELECT 2 FROM t1 WHERE b=0)
]], {
-- <tkt1473-3.2>
1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
true
-- </tkt1473-3.2>
})

Expand All @@ -221,36 +221,36 @@ test:do_execsql_test(
-- </tkt1473-3.3>
})

test:do_catchsql_test(
test:do_execsql_test(
"tkt1473-3.4",
[[
SELECT EXISTS
(SELECT 1 FROM t1 WHERE a=1 UNION ALL SELECT 2 FROM t1 WHERE b=4)
]], {
-- <tkt1473-3.4>
1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
true
-- </tkt1473-3.4>
})

test:do_catchsql_test(
test:do_execsql_test(
"tkt1473-3.5",
[[
SELECT EXISTS
(SELECT 1 FROM t1 WHERE a=1 UNION SELECT 2 FROM t1 WHERE b=4)
]], {
-- <tkt1473-3.5>
1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
true
-- </tkt1473-3.5>
})

test:do_catchsql_test(
test:do_execsql_test(
"tkt1473-3.6",
[[
SELECT EXISTS
(SELECT 1 FROM t1 WHERE a=0 UNION ALL SELECT 2 FROM t1 WHERE b=4)
]], {
-- <tkt1473-3.6>
1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
true
-- </tkt1473-3.6>
})

Expand Down Expand Up @@ -483,7 +483,7 @@ test:do_execsql_test(
-- </tkt1473-4.7>
})

test:do_catchsql_test(
test:do_execsql_test(
"tkt1473-5.3",
[[
SELECT EXISTS (
Expand All @@ -509,11 +509,11 @@ test:do_catchsql_test(
)
]], {
-- <tkt1473-5.3>
1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
true
-- </tkt1473-5.3>
})

test:do_catchsql_test(
test:do_execsql_test(
"tkt1473-5.4",
[[
SELECT EXISTS (
Expand All @@ -539,11 +539,11 @@ test:do_catchsql_test(
)
]], {
-- <tkt1473-5.4>
1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
true
-- </tkt1473-5.4>
})

test:do_catchsql_test(
test:do_execsql_test(
"tkt1473-5.5",
[[
SELECT EXISTS (
Expand All @@ -569,11 +569,11 @@ test:do_catchsql_test(
)
]], {
-- <tkt1473-5.5>
1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
true
-- </tkt1473-5.5>
})

test:do_catchsql_test(
test:do_execsql_test(
"tkt1473-5.6",
[[
SELECT EXISTS (
Expand All @@ -599,7 +599,7 @@ test:do_catchsql_test(
)
]], {
-- <tkt1473-5.6>
1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
true
-- </tkt1473-5.6>
})

Expand Down Expand Up @@ -633,7 +633,7 @@ test:do_execsql_test(
-- </tkt1473-5.7>
})

test:do_catchsql_test(
test:do_execsql_test(
"tkt1473-6.3",
[[
SELECT EXISTS (
Expand All @@ -659,11 +659,11 @@ test:do_catchsql_test(
)
]], {
-- <tkt1473-6.3>
1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
true
-- </tkt1473-6.3>
})

test:do_catchsql_test(
test:do_execsql_test(
"tkt1473-6.4",
[[
SELECT EXISTS (
Expand All @@ -689,7 +689,7 @@ test:do_catchsql_test(
)
]], {
-- <tkt1473-6.4>
1, "Failed to execute SQL statement: Expression subquery returned more than 1 row"
true
-- </tkt1473-6.4>
})

Expand Down

0 comments on commit 9f04dab

Please sign in to comment.