in ext/pg_query/pg_query_deparse.c [2015:2194]
static void deparseSelectStmt(StringInfo str, SelectStmt *stmt)
{
const ListCell *lc = NULL;
const ListCell *lc2 = NULL;
if (stmt->withClause)
{
deparseWithClause(str, stmt->withClause);
appendStringInfoChar(str, ' ');
}
switch (stmt->op) {
case SETOP_NONE:
if (list_length(stmt->valuesLists) > 0)
{
const ListCell *lc;
appendStringInfoString(str, "VALUES ");
foreach(lc, stmt->valuesLists)
{
appendStringInfoChar(str, '(');
deparseExprList(str, lfirst(lc));
appendStringInfoChar(str, ')');
if (lnext(stmt->valuesLists, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ' ');
break;
}
appendStringInfoString(str, "SELECT ");
if (list_length(stmt->targetList) > 0)
{
if (stmt->distinctClause != NULL)
{
appendStringInfoString(str, "DISTINCT ");
if (list_length(stmt->distinctClause) > 0 && linitial(stmt->distinctClause) != NULL)
{
appendStringInfoString(str, "ON (");
deparseExprList(str, stmt->distinctClause);
appendStringInfoString(str, ") ");
}
}
deparseTargetList(str, stmt->targetList);
appendStringInfoChar(str, ' ');
}
if (stmt->intoClause != NULL)
{
appendStringInfoString(str, "INTO ");
deparseOptTemp(str, stmt->intoClause->rel->relpersistence);
deparseIntoClause(str, stmt->intoClause);
appendStringInfoChar(str, ' ');
}
deparseFromClause(str, stmt->fromClause);
deparseWhereClause(str, stmt->whereClause);
if (list_length(stmt->groupClause) > 0)
{
appendStringInfoString(str, "GROUP BY ");
deparseGroupByList(str, stmt->groupClause);
appendStringInfoChar(str, ' ');
}
if (stmt->havingClause != NULL)
{
appendStringInfoString(str, "HAVING ");
deparseExpr(str, stmt->havingClause);
appendStringInfoChar(str, ' ');
}
if (stmt->windowClause != NULL)
{
appendStringInfoString(str, "WINDOW ");
foreach(lc, stmt->windowClause)
{
WindowDef *window_def = castNode(WindowDef, lfirst(lc));
Assert(window_def->name != NULL);
appendStringInfoString(str, window_def->name);
appendStringInfoString(str, " AS ");
deparseWindowDef(str, window_def);
if (lnext(stmt->windowClause, lc))
appendStringInfoString(str, ", ");
}
appendStringInfoChar(str, ' ');
}
break;
case SETOP_UNION:
case SETOP_INTERSECT:
case SETOP_EXCEPT:
{
bool need_larg_parens =
list_length(stmt->larg->sortClause) > 0 ||
stmt->larg->limitOffset != NULL ||
stmt->larg->limitCount != NULL ||
list_length(stmt->larg->lockingClause) > 0 ||
stmt->larg->withClause != NULL ||
stmt->larg->op != SETOP_NONE;
bool need_rarg_parens =
list_length(stmt->rarg->sortClause) > 0 ||
stmt->rarg->limitOffset != NULL ||
stmt->rarg->limitCount != NULL ||
list_length(stmt->rarg->lockingClause) > 0 ||
stmt->rarg->withClause != NULL ||
stmt->rarg->op != SETOP_NONE;
if (need_larg_parens)
appendStringInfoChar(str, '(');
deparseSelectStmt(str, stmt->larg);
if (need_larg_parens)
appendStringInfoChar(str, ')');
switch (stmt->op)
{
case SETOP_UNION:
appendStringInfoString(str, " UNION ");
break;
case SETOP_INTERSECT:
appendStringInfoString(str, " INTERSECT ");
break;
case SETOP_EXCEPT:
appendStringInfoString(str, " EXCEPT ");
break;
default:
Assert(false);
}
if (stmt->all)
appendStringInfoString(str, "ALL ");
if (need_rarg_parens)
appendStringInfoChar(str, '(');
deparseSelectStmt(str, stmt->rarg);
if (need_rarg_parens)
appendStringInfoChar(str, ')');
appendStringInfoChar(str, ' ');
}
break;
}
deparseOptSortClause(str, stmt->sortClause);
if (stmt->limitCount != NULL)
{
if (stmt->limitOption == LIMIT_OPTION_COUNT)
appendStringInfoString(str, "LIMIT ");
else if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
appendStringInfoString(str, "FETCH FIRST ");
if (IsA(stmt->limitCount, A_Const) && IsA(&castNode(A_Const, stmt->limitCount)->val, Null))
appendStringInfoString(str, "ALL");
else
deparseCExpr(str, stmt->limitCount);
appendStringInfoChar(str, ' ');
if (stmt->limitOption == LIMIT_OPTION_WITH_TIES)
appendStringInfoString(str, "ROWS WITH TIES ");
}
if (stmt->limitOffset != NULL)
{
appendStringInfoString(str, "OFFSET ");
deparseExpr(str, stmt->limitOffset);
appendStringInfoChar(str, ' ');
}
if (list_length(stmt->lockingClause) > 0)
{
foreach(lc, stmt->lockingClause)
{
deparseLockingClause(str, castNode(LockingClause, lfirst(lc)));
if (lnext(stmt->lockingClause, lc))
appendStringInfoString(str, " ");
}
appendStringInfoChar(str, ' ');
}
removeTrailingSpace(str);
}