Coverage Report

Created: 2026-06-13 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libpg_query/src/pg_query_outfuncs_protobuf.c
Line
Count
Source
1
#include "pg_query_outfuncs.h"
2
3
#include "postgres.h"
4
#include <ctype.h>
5
#include "access/relation.h"
6
#include "nodes/parsenodes.h"
7
#include "nodes/plannodes.h"
8
#include "nodes/value.h"
9
#include "utils/datum.h"
10
11
#include "protobuf/pg_query.pb-c.h"
12
13
#define OUT_TYPE(typename, typename_c) PgQuery__##typename_c*
14
15
#define OUT_NODE(typename, typename_c, typename_underscore, typename_underscore_upcase, typename_cast, fldname) \
16
  { \
17
    PgQuery__##typename_c *__node = palloc(sizeof(PgQuery__##typename_c)); \
18
  pg_query__##typename_underscore##__init(__node); \
19
    _out##typename_c(__node, (const typename_cast *) obj); \
20
  out->fldname = __node; \
21
  out->node_case = PG_QUERY__NODE__NODE_##typename_underscore_upcase; \
22
  }
23
24
0
#define WRITE_INT_FIELD(outname, outname_json, fldname) out->outname = node->fldname;
25
0
#define WRITE_UINT_FIELD(outname, outname_json, fldname) out->outname = node->fldname;
26
0
#define WRITE_UINT64_FIELD(outname, outname_json, fldname) out->outname = node->fldname;
27
0
#define WRITE_LONG_FIELD(outname, outname_json, fldname) out->outname = node->fldname;
28
0
#define WRITE_FLOAT_FIELD(outname, outname_json, fldname) out->outname = node->fldname;
29
0
#define WRITE_BOOL_FIELD(outname, outname_json, fldname) out->outname = node->fldname;
30
31
#define WRITE_CHAR_FIELD(outname, outname_json, fldname) \
32
0
  if (node->fldname != 0) { \
33
0
    out->outname = palloc(sizeof(char) * 2); \
34
0
    out->outname[0] = node->fldname; \
35
0
    out->outname[1] = '\0'; \
36
0
  }
37
#define WRITE_STRING_FIELD(outname, outname_json, fldname) \
38
0
  if (node->fldname != NULL) { \
39
0
    out->outname = pstrdup(node->fldname); \
40
0
  }
41
42
#define WRITE_ENUM_FIELD(typename, outname, outname_json, fldname) \
43
0
  out->outname = _enumToInt##typename(node->fldname);
