File: pg_query_readfuncs_protobuf.c

package info (click to toggle)
ruby-pg-query 5.1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 18,248 kB
  • sloc: ansic: 149,767; ruby: 865; makefile: 3
file content (177 lines) | stat: -rw-r--r-- 5,729 bytes parent folder | download
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;
}