#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_UINT64_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_ABSTRACT_PTR_FIELD(outname, outname_json, fldname, fldtype) \
if (msg->outname != NULL) { \
node->fldname = (fldtype) _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);
static String *
_readString(PgQuery__String* msg)
{
return makeString(pstrdup(msg->sval));
}
#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_->fval));
case PG_QUERY__NODE__NODE_BOOLEAN:
return (Node *) makeBoolean(msg->boolean->boolval);
case PG_QUERY__NODE__NODE_STRING:
return (Node *) makeString(pstrdup(msg->string->sval));
case PG_QUERY__NODE__NODE_BIT_STRING:
return (Node *) makeBitString(pstrdup(msg->bit_string->bsval));
case PG_QUERY__NODE__NODE_A_CONST: {
A_Const *ac = makeNode(A_Const);
ac->location = msg->a_const->location;
if (msg->a_const->isnull) {
ac->isnull = true;
} else {
switch (msg->a_const->val_case) {
case PG_QUERY__A__CONST__VAL_IVAL:
ac->val.ival = *makeInteger(msg->a_const->ival->ival);
break;
case PG_QUERY__A__CONST__VAL_FVAL:
ac->val.fval = *makeFloat(pstrdup(msg->a_const->fval->fval));
break;
case PG_QUERY__A__CONST__VAL_BOOLVAL:
ac->val.boolval = *makeBoolean(msg->a_const->boolval->boolval);
break;
case PG_QUERY__A__CONST__VAL_SVAL:
ac->val.sval = *makeString(pstrdup(msg->a_const->sval->sval));
break;
case PG_QUERY__A__CONST__VAL_BSVAL:
ac->val.bsval = *makeBitString(pstrdup(msg->a_const->bsval->bsval));
break;
case PG_QUERY__A__CONST__VAL__NOT_SET:
case _PG_QUERY__A__CONST__VAL__CASE_IS_INT_SIZE:
Assert(false);
break;
}
}
return (Node *) ac;
}
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;
}