in ext/pg_query/pg_query_deparse.c [2552:2770]
static void deparseAExpr(StringInfo str, A_Expr* a_expr, DeparseNodeContext context)
{
ListCell *lc;
char *name;
bool need_lexpr_parens = a_expr->lexpr != NULL && (IsA(a_expr->lexpr, BoolExpr) || IsA(a_expr->lexpr, NullTest) || IsA(a_expr->lexpr, A_Expr));
bool need_rexpr_parens = a_expr->rexpr != NULL && (IsA(a_expr->rexpr, BoolExpr) || IsA(a_expr->rexpr, NullTest) || IsA(a_expr->rexpr, A_Expr));
switch (a_expr->kind) {
case AEXPR_OP: /* normal operator */
{
bool need_outer_parens = context == DEPARSE_NODE_CONTEXT_A_EXPR;
if (need_outer_parens)
appendStringInfoChar(str, '(');
if (a_expr->lexpr != NULL)
{
if (need_lexpr_parens)
appendStringInfoChar(str, '(');
deparseExpr(str, a_expr->lexpr);
if (need_lexpr_parens)
appendStringInfoChar(str, ')');
appendStringInfoChar(str, ' ');
}
deparseQualOp(str, a_expr->name);
if (a_expr->rexpr != NULL)
{
appendStringInfoChar(str, ' ');
if (need_rexpr_parens)
appendStringInfoChar(str, '(');
deparseExpr(str, a_expr->rexpr);
if (need_rexpr_parens)
appendStringInfoChar(str, ')');
}
if (need_outer_parens)
appendStringInfoChar(str, ')');
}
return;
case AEXPR_OP_ANY: /* scalar op ANY (array) */
deparseExpr(str, a_expr->lexpr);
appendStringInfoChar(str, ' ');
deparseSubqueryOp(str, a_expr->name);
appendStringInfoString(str, " ANY(");
deparseExpr(str, a_expr->rexpr);
appendStringInfoChar(str, ')');
return;
case AEXPR_OP_ALL: /* scalar op ALL (array) */
deparseExpr(str, a_expr->lexpr);
appendStringInfoChar(str, ' ');
deparseSubqueryOp(str, a_expr->name);
appendStringInfoString(str, " ALL(");
deparseExpr(str, a_expr->rexpr);
appendStringInfoChar(str, ')');
return;
case AEXPR_DISTINCT: /* IS DISTINCT FROM - name must be "=" */
Assert(list_length(a_expr->name) == 1);
Assert(IsA(linitial(a_expr->name), String));
Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
if (need_lexpr_parens)
appendStringInfoChar(str, '(');
deparseExpr(str, a_expr->lexpr);
if (need_lexpr_parens)
appendStringInfoChar(str, ')');
appendStringInfoString(str, " IS DISTINCT FROM ");
if (need_rexpr_parens)
appendStringInfoChar(str, '(');
deparseExpr(str, a_expr->rexpr);
if (need_rexpr_parens)
appendStringInfoChar(str, ')');
return;
case AEXPR_NOT_DISTINCT: /* IS NOT DISTINCT FROM - name must be "=" */
Assert(list_length(a_expr->name) == 1);
Assert(IsA(linitial(a_expr->name), String));
Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
deparseExpr(str, a_expr->lexpr);
appendStringInfoString(str, " IS NOT DISTINCT FROM ");
deparseExpr(str, a_expr->rexpr);
return;
case AEXPR_NULLIF: /* NULLIF - name must be "=" */
Assert(list_length(a_expr->name) == 1);
Assert(IsA(linitial(a_expr->name), String));
Assert(strcmp(strVal(linitial(a_expr->name)), "=") == 0);
appendStringInfoString(str, "NULLIF(");
deparseExpr(str, a_expr->lexpr);
appendStringInfoString(str, ", ");
deparseExpr(str, a_expr->rexpr);
appendStringInfoChar(str, ')');
return;
case AEXPR_OF: /* IS [NOT] OF - name must be "=" or "<>" */
Assert(list_length(a_expr->name) == 1);
Assert(IsA(linitial(a_expr->name), String));
Assert(IsA(a_expr->rexpr, List));
deparseExpr(str, a_expr->lexpr);
appendStringInfoChar(str, ' ');
name = ((Value *) linitial(a_expr->name))->val.str;
if (strcmp(name, "=") == 0) {
appendStringInfoString(str, "IS OF ");
} else if (strcmp(name, "<>") == 0) {
appendStringInfoString(str, "IS NOT OF ");
} else {
Assert(false);
}
appendStringInfoChar(str, '(');
deparseTypeList(str, castNode(List, a_expr->rexpr));
appendStringInfoChar(str, ')');
return;
case AEXPR_IN: /* [NOT] IN - name must be "=" or "<>" */
Assert(list_length(a_expr->name) == 1);
Assert(IsA(linitial(a_expr->name), String));
Assert(IsA(a_expr->rexpr, List));
deparseExpr(str, a_expr->lexpr);
appendStringInfoChar(str, ' ');
name = ((Value *) linitial(a_expr->name))->val.str;
if (strcmp(name, "=") == 0) {
appendStringInfoString(str, "IN ");
} else if (strcmp(name, "<>") == 0) {
appendStringInfoString(str, "NOT IN ");
} else {
Assert(false);
}
appendStringInfoChar(str, '(');
if (IsA(a_expr->rexpr, SubLink))
deparseSubLink(str, castNode(SubLink, a_expr->rexpr));
else
deparseExprList(str, castNode(List, a_expr->rexpr));
appendStringInfoChar(str, ')');
return;
case AEXPR_LIKE: /* [NOT] LIKE - name must be "~~" or "!~~" */
Assert(list_length(a_expr->name) == 1);
Assert(IsA(linitial(a_expr->name), String));
deparseExpr(str, a_expr->lexpr);
appendStringInfoChar(str, ' ');
name = ((Value *) linitial(a_expr->name))->val.str;
if (strcmp(name, "~~") == 0) {
appendStringInfoString(str, "LIKE ");
} else if (strcmp(name, "!~~") == 0) {
appendStringInfoString(str, "NOT LIKE ");
} else {
Assert(false);
}
deparseExpr(str, a_expr->rexpr);
return;
case AEXPR_ILIKE: /* [NOT] ILIKE - name must be "~~*" or "!~~*" */
Assert(list_length(a_expr->name) == 1);
Assert(IsA(linitial(a_expr->name), String));
deparseExpr(str, a_expr->lexpr);
appendStringInfoChar(str, ' ');
name = ((Value *) linitial(a_expr->name))->val.str;
if (strcmp(name, "~~*") == 0) {
appendStringInfoString(str, "ILIKE ");
} else if (strcmp(name, "!~~*") == 0) {
appendStringInfoString(str, "NOT ILIKE ");
} else {
Assert(false);
}
deparseExpr(str, a_expr->rexpr);
return;
case AEXPR_SIMILAR: /* [NOT] SIMILAR - name must be "~" or "!~" */
Assert(list_length(a_expr->name) == 1);
Assert(IsA(linitial(a_expr->name), String));
deparseExpr(str, a_expr->lexpr);
appendStringInfoChar(str, ' ');
name = ((Value *) linitial(a_expr->name))->val.str;
if (strcmp(name, "~") == 0) {
appendStringInfoString(str, "SIMILAR TO ");
} else if (strcmp(name, "!~") == 0) {
appendStringInfoString(str, "NOT SIMILAR TO ");
} else {
Assert(false);
}
FuncCall *n = castNode(FuncCall, a_expr->rexpr);
Assert(list_length(n->funcname) == 2);
Assert(strcmp(strVal(linitial(n->funcname)), "pg_catalog") == 0);
Assert(strcmp(strVal(lsecond(n->funcname)), "similar_to_escape") == 0);
Assert(list_length(n->args) == 1 || list_length(n->args) == 2);
deparseExpr(str, linitial(n->args));
if (list_length(n->args) == 2)
{
appendStringInfoString(str, " ESCAPE ");
deparseExpr(str, lsecond(n->args));
}
return;
case AEXPR_BETWEEN: /* name must be "BETWEEN" */
case AEXPR_NOT_BETWEEN: /* name must be "NOT BETWEEN" */
case AEXPR_BETWEEN_SYM: /* name must be "BETWEEN SYMMETRIC" */
case AEXPR_NOT_BETWEEN_SYM: /* name must be "NOT BETWEEN SYMMETRIC" */
Assert(list_length(a_expr->name) == 1);
Assert(IsA(linitial(a_expr->name), String));
Assert(IsA(a_expr->rexpr, List));
deparseExpr(str, a_expr->lexpr);
appendStringInfoChar(str, ' ');
appendStringInfoString(str, strVal(linitial(a_expr->name)));
appendStringInfoChar(str, ' ');
foreach(lc, castNode(List, a_expr->rexpr)) {
deparseExpr(str, lfirst(lc));
if (lnext(castNode(List, a_expr->rexpr), lc))
appendStringInfoString(str, " AND ");
}
return;
case AEXPR_PAREN: /* nameless dummy node for parentheses */
// Not present in parse trees when operator_precedence_warning is turned off
Assert(false);
return;
}
}