#include "pg_query_readfuncs.h"
#include "nodes/nodes.h"
#include "nodes/parsenodes.h"
#include "nodes/pg_list.h"
#include "protobuf/pg_query.pb-c.h"
#define OUT_TYPE(typename, typename_c) PgQuery__##typename_c*
#define READ_COND(typename, typename_c, typename_underscore, typename_underscore_upcase, typename_cast, outname) \
case PG_QUERY__NODE__NODE_##typename_underscore_upcase: \
return (Node *) _read##typename_c(msg->outname);
#define READ_INT_FIELD(outname, outname_json, fldname) node->fldname = msg->outname;
#define READ_UINT_FIELD(outname, outname_json, fldname) node->fldname = msg->outname;
#define READ_LONG_FIELD(outname, outname_json, fldname) node->fldname = msg->outname;
#define READ_FLOAT_FIELD(outname, outname_json, fldname) node->fldname = msg->outname;
#define READ_BOOL_FIELD(outname, outname_json, fldname) node->fldname = msg->outname;
#define READ_CHAR_FIELD(outname, outname_json, fldname) \
if (msg->outname != NULL && strlen(msg->outname) > 0) { \
node->fldname = msg->outname[0]; \
}
#define READ_STRING_FIELD(outname, outname_json, fldname) \
if (msg->outname != NULL && strlen(msg->outname) > 0) { \
node->fldname = pstrdup(msg->outname); \
}
#define READ_ENUM_FIELD(typename, outname, outname_json, fldname) \
node->fldname = _intToEnum##typename(msg->outname);
#define READ_LIST_FIELD(outname, outname_json, fldname) \
{ \
if (msg->n_##outname > 0) \
node->fldname = list_make1(_readNode(msg->outname[0])); \
for (int i = 1; i < msg->n_##outname; i++) \
node->fldname = lappend(node->fldname, _readNode(msg->outname[i])); \
}
#define READ_BITMAPSET_FIELD(outname, outname_json, fldname)
#define READ_NODE_FIELD(outname, outname_json, fldname) \
node->fldname = *_readNode(msg->outname);
#define READ_NODE_PTR_FIELD(outname, outname_json, fldname) \
if (msg->outname != NULL) { \
node->fldname = _readNode(msg->outname); \
}
#define READ_EXPR_PTR_FIELD(outname, outname_json, fldname) \
if (msg->outname != NULL) { \
node->fldname = (Expr *) _readNode(msg->outname); \
}
#define READ_VALUE_FIELD(outname, outname_json, fldname) \
if (msg->outname != NULL) { \
node->fldname = *((Value *) _readNode(msg->outname)); \
}
#define READ_VALUE_PTR_FIELD(outname, outname_json, fldname) \
if (msg->outname != NULL) { \
node->fldname = (Value *) _readNode(msg->outname); \
}
#define READ_SPECIFIC_NODE_FIELD(typename, typename_underscore, outname, outname_json, fldname) \
node->fldname = *_read##typename(msg->outname);
#define READ_SPECIFIC_NODE_PTR_FIELD(typename, typename_underscore, outname, outname_json, fldname) \
if (msg->outname != NULL) { \
node->fldname = _read##typename(msg->outname); \
}
static Node * _readNode(PgQuery__Node *msg);
#include "pg_query_enum_defs.c"
#include "pg_query_readfuncs_defs.c"
static List * _readList(PgQuery__List *msg)
{
List *node = NULL;
if (msg->n_items > 0)
node = list_make1(_readNode(msg->items[0]));
for (int i = 1; i < msg->n_items; i++)
node = lappend(node, _readNode(msg->items[i]));
return node;
}
static Node * _readNode(PgQuery__Node *msg)
{
switch (msg->node_case)
{
#include "pg_query_readfuncs_conds.c"
case PG_QUERY__NODE__NODE_INTEGER:
return (Node *) makeInteger(msg->integer->ival);
case PG_QUERY__NODE__NODE_FLOAT:
return (Node *) makeFloat(pstrdup(msg->float_->str));
case PG_QUERY__NODE__NODE_STRING:
return (Node *) makeString(pstrdup(msg->string->str));
case PG_QUERY__NODE__NODE_BIT_STRING:
return (Node *) makeBitString(pstrdup(msg->bit_string->str));
case PG_QUERY__NODE__NODE_NULL:
{
Value *v = makeNode(Value);
v->type = T_Null;
return (Node *) v;
}
case PG_QUERY__NODE__NODE_LIST:
return (Node *) _readList(msg->list);
case PG_QUERY__NODE__NODE__NOT_SET:
return NULL;
default:
elog(ERROR, "unsupported protobuf node type: %d",
(int) msg->node_case);
}
}
List * pg_query_protobuf_to_nodes(PgQueryProtobuf protobuf)
{
PgQuery__ParseResult *result = NULL;
List * list = NULL;
size_t i = 0;
result = pg_query__parse_result__unpack(NULL, protobuf.len, (const uint8_t *) protobuf.data);
Assert(result != NULL);
Assert(result->version == PG_VERSION_NUM);
if (result->n_stmts > 0)
list = list_make1(_readRawStmt(result->stmts[0]));
for (i = 1; i < result->n_stmts; i++)
list = lappend(list, _readRawStmt(result->stmts[i]));
pg_query__parse_result__free_unpacked(result, NULL);
return list;
}