File: pg_query_readfuncs_protobuf.c

package info (click to toggle)
ruby-gitlab-pg-query 2.0.4-3
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 15,584 kB
  • sloc: ansic: 143,939; ruby: 2,096; makefile: 4
file content (142 lines) | stat: -rw-r--r-- 4,566 bytes parent folder | download | duplicates (2)
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;
}