static void deparseAExpr()

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;
	}
}