1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
#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) // FIXME
#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);
// TODO: Handle this by returning an error instead
Assert(result != NULL);
// TODO: Handle this by returning an error instead
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;
}
|