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 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
|
#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) // 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);
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);
// 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;
}
|