Transform isNull/isNotNull to IS NULL/IS NOT NULL (for external dbs)

This is required to support queries (like `foo IS NULL`) to external
databases (i.e. MySQL).

This patch had been submitted separately, due to:
- avoid mixing patches
- run CI (and update tests references)
This commit is contained in:
Azat Khuzhin 2021-09-27 21:04:12 +03:00
parent e9749b0027
commit 2378491c04
5 changed files with 49 additions and 6 deletions

View File

@ -217,10 +217,13 @@ void ASTFunction::formatImplWithoutAlias(const FormatSettings & settings, Format
settings.ostr << nl_or_nothing << indent_str << ")"; settings.ostr << nl_or_nothing << indent_str << ")";
return; return;
} }
/// Should this function to be written as operator? /// Should this function to be written as operator?
bool written = false; bool written = false;
if (arguments && !parameters) if (arguments && !parameters)
{ {
/// Unary prefix operators.
if (arguments->children.size() == 1) if (arguments->children.size() == 1)
{ {
const char * operators[] = const char * operators[] =
@ -270,6 +273,32 @@ void ASTFunction::formatImplWithoutAlias(const FormatSettings & settings, Format
} }
} }
/// Unary postfix operators.
if (!written && arguments->children.size() == 1)
{
const char * operators[] =
{
"isNull", " IS NULL",
"isNotNull", " IS NOT NULL",
nullptr
};
for (const char ** func = operators; *func; func += 2)
{
if (strcasecmp(name.c_str(), func[0]) != 0)
{
continue;
}
arguments->formatImpl(settings, state, nested_need_parens);
settings.ostr << (settings.hilite ? hilite_operator : "") << func[1] << (settings.hilite ? hilite_none : "");
written = true;
break;
}
}
/** need_parens - do we need parentheses around the expression with the operator. /** need_parens - do we need parentheses around the expression with the operator.
* They are needed only if this expression is included in another expression with the operator. * They are needed only if this expression is included in another expression with the operator.
*/ */

View File

@ -146,7 +146,7 @@ SELECT
t2_00826.b t2_00826.b
FROM t1_00826 FROM t1_00826
ALL INNER JOIN t2_00826 ON b = t2_00826.a ALL INNER JOIN t2_00826 ON b = t2_00826.a
WHERE (b = t2_00826.a) AND (isNull(t2_00826.b) OR (t2_00826.b > t2_00826.a)) WHERE (b = t2_00826.a) AND (t2_00826.b IS NULL OR (t2_00826.b > t2_00826.a))
--- do not rewrite alias --- --- do not rewrite alias ---
SELECT a AS b SELECT a AS b
FROM t1_00826 FROM t1_00826
@ -178,4 +178,4 @@ SELECT
t2_00826.b t2_00826.b
FROM t1_00826 FROM t1_00826
ALL INNER JOIN t2_00826 ON a = t2_00826.a ALL INNER JOIN t2_00826 ON a = t2_00826.a
WHERE (a = t2_00826.a) AND (isNull(t2_00826.b) OR (t2_00826.b < 2)) WHERE (a = t2_00826.a) AND (t2_00826.b IS NULL OR (t2_00826.b < 2))

View File

@ -1,7 +1,7 @@
0 0 1 0 0 1
0 1 0 0 1 0
SELECT SELECT
isNull(id), id IS NULL,
`n.null`, `n.null`,
NOT `n.null` NOT `n.null`
FROM t_func_to_subcolumns FROM t_func_to_subcolumns
@ -31,7 +31,7 @@ FROM t_func_to_subcolumns
SELECT SELECT
id, id,
`n.null`, `n.null`,
isNull(right.n) right.n IS NULL
FROM t_func_to_subcolumns AS left FROM t_func_to_subcolumns AS left
ALL FULL OUTER JOIN ALL FULL OUTER JOIN
( (

View File

@ -0,0 +1,9 @@
-- { echo }
explain syntax select null is null;
SELECT NULL IS NULL
explain syntax select null is not null;
SELECT NULL IS NOT NULL
explain syntax select isNull(null);
SELECT NULL IS NULL
explain syntax select isNotNull(null);
SELECT NULL IS NOT NULL

View File

@ -0,0 +1,5 @@
-- { echo }
explain syntax select null is null;
explain syntax select null is not null;
explain syntax select isNull(null);
explain syntax select isNotNull(null);