#include "pg_query_outfuncs.h"
#include "postgres.h"
#include <ctype.h>
#include "access/relation.h"
#include "nodes/parsenodes.h"
#include "nodes/plannodes.h"
#include "nodes/value.h"
#include "utils/datum.h"
#include "protobuf/pg_query.pb-c.h"
#define OUT_TYPE(typename, typename_c) PgQuery__##typename_c*
#define OUT_NODE(typename, typename_c, typename_underscore, typename_underscore_upcase, typename_cast, fldname) \
{ \
PgQuery__##typename_c *__node = palloc(sizeof(PgQuery__##typename_c)); \
pg_query__##typename_underscore##__init(__node); \
_out##typename_c(__node, (const typename_cast *) obj); \
out->fldname = __node; \
out->node_case = PG_QUERY__NODE__NODE_##typename_underscore_upcase; \
}
#define WRITE_INT_FIELD(outname, outname_json, fldname) out->outname = node->fldname;
#define WRITE_UINT_FIELD(outname, outname_json, fldname) out->outname = node->fldname;
#define WRITE_UINT64_FIELD(outname, outname_json, fldname) out->outname = node->fldname;
#define WRITE_LONG_FIELD(outname, outname_json, fldname) out->outname = node->fldname;
#define WRITE_FLOAT_FIELD(outname, outname_json, fldname) out->outname = node->fldname;
#define WRITE_BOOL_FIELD(outname, outname_json, fldname) out->outname = node->fldname;
#define WRITE_CHAR_FIELD(outname, outname_json, fldname) \
if (node->fldname != 0) { \
out->outname = palloc(sizeof(char) * 2); \
out->outname[0] = node->fldname; \
out->outname[1] = '\0'; \
}
#define WRITE_STRING_FIELD(outname, outname_json, fldname) \
if (node->fldname != NULL) { \
out->outname = pstrdup(node->fldname); \
}
#define WRITE_ENUM_FIELD(typename, outname, outname_json, fldname) \
out->outname = _enumToInt##typename(node->fldname);
#define WRITE_LIST_FIELD(outname, outname_json, fldname) \
if (node->fldname != NULL) { \
out->n_##outname = list_length(node->fldname); \
out->outname = palloc(sizeof(PgQuery__Node*) * out->n_##outname); \
for (int i = 0; i < out->n_##outname; i++) \
{ \
PgQuery__Node *__node = palloc(sizeof(PgQuery__Node)); \
pg_query__node__init(__node); \
out->outname[i] = __node; \
_outNode(out->outname[i], list_nth(node->fldname, i)); \
} \
}
#define WRITE_BITMAPSET_FIELD(outname, outname_json, fldname) \
if (!bms_is_empty(node->fldname)) \
{ \
int x = -1; \
int i = 0; \
out->n_##outname = bms_num_members(node->fldname); \
out->outname = palloc(sizeof(PgQuery__Node*) * out->n_##outname); \
while ((x = bms_next_member(node->fldname, x)) >= 0) \
out->outname[i++] = x; \
}
#define WRITE_NODE_FIELD(outname, outname_json, fldname) \
{ \
PgQuery__Node *__node = palloc(sizeof(PgQuery__Node)); \
pg_query__node__init(__node); \
out->outname = __node; \
_outNode(out->outname, &node->fldname); \
}
#define WRITE_NODE_PTR_FIELD(outname, outname_json, fldname) \
if (node->fldname != NULL) { \
PgQuery__Node *__node = palloc(sizeof(PgQuery__Node)); \
pg_query__node__init(__node); \
out->outname = __node; \
_outNode(out->outname, node->fldname); \
}
#define WRITE_SPECIFIC_NODE_FIELD(typename, typename_underscore, outname, outname_json, fldname) \
{ \
PgQuery__##typename *__node = palloc(sizeof(PgQuery__##typename)); \
pg_query__##typename_underscore##__init(__node); \
_out##typename(__node, &node->fldname); \
out->outname = __node; \
}
#define WRITE_SPECIFIC_NODE_PTR_FIELD(typename, typename_underscore, outname, outname_json, fldname) \
if (node->fldname != NULL) { \
PgQuery__##typename *__node = palloc(sizeof(PgQuery__##typename)); \
pg_query__##typename_underscore##__init(__node); \
_out##typename(__node, node->fldname); \
out->outname = __node; \
}
static void _outNode(PgQuery__Node* out, const void *obj);
static void
_outList(PgQuery__List* out, const List *node)
{
const ListCell *lc;
int i = 0;
out->n_items = list_length(node);
out->items = palloc(sizeof(PgQuery__Node*) * out->n_items);
foreach(lc, node)
{
out->items[i] = palloc(sizeof(PgQuery__Node));
pg_query__node__init(out->items[i]);
_outNode(out->items[i], lfirst(lc));
i++;
}
}
static void
_outIntList(PgQuery__IntList* out, const List *node)
{
const ListCell *lc;
int i = 0;
out->n_items = list_length(node);
out->items = palloc(sizeof(PgQuery__Node*) * out->n_items);
foreach(lc, node)
{
out->items[i] = palloc(sizeof(PgQuery__Node));
pg_query__node__init(out->items[i]);
_outNode(out->items[i], lfirst(lc));
i++;
}
}
static void
_outOidList(PgQuery__OidList* out, const List *node)
{
const ListCell *lc;
int i = 0;
out->n_items = list_length(node);
out->items = palloc(sizeof(PgQuery__Node*) * out->n_items);
foreach(lc, node)
{
out->items[i] = palloc(sizeof(PgQuery__Node));
pg_query__node__init(out->items[i]);
_outNode(out->items[i], lfirst(lc));
i++;
}
}
static void
_outInteger(PgQuery__Integer* out, const Integer *node)
{
out->ival = node->ival;
}
static void
_outFloat(PgQuery__Float* out, const Float *node)
{
out->fval = node->fval;
}
static void
_outBoolean(PgQuery__Boolean* out, const Boolean *node)
{
out->boolval = node->boolval;
}
static void
_outString(PgQuery__String* out, const String *node)
{
out->sval = node->sval;
}
static void
_outBitString(PgQuery__BitString* out, const BitString *node)
{
out->bsval = node->bsval;
}
static void
_outAConst(PgQuery__AConst* out, const A_Const *node)
{
out->isnull = node->isnull;
out->location = node->location;
if (!node->isnull) {
switch (nodeTag(&node->val.node)) {
case T_Integer: {
PgQuery__Integer *value = palloc(sizeof(PgQuery__Integer));
pg_query__integer__init(value);
value->ival = node->val.ival.ival;
out->val_case = PG_QUERY__A__CONST__VAL_IVAL;
out->ival = value;
break;
}
case T_Float: {
PgQuery__Float *value = palloc(sizeof(PgQuery__Float));
pg_query__float__init(value);
value->fval = pstrdup(node->val.fval.fval);
out->val_case = PG_QUERY__A__CONST__VAL_FVAL;
out->fval = value;
break;
}
case T_Boolean: {
PgQuery__Boolean *value = palloc(sizeof(PgQuery__Boolean));
pg_query__boolean__init(value);
value->boolval = node->val.boolval.boolval;
out->val_case = PG_QUERY__A__CONST__VAL_BOOLVAL;
out->boolval = value;
break;
}
case T_String: {
PgQuery__String *value = palloc(sizeof(PgQuery__String));
pg_query__string__init(value);
value->sval = pstrdup(node->val.sval.sval);
out->val_case = PG_QUERY__A__CONST__VAL_SVAL;
out->sval = value;
break;
}
case T_BitString: {
PgQuery__BitString *value = palloc(sizeof(PgQuery__BitString));
pg_query__bit_string__init(value);
value->bsval = pstrdup(node->val.bsval.bsval);
out->val_case = PG_QUERY__A__CONST__VAL_BSVAL;
out->bsval = value;
break;
}
default:
Assert(false);
}
}
}
#include "pg_query_enum_defs.c"
#include "pg_query_outfuncs_defs.c"
static void
_outNode(PgQuery__Node* out, const void *obj)
{
if (obj == NULL)
return;
switch (nodeTag(obj))
{
#include "pg_query_outfuncs_conds.c"
default:
printf("could not dump unrecognized node type: %d", (int) nodeTag(obj));
elog(WARNING, "could not dump unrecognized node type: %d",
(int) nodeTag(obj));
return;
}
}
PgQueryProtobuf
pg_query_nodes_to_protobuf(const void *obj)
{
PgQueryProtobuf protobuf;
const ListCell *lc;
int i = 0;
PgQuery__ParseResult parse_result = PG_QUERY__PARSE_RESULT__INIT;
parse_result.version = PG_VERSION_NUM;
if (obj == NULL) {
parse_result.n_stmts = 0;
parse_result.stmts = NULL;
}
else
{
parse_result.n_stmts = list_length(obj);
parse_result.stmts = palloc(sizeof(PgQuery__RawStmt*) * parse_result.n_stmts);
foreach(lc, obj)
{
parse_result.stmts[i] = palloc(sizeof(PgQuery__RawStmt));
pg_query__raw_stmt__init(parse_result.stmts[i]);
_outRawStmt(parse_result.stmts[i], lfirst(lc));
i++;
}
}
protobuf.len = pg_query__parse_result__get_packed_size(&parse_result);
protobuf.data = malloc(sizeof(char) * protobuf.len);
pg_query__parse_result__pack(&parse_result, (void*) protobuf.data);
return protobuf;
}