#include "pg_query.h"
#include "pg_query_json_plpgsql.h"
#include "pg_query_json_helper.c"
#define WRITE_NODE_TYPE(nodelabel) \
appendStringInfoString(out, "\"" nodelabel "\":{")
#define WRITE_INT_FIELD(outname, outname_json, fldname) \
if (node->fldname != 0) { \
appendStringInfo(out, "\"" CppAsString(outname_json) "\":%d,", node->fldname); \
}
#define WRITE_LONG_FIELD(outname, outname_json, fldname) \
if (node->fldname != 0) { \
appendStringInfo(out, "\"" CppAsString(outname_json) "\":%ld,", node->fldname); \
}
#define WRITE_ENUM_FIELD(outname, outname_json, fldname) \
appendStringInfo(out, "\"" CppAsString(outname_json) "\":%d,", \
(int) node->fldname)
#define WRITE_BOOL_FIELD(outname, outname_json, fldname) \
if (node->fldname) { \
appendStringInfo(out, "\"" CppAsString(outname_json) "\":%s,", \
booltostr(node->fldname)); \
}
#define WRITE_STRING_FIELD(outname, outname_json, fldname) \
if (node->fldname != NULL) { \
appendStringInfo(out, "\"" CppAsString(outname_json) "\":"); \
_outToken(out, node->fldname); \
appendStringInfo(out, ","); \
}
#define WRITE_INT_VALUE(fldname, value) \
if (value != 0) { \
appendStringInfo(out, "\"" CppAsString(fldname) "\":%d,", value); \
}
#define WRITE_STRING_VALUE(fldname, value) \
if (true) { \
appendStringInfo(out, "\"" CppAsString(fldname) "\":"); \
_outToken(out, value); \
appendStringInfo(out, ","); \
}
#define WRITE_OBJ_FIELD(fldname, outfunc) \
if (node->fldname != NULL) { \
appendStringInfo(out, "\"" CppAsString(fldname) "\":{"); \
outfunc(out, node->fldname); \
removeTrailingDelimiter(out); \
appendStringInfo(out, "}},"); \
}
#define WRITE_LIST_FIELD(fldname, fldtype, outfunc) \
if (node->fldname != NULL) { \
ListCell *lc; \
appendStringInfo(out, "\"" CppAsString(fldname) "\":["); \
foreach(lc, node->fldname) { \
appendStringInfoString(out, "{"); \
outfunc(out, (fldtype *) lfirst(lc)); \
removeTrailingDelimiter(out); \
appendStringInfoString(out, "}},"); \
} \
removeTrailingDelimiter(out); \
appendStringInfoString(out, "],"); \
}
#define WRITE_STATEMENTS_FIELD(fldname) \
if (node->fldname != NULL) { \
ListCell *lc; \
appendStringInfo(out, "\"" CppAsString(fldname) "\":["); \
foreach(lc, node->fldname) { \
dump_stmt(out, (PLpgSQL_stmt *) lfirst(lc)); \
} \
removeTrailingDelimiter(out); \
appendStringInfoString(out, "],"); \
}
#define WRITE_EXPR_FIELD(fldname) WRITE_OBJ_FIELD(fldname, dump_expr)
#define WRITE_BLOCK_FIELD(fldname) WRITE_OBJ_FIELD(fldname, dump_block)
#define WRITE_RECORD_FIELD(fldname) WRITE_OBJ_FIELD(fldname, dump_record)
#define WRITE_ROW_FIELD(fldname) WRITE_OBJ_FIELD(fldname, dump_row)
#define WRITE_VAR_FIELD(fldname) WRITE_OBJ_FIELD(fldname, dump_var)
#define WRITE_VARIABLE_FIELD(fldname) WRITE_OBJ_FIELD(fldname, dump_variable);
static void dump_record(StringInfo out, PLpgSQL_rec *stmt);
static void dump_row(StringInfo out, PLpgSQL_row *stmt);
static void dump_var(StringInfo out, PLpgSQL_var *stmt);
static void dump_variable(StringInfo out, PLpgSQL_variable *stmt);
static void dump_record_field(StringInfo out, PLpgSQL_recfield *node);
static void dump_stmt(StringInfo out, PLpgSQL_stmt *stmt);
static void dump_block(StringInfo out, PLpgSQL_stmt_block *block);
static void dump_exception_block(StringInfo out, PLpgSQL_exception_block *node);
static void dump_assign(StringInfo out, PLpgSQL_stmt_assign *stmt);
static void dump_if(StringInfo out, PLpgSQL_stmt_if *stmt);
static void dump_if_elsif(StringInfo out, PLpgSQL_if_elsif *node);
static void dump_case(StringInfo out, PLpgSQL_stmt_case *stmt);
static void dump_case_when(StringInfo out, PLpgSQL_case_when *node);
static void dump_loop(StringInfo out, PLpgSQL_stmt_loop *stmt);
static void dump_while(StringInfo out, PLpgSQL_stmt_while *stmt);
static void dump_fori(StringInfo out, PLpgSQL_stmt_fori *stmt);
static void dump_fors(StringInfo out, PLpgSQL_stmt_fors *stmt);
static void dump_forc(StringInfo out, PLpgSQL_stmt_forc *stmt);
static void dump_foreach_a(StringInfo out, PLpgSQL_stmt_foreach_a *stmt);
static void dump_exit(StringInfo out, PLpgSQL_stmt_exit *stmt);
static void dump_return(StringInfo out, PLpgSQL_stmt_return *stmt);
static void dump_return_next(StringInfo out, PLpgSQL_stmt_return_next *stmt);
static void dump_return_query(StringInfo out, PLpgSQL_stmt_return_query *stmt);
static void dump_raise(StringInfo out, PLpgSQL_stmt_raise *stmt);
static void dump_raise_option(StringInfo out, PLpgSQL_raise_option *node);
static void dump_assert(StringInfo out, PLpgSQL_stmt_assert *stmt);
static void dump_execsql(StringInfo out, PLpgSQL_stmt_execsql *stmt);
static void dump_dynexecute(StringInfo out, PLpgSQL_stmt_dynexecute *stmt);
static void dump_dynfors(StringInfo out, PLpgSQL_stmt_dynfors *stmt);
static void dump_getdiag(StringInfo out, PLpgSQL_stmt_getdiag *stmt);
static void dump_getdiag_item(StringInfo out, PLpgSQL_diag_item *node);
static void dump_open(StringInfo out, PLpgSQL_stmt_open *stmt);
static void dump_fetch(StringInfo out, PLpgSQL_stmt_fetch *stmt);
static void dump_close(StringInfo out, PLpgSQL_stmt_close *stmt);
static void dump_perform(StringInfo out, PLpgSQL_stmt_perform *stmt);
static void dump_call(StringInfo out, PLpgSQL_stmt_call *stmt);
static void dump_commit(StringInfo out, PLpgSQL_stmt_commit *stmt);
static void dump_rollback(StringInfo out, PLpgSQL_stmt_rollback *stmt);
static void dump_expr(StringInfo out, PLpgSQL_expr *expr);
static void dump_function(StringInfo out, PLpgSQL_function *func);
static void dump_exception(StringInfo out, PLpgSQL_exception *node);
static void dump_condition(StringInfo out, PLpgSQL_condition *node);
static void dump_type(StringInfo out, PLpgSQL_type *node);
static void
dump_stmt(StringInfo out, PLpgSQL_stmt *node)
{
appendStringInfoChar(out, '{');
switch (node->cmd_type)
{
case PLPGSQL_STMT_BLOCK:
dump_block(out, (PLpgSQL_stmt_block *) node);
break;
case PLPGSQL_STMT_ASSIGN:
dump_assign(out, (PLpgSQL_stmt_assign *) node);
break;
case PLPGSQL_STMT_IF:
dump_if(out, (PLpgSQL_stmt_if *) node);
break;
case PLPGSQL_STMT_CASE:
dump_case(out, (PLpgSQL_stmt_case *) node);
break;
case PLPGSQL_STMT_LOOP:
dump_loop(out, (PLpgSQL_stmt_loop *) node);
break;
case PLPGSQL_STMT_WHILE:
dump_while(out, (PLpgSQL_stmt_while *) node);
break;
case PLPGSQL_STMT_FORI:
dump_fori(out, (PLpgSQL_stmt_fori *) node);
break;
case PLPGSQL_STMT_FORS:
dump_fors(out, (PLpgSQL_stmt_fors *) node);
break;
case PLPGSQL_STMT_FORC:
dump_forc(out, (PLpgSQL_stmt_forc *) node);
break;
case PLPGSQL_STMT_FOREACH_A:
dump_foreach_a(out, (PLpgSQL_stmt_foreach_a *) node);
break;
case PLPGSQL_STMT_EXIT:
dump_exit(out, (PLpgSQL_stmt_exit *) node);
break;
case PLPGSQL_STMT_RETURN:
dump_return(out, (PLpgSQL_stmt_return *) node);
break;
case PLPGSQL_STMT_RETURN_NEXT:
dump_return_next(out, (PLpgSQL_stmt_return_next *) node);
break;
case PLPGSQL_STMT_RETURN_QUERY:
dump_return_query(out, (PLpgSQL_stmt_return_query *) node);
break;
case PLPGSQL_STMT_RAISE:
dump_raise(out, (PLpgSQL_stmt_raise *) node);
break;
case PLPGSQL_STMT_ASSERT:
dump_assert(out, (PLpgSQL_stmt_assert *) node);
break;
case PLPGSQL_STMT_EXECSQL:
dump_execsql(out, (PLpgSQL_stmt_execsql *) node);
break;
case PLPGSQL_STMT_DYNEXECUTE:
dump_dynexecute(out, (PLpgSQL_stmt_dynexecute *) node);
break;
case PLPGSQL_STMT_DYNFORS:
dump_dynfors(out, (PLpgSQL_stmt_dynfors *) node);
break;
case PLPGSQL_STMT_GETDIAG:
dump_getdiag(out, (PLpgSQL_stmt_getdiag *) node);
break;
case PLPGSQL_STMT_OPEN:
dump_open(out, (PLpgSQL_stmt_open *) node);
break;
case PLPGSQL_STMT_FETCH:
dump_fetch(out, (PLpgSQL_stmt_fetch *) node);
break;
case PLPGSQL_STMT_CLOSE:
dump_close(out, (PLpgSQL_stmt_close *) node);
break;
case PLPGSQL_STMT_PERFORM:
dump_perform(out, (PLpgSQL_stmt_perform *) node);
break;
case PLPGSQL_STMT_CALL:
dump_call(out, (PLpgSQL_stmt_call *) node);
break;
case PLPGSQL_STMT_COMMIT:
dump_commit(out, (PLpgSQL_stmt_commit *) node);
break;
case PLPGSQL_STMT_ROLLBACK:
dump_rollback(out, (PLpgSQL_stmt_rollback *) node);
break;
default:
elog(ERROR, "unrecognized cmd_type: %d", node->cmd_type);
break;
}
removeTrailingDelimiter(out);
appendStringInfoString(out, "}},");
}
static void
dump_block(StringInfo out, PLpgSQL_stmt_block *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_block");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_STRING_FIELD(label, label, label);
WRITE_STATEMENTS_FIELD(body);
WRITE_OBJ_FIELD(exceptions, dump_exception_block);
removeTrailingDelimiter(out);
}
static void
dump_exception_block(StringInfo out, PLpgSQL_exception_block *node)
{
WRITE_NODE_TYPE("PLpgSQL_exception_block");
WRITE_LIST_FIELD(exc_list, PLpgSQL_exception, dump_exception);
}
static void
dump_exception(StringInfo out, PLpgSQL_exception *node)
{
PLpgSQL_condition *cond;
WRITE_NODE_TYPE("PLpgSQL_exception");
appendStringInfo(out, "\"conditions\":[");
for (cond = node->conditions; cond; cond = cond->next)
{
appendStringInfoString(out, "{");
dump_condition(out, cond);
removeTrailingDelimiter(out);
appendStringInfoString(out, "}},");
}
removeTrailingDelimiter(out);
appendStringInfoString(out, "],");
WRITE_STATEMENTS_FIELD(action);
}
static void
dump_condition(StringInfo out, PLpgSQL_condition *node)
{
WRITE_NODE_TYPE("PLpgSQL_condition");
WRITE_STRING_FIELD(condname, condname, condname);
}
static void
dump_assign(StringInfo out, PLpgSQL_stmt_assign *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_assign");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_INT_FIELD(varno, varno, varno);
WRITE_EXPR_FIELD(expr);
}
static void
dump_if(StringInfo out, PLpgSQL_stmt_if *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_if");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_EXPR_FIELD(cond);
WRITE_STATEMENTS_FIELD(then_body);
WRITE_LIST_FIELD(elsif_list, PLpgSQL_if_elsif, dump_if_elsif);
WRITE_STATEMENTS_FIELD(else_body);
}
static void
dump_if_elsif(StringInfo out, PLpgSQL_if_elsif *node)
{
WRITE_NODE_TYPE("PLpgSQL_if_elsif");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_EXPR_FIELD(cond);
WRITE_STATEMENTS_FIELD(stmts);
}
static void
dump_case(StringInfo out, PLpgSQL_stmt_case *node)
{
ListCell *l;
WRITE_NODE_TYPE("PLpgSQL_stmt_case");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_EXPR_FIELD(t_expr);
WRITE_INT_FIELD(t_varno, t_varno, t_varno);
WRITE_LIST_FIELD(case_when_list, PLpgSQL_case_when, dump_case_when);
WRITE_BOOL_FIELD(have_else, have_else, have_else);
WRITE_STATEMENTS_FIELD(else_stmts);
}
static void
dump_case_when(StringInfo out, PLpgSQL_case_when *node)
{
WRITE_NODE_TYPE("PLpgSQL_case_when");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_EXPR_FIELD(expr);
WRITE_STATEMENTS_FIELD(stmts);
}
static void
dump_loop(StringInfo out, PLpgSQL_stmt_loop *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_loop");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_STRING_FIELD(label, label, label);
WRITE_STATEMENTS_FIELD(body);
}
static void
dump_while(StringInfo out, PLpgSQL_stmt_while *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_while");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_STRING_FIELD(label, label, label);
WRITE_EXPR_FIELD(cond);
WRITE_STATEMENTS_FIELD(body);
}
static void
dump_fori(StringInfo out, PLpgSQL_stmt_fori *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_fori");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_STRING_FIELD(label, label, label);
WRITE_VAR_FIELD(var);
WRITE_EXPR_FIELD(lower);
WRITE_EXPR_FIELD(upper);
WRITE_EXPR_FIELD(step);
WRITE_BOOL_FIELD(reverse, reverse, reverse);
WRITE_STATEMENTS_FIELD(body);
}
static void
dump_fors(StringInfo out, PLpgSQL_stmt_fors *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_fors");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_STRING_FIELD(label, label, label);
WRITE_VARIABLE_FIELD(var);
WRITE_STATEMENTS_FIELD(body);
WRITE_EXPR_FIELD(query);
}
static void
dump_forc(StringInfo out, PLpgSQL_stmt_forc *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_forc");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_STRING_FIELD(label, label, label);
WRITE_VARIABLE_FIELD(var);
WRITE_STATEMENTS_FIELD(body);
WRITE_INT_FIELD(curvar, curvar, curvar);
WRITE_EXPR_FIELD(argquery);
}
static void
dump_foreach_a(StringInfo out, PLpgSQL_stmt_foreach_a *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_foreach_a");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_STRING_FIELD(label, label, label);
WRITE_INT_FIELD(varno, varno, varno);
WRITE_INT_FIELD(slice, slice, slice);
WRITE_EXPR_FIELD(expr);
WRITE_STATEMENTS_FIELD(body);
}
static void
dump_open(StringInfo out, PLpgSQL_stmt_open *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_open");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_INT_FIELD(curvar, curvar, curvar);
WRITE_INT_FIELD(cursor_options, cursor_options, cursor_options);
WRITE_EXPR_FIELD(argquery);
WRITE_EXPR_FIELD(query);
WRITE_EXPR_FIELD(dynquery);
WRITE_LIST_FIELD(params, PLpgSQL_expr, dump_expr);
}
static void
dump_fetch(StringInfo out, PLpgSQL_stmt_fetch *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_fetch");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_VARIABLE_FIELD(target);
WRITE_INT_FIELD(curvar, curvar, curvar);
WRITE_ENUM_FIELD(direction, direction, direction);
WRITE_LONG_FIELD(how_many, how_many, how_many);
WRITE_EXPR_FIELD(expr);
WRITE_BOOL_FIELD(is_move, is_move, is_move);
WRITE_BOOL_FIELD(returns_multiple_rows, returns_multiple_rows, returns_multiple_rows);
}
static void
dump_close(StringInfo out, PLpgSQL_stmt_close *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_close");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_INT_FIELD(curvar, curvar, curvar);
}
static void
dump_perform(StringInfo out, PLpgSQL_stmt_perform *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_perform");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_EXPR_FIELD(expr);
}
static void
dump_call(StringInfo out, PLpgSQL_stmt_call *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_call");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_EXPR_FIELD(expr);
WRITE_BOOL_FIELD(is_call, is_call, is_call);
WRITE_VARIABLE_FIELD(target);
}
static void
dump_commit(StringInfo out, PLpgSQL_stmt_commit *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_commit");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_BOOL_FIELD(chain, chain, chain);
}
static void
dump_rollback(StringInfo out, PLpgSQL_stmt_rollback *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_rollback");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_BOOL_FIELD(chain, chain, chain);
}
static void
dump_exit(StringInfo out, PLpgSQL_stmt_exit *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_exit");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_BOOL_FIELD(is_exit, is_exit, is_exit);
WRITE_STRING_FIELD(label, label, label);
WRITE_EXPR_FIELD(cond);
}
static void
dump_return(StringInfo out, PLpgSQL_stmt_return *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_return");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_EXPR_FIELD(expr);
}
static void
dump_return_next(StringInfo out, PLpgSQL_stmt_return_next *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_return_next");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_EXPR_FIELD(expr);
}
static void
dump_return_query(StringInfo out, PLpgSQL_stmt_return_query *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_return_query");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_EXPR_FIELD(query);
WRITE_EXPR_FIELD(dynquery);
WRITE_LIST_FIELD(params, PLpgSQL_expr, dump_expr);
}
static void
dump_raise(StringInfo out, PLpgSQL_stmt_raise *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_raise");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_INT_FIELD(elog_level, elog_level, elog_level);
WRITE_STRING_FIELD(condname, condname, condname);
WRITE_STRING_FIELD(message, message, message);
WRITE_LIST_FIELD(params, PLpgSQL_expr, dump_expr);
WRITE_LIST_FIELD(options, PLpgSQL_raise_option, dump_raise_option);
}
static void
dump_raise_option(StringInfo out, PLpgSQL_raise_option *node)
{
WRITE_NODE_TYPE("PLpgSQL_raise_option");
WRITE_ENUM_FIELD(opt_type, opt_type, opt_type);
WRITE_EXPR_FIELD(expr);
}
static void
dump_assert(StringInfo out, PLpgSQL_stmt_assert *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_assert");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_EXPR_FIELD(cond);
WRITE_EXPR_FIELD(message);
}
static void
dump_execsql(StringInfo out, PLpgSQL_stmt_execsql *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_execsql");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_EXPR_FIELD(sqlstmt);
WRITE_BOOL_FIELD(into, into, into);
WRITE_BOOL_FIELD(strict, strict, strict);
WRITE_VARIABLE_FIELD(target);
}
static void
dump_dynexecute(StringInfo out, PLpgSQL_stmt_dynexecute *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_dynexecute");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_EXPR_FIELD(query);
WRITE_BOOL_FIELD(into, into, into);
WRITE_BOOL_FIELD(strict, strict, strict);
WRITE_VARIABLE_FIELD(target);
WRITE_LIST_FIELD(params, PLpgSQL_expr, dump_expr);
}
static void
dump_dynfors(StringInfo out, PLpgSQL_stmt_dynfors *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_dynfors");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_STRING_FIELD(label, label, label);
WRITE_VARIABLE_FIELD(var);
WRITE_STATEMENTS_FIELD(body);
WRITE_EXPR_FIELD(query);
WRITE_LIST_FIELD(params, PLpgSQL_expr, dump_expr);
}
static void
dump_getdiag(StringInfo out, PLpgSQL_stmt_getdiag *node)
{
WRITE_NODE_TYPE("PLpgSQL_stmt_getdiag");
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_BOOL_FIELD(is_stacked, is_stacked, is_stacked);
WRITE_LIST_FIELD(diag_items, PLpgSQL_diag_item, dump_getdiag_item);
}
static void
dump_getdiag_item(StringInfo out, PLpgSQL_diag_item *node)
{
WRITE_NODE_TYPE("PLpgSQL_diag_item");
WRITE_STRING_VALUE(kind, plpgsql_getdiag_kindname(node->kind));
WRITE_INT_FIELD(target, target, target);
}
static void
dump_expr(StringInfo out, PLpgSQL_expr *node)
{
WRITE_NODE_TYPE("PLpgSQL_expr");
WRITE_STRING_FIELD(query, query, query);
WRITE_ENUM_FIELD(parseMode, parseMode, parseMode);
}
static void
dump_function(StringInfo out, PLpgSQL_function *node)
{
int i;
PLpgSQL_datum *d;
WRITE_NODE_TYPE("PLpgSQL_function");
WRITE_INT_FIELD(new_varno, new_varno, new_varno);
WRITE_INT_FIELD(old_varno, old_varno, old_varno);
appendStringInfoString(out, "\"datums\":");
appendStringInfoChar(out, '[');
for (i = 0; i < node->ndatums; i++)
{
appendStringInfoChar(out, '{');
d = node->datums[i];
switch (d->dtype)
{
case PLPGSQL_DTYPE_VAR:
dump_var(out, (PLpgSQL_var *) d);
break;
case PLPGSQL_DTYPE_ROW:
dump_row(out, (PLpgSQL_row *) d);
break;
case PLPGSQL_DTYPE_REC:
dump_record(out, (PLpgSQL_rec *) d);
break;
case PLPGSQL_DTYPE_RECFIELD:
dump_record_field(out, (PLpgSQL_recfield *) d);
break;
default:
elog(WARNING, "could not dump unrecognized dtype: %d",
(int) d->dtype);
}
removeTrailingDelimiter(out);
appendStringInfoString(out, "}},");
}
removeTrailingDelimiter(out);
appendStringInfoString(out, "],");
WRITE_BLOCK_FIELD(action);
}
static void
dump_var(StringInfo out, PLpgSQL_var *node)
{
WRITE_NODE_TYPE("PLpgSQL_var");
WRITE_STRING_FIELD(refname, refname, refname);
WRITE_INT_FIELD(lineno, lineno, lineno);
WRITE_OBJ_FIELD(datatype, dump_type);
WRITE_BOOL_FIELD(isconst, isconst, isconst);
WRITE_BOOL_FIELD(notnull, notnull, notnull);
WRITE_EXPR_FIELD(default_val);
WRITE_EXPR_FIELD(cursor_explicit_expr);
WRITE_INT_FIELD(cursor_explicit_argrow, cursor_explicit_argrow, cursor_explicit_argrow);
WRITE_INT_FIELD(cursor_options, cursor_options, cursor_options);
}
static void
dump_variable(StringInfo out, PLpgSQL_variable *node)
{
switch (node->dtype)
{
case PLPGSQL_DTYPE_REC:
dump_record(out, (PLpgSQL_rec *) node);
break;
case PLPGSQL_DTYPE_VAR:
dump_var(out, (PLpgSQL_var *) node);
break;
case PLPGSQL_DTYPE_ROW:
dump_row(out, (PLpgSQL_row *) node);
break;
default:
elog(ERROR, "unrecognized variable type: %d", node->dtype);
break;
}
}
static void
dump_type(StringInfo out, PLpgSQL_type *node)
{
WRITE_NODE_TYPE("PLpgSQL_type");
WRITE_STRING_FIELD(typname, typname, typname);
}
static void
dump_row(StringInfo out, PLpgSQL_row *node)
{
int i = 0;
WRITE_NODE_TYPE("PLpgSQL_row");
WRITE_STRING_FIELD(refname, refname, refname);
WRITE_INT_FIELD(lineno, lineno, lineno);
appendStringInfoString(out, "\"fields\":");
appendStringInfoChar(out, '[');
for (i = 0; i < node->nfields; i++)
{
if (node->fieldnames[i]) {
appendStringInfoChar(out, '{');
WRITE_STRING_VALUE(name, node->fieldnames[i]);
WRITE_INT_VALUE(varno, node->varnos[i]);
removeTrailingDelimiter(out);
appendStringInfoString(out, "},");
} else {
appendStringInfoString(out, "null,");
}
}
removeTrailingDelimiter(out);
appendStringInfoString(out, "],");
}
static void
dump_record(StringInfo out, PLpgSQL_rec *node) {
WRITE_NODE_TYPE("PLpgSQL_rec");
WRITE_STRING_FIELD(refname, refname, refname);
WRITE_INT_FIELD(dno, dno, dno);
WRITE_INT_FIELD(lineno, lineno, lineno);
}
static void
dump_record_field(StringInfo out, PLpgSQL_recfield *node) {
WRITE_NODE_TYPE("PLpgSQL_recfield");
WRITE_STRING_FIELD(fieldname, fieldname, fieldname);
WRITE_INT_FIELD(recparentno, recparentno, recparentno);
}
char *
plpgsqlToJSON(PLpgSQL_function *func)
{
StringInfoData str;
initStringInfo(&str);
appendStringInfoChar(&str, '{');
dump_function(&str, func);
removeTrailingDelimiter(&str);
appendStringInfoString(&str, "}}");
return str.data;
}