static void deparseSelectStmt()

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