44
45
#define WRITE_LIST_FIELD(outname, outname_json, fldname) \
46
0
  if (node->fldname != NULL) { \
47
0
    out->n_##outname = list_length(node->fldname); \
48
0
    out->outname = palloc(sizeof(PgQuery__Node*) * out->n_##outname); \
49
0
    for (int i = 0; i < out->n_##outname; i++) \
50
0
      { \
51
0
      PgQuery__Node *__node = palloc(sizeof(PgQuery__Node)); \
52
0
      pg_query__node__init(__node); \
53
0
      out->outname[i] = __node; \
54
0
      _outNode(out->outname[i], list_nth(node->fldname, i)); \
55
0
      } \
56
0
    }
57
58
#define WRITE_BITMAPSET_FIELD(outname, outname_json, fldname) \
59
0
  if (!bms_is_empty(node->fldname)) \
60
0
  { \
61
0
    int x = -1; \
62
0
    int i = 0; \
63
0
    out->n_##outname = bms_num_members(node->fldname); \
64
0
    out->outname = palloc(sizeof(PgQuery__Node*) * out->n_##outname); \
65
0
    while ((x = bms_next_member(node->fldname, x)) >= 0) \
66
0
      out->outname[i++] = x; \
67
0
    }
68
69
#define WRITE_NODE_FIELD(outname, outname_json, fldname) \
70
  { \
71
    PgQuery__Node *__node = palloc(sizeof(PgQuery__Node)); \
72
    pg_query__node__init(__node); \
73
    out->outname = __node; \
74
    _outNode(out->outname, &node->fldname); \
75
  }
76
77
#define WRITE_NODE_PTR_FIELD(outname, outname_json, fldname) \
78
0
  if (node->fldname != NULL) { \
79
0
    PgQuery__Node *__node = palloc(sizeof(PgQuery__Node)); \
80
0
    pg_query__node__init(__node); \
81
0
    out->outname = __node; \
82
0
    _outNode(out->outname, node->fldname); \
83
0
  }
84
85
#define WRITE_SPECIFIC_NODE_FIELD(typename, typename_underscore, outname, outname_json, fldname) \
86
0
  { \
87
0
    PgQuery__##typename *__node = palloc(sizeof(PgQuery__##typename)); \
88
0
    pg_query__##typename_underscore##__init(__node); \
89
0
    _out##typename(__node, &node->fldname); \
90
0
    out->outname = __node; \
91
0
  }
92
93
#define WRITE_SPECIFIC_NODE_PTR_FIELD(typename, typename_underscore, outname, outname_json, fldname) \
94
0
  if (node->fldname != NULL) { \
95
0
    PgQuery__##typename *__node = palloc(sizeof(PgQuery__##typename)); \
96
0
    pg_query__##typename_underscore##__init(__node); \
97
0
    _out##typename(__node, node->fldname); \
98
0
    out->outname = __node; \
99
0
  }
100
101
static void _outNode(PgQuery__Node* out, const void *obj);
102
103
static void
104
_outList(PgQuery__List* out, const List *node)
105
0
{
106
0
  const ListCell *lc;
107
0
  int i = 0;
108
0
  out->n_items = list_length(node);
109
0
  out->items = palloc(sizeof(PgQuery__Node*) * out->n_items);
110
0
    foreach(lc, node)
111
0
    {
112
0
    out->items[i] = palloc(sizeof(PgQuery__Node));
113
0
    pg_query__node__init(out->items[i]);
114
0
      _outNode(out->items[i], lfirst(lc));
115
0
    i++;
116
0
    }
117
0
}
118
119
static void
120
_outIntList(PgQuery__IntList* out, const List *node)
121
0
{
122
0
  const ListCell *lc;
123
0
  int i = 0;
124
0
  out->n_items = list_length(node);
125
0
  out->items = palloc(sizeof(PgQuery__Node*) * out->n_items);
126
0
    foreach(lc, node)
127
0
    {
128
0
    out->items[i] = palloc(sizeof(PgQuery__Node));
129
0
    pg_query__node__init(out->items[i]);
130
0
      _outNode(out->items[i], lfirst(lc));
131
0
    i++;
132
0
    }
133
0
}
134
135
static void
136
_outOidList(PgQuery__OidList* out, const List *node)
137
0
{
138
0
  const ListCell *lc;
139
0
  int i = 0;
140
0
  out->n_items = list_length(node);
141
0
  out->items = palloc(sizeof(PgQuery__Node*) * out->n_items);
142
0
    foreach(lc, node)
143
0
    {
144
0
    out->items[i] = palloc(sizeof(PgQuery__Node));
145
0
    pg_query__node__init(out->items[i]);
146
0
      _outNode(out->items[i], lfirst(lc));
147
0
    i++;
148
0
    }
149
0
}
150
151
// TODO: Add Bitmapset
152
153
static void
154
_outInteger(PgQuery__Integer* out, const Integer *node)
155
0
{
156
0
  out->ival = node->ival;
157
0
}
158
159
static void
160
_outFloat(PgQuery__Float* out, const Float *node)
161
0
{
162
0
  out->fval = node->fval;
163
0
}
164
165
static void
166
_outBoolean(PgQuery__Boolean* out, const Boolean *node)
167
0
{
168
0
  out->boolval = node->boolval;
169
0
}
170
171
static void
172
_outString(PgQuery__String* out, const String *node)
173
0
{
174
0
  out->sval = node->sval;
175
0
}
176
177
static void
178
_outBitString(PgQuery__BitString* out, const BitString *node)
179
0
{
180
0
  out->bsval = node->bsval;
181
0
}
182
183
static void
184
_outAConst(PgQuery__AConst* out, const A_Const *node)
185
0
{
186
0
  out->isnull = node->isnull;
187
0
  out->location = node->location;
188
189
0
  if (!node->isnull) {
190
0
    switch (nodeTag(&node->val.node)) {
191
0
      case T_Integer: {
192
0
        PgQuery__Integer *value = palloc(sizeof(PgQuery__Integer));
193
0
        pg_query__integer__init(value);
194
0
        value->ival = node->val.ival.ival;
195
196
0
        out->val_case = PG_QUERY__A__CONST__VAL_IVAL;
197
0
        out->ival = value;
198
0
        break;
199
0
      }
200
0
      case T_Float: {
201
0
        PgQuery__Float *value = palloc(sizeof(PgQuery__Float));
202
0
        pg_query__float__init(value);
203
0
        value->fval = pstrdup(node->val.fval.fval);
204
205
0
        out->val_case = PG_QUERY__A__CONST__VAL_FVAL;
206
0
        out->fval = value;
207
0
        break;
208
0
      }
209
0
      case T_Boolean: {
210
0
        PgQuery__Boolean *value = palloc(sizeof(PgQuery__Boolean));
211
0
        pg_query__boolean__init(value);
212
0
        value->boolval = node->val.boolval.boolval;
213
214
0
        out->val_case = PG_QUERY__A__CONST__VAL_BOOLVAL;
215
0
        out->boolval = value;
216
0
        break;
217
0
      }
218
0
      case T_String: {
219
0
        PgQuery__String *value = palloc(sizeof(PgQuery__String));
220
0
  pg_query__string__init(value);
221
0
  value->sval = pstrdup(node->val.sval.sval);
222
223
0
  out->val_case = PG_QUERY__A__CONST__VAL_SVAL;
224
0
  out->sval = value;
225
0
  break;
226
0
      }
227
0
      case T_BitString: {
228
0
        PgQuery__BitString *value = palloc(sizeof(PgQuery__BitString));
229
0
  pg_query__bit_string__init(value);
230
0
  value->bsval = pstrdup(node->val.bsval.bsval);
231
232
0
  out->val_case = PG_QUERY__A__CONST__VAL_BSVAL;
233
0
  out->bsval = value;
234
0
  break;
235
0
      }
236
0
      default:
237
        // Unreachable
238
0
        Assert(false);
239
0
    }
240
0
  }
241
0
}
242
243
#include "pg_query_enum_defs.c"
244
#include "pg_query_outfuncs_defs.c"
245
246
static void
247
_outNode(PgQuery__Node* out, const void *obj)
248
{
249
  if (obj == NULL)
250
    return; // Keep out as NULL
251
252
  switch (nodeTag(obj))
253
  {
254
    #include "pg_query_outfuncs_conds.c"
255
256
    default:
257
      printf("could not dump unrecognized node type: %d", (int) nodeTag(obj));
258
      elog(WARNING, "could not dump unrecognized node type: %d",
259
          (int) nodeTag(obj));
260
261
      return;
262
  }
263
}
264
265
PgQueryProtobuf
266
pg_query_nodes_to_protobuf(const void *obj)
267
0
{
268
0
  PgQueryProtobuf protobuf;
269
0
  const ListCell *lc;
270
0
  int i = 0;
271
0
  PgQuery__ParseResult parse_result = PG_QUERY__PARSE_RESULT__INIT;
272
273
0
  parse_result.version = PG_VERSION_NUM;
274
275
0
  if (obj == NULL) {
276
0
    parse_result.n_stmts = 0;
277
0
    parse_result.stmts = NULL;
278
0
  }
279
0
  else
280
0
  {
281
0
    parse_result.n_stmts = list_length(obj);
282
0
    parse_result.stmts = palloc(sizeof(PgQuery__RawStmt*) * parse_result.n_stmts);
283
0
    foreach(lc, obj)
284
0
    {
285
0
      parse_result.stmts[i] = palloc(sizeof(PgQuery__RawStmt));
286
0
      pg_query__raw_stmt__init(parse_result.stmts[i]);
287
0
      _outRawStmt(parse_result.stmts[i], lfirst(lc));
288
0
      i++;
289
0
    }
290
0
  }
291
292
0
  protobuf.len = pg_query__parse_result__get_packed_size(&parse_result);
293
  // Note: This is intentionally malloc so exiting the memory context doesn't free this
294
0
  protobuf.data = malloc(sizeof(char) * protobuf.len);
295
0
  pg_query__parse_result__pack(&parse_result, (void*) protobuf.data); 
296
297
0
  return protobuf;
298
0
}