1#include <stdexcept>
2#include <string>
3#include <thread>
4#include <mutex>
5#include "pg_functions.hpp"
6#include "parser/parser.hpp"
7#include <stdarg.h>
8#include <mutex>
9#include <cstring>
10
11
12// max parse tree size approx 100 MB, should be enough
13#define PG_MALLOC_SIZE 10240
14#define PG_MALLOC_LIMIT 1000
15
16typedef struct pg_parser_state_str parser_state;
17struct pg_parser_state_str {
18 int pg_err_code;
19 int pg_err_pos;
20 char pg_err_msg[BUFSIZ];
21
22 size_t malloc_pos;
23 size_t malloc_ptr_idx;
24 char *malloc_ptrs[PG_MALLOC_LIMIT];
25};
26
27static __thread parser_state pg_parser_state;
28
29#ifndef __GNUC__
30__thread PGNode *newNodeMacroHolder;
31#endif
32
33static void allocate_new(parser_state* state, size_t n) {
34 if (state->malloc_ptr_idx + 1 >= PG_MALLOC_LIMIT) {
35 throw std::runtime_error("Memory allocation failure");
36 }
37 if (n < PG_MALLOC_SIZE) {
38 n = PG_MALLOC_SIZE;
39 }
40 char* base_ptr = (char*) malloc(n);
41 if (!base_ptr) {
42 throw std::runtime_error("Memory allocation failure");
43 }
44 state->malloc_ptrs[state->malloc_ptr_idx] = base_ptr;
45 state->malloc_ptr_idx++;
46 state->malloc_pos = 0;
47}
48
49
50void* palloc(size_t n) {
51 if (pg_parser_state.malloc_pos + n > PG_MALLOC_SIZE) {
52 allocate_new(&pg_parser_state, n);
53 }
54
55 void *ptr = pg_parser_state.malloc_ptrs[pg_parser_state.malloc_ptr_idx - 1] + pg_parser_state.malloc_pos;
56 memset(ptr, 0, n);
57 pg_parser_state.malloc_pos += n;
58 return ptr;
59}
60
61
62
63void pg_parser_init() {
64 pg_parser_state.pg_err_code = PGUNDEFINED;
65 pg_parser_state.pg_err_msg[0] = '\0';
66
67 pg_parser_state.malloc_ptr_idx = 0;
68 allocate_new(&pg_parser_state, 1);
69}
70
71void pg_parser_parse(const char* query, parse_result *res) {
72
73 res->parse_tree = nullptr;
74 try{
75 res->parse_tree = raw_parser(query);
76 res->success = pg_parser_state.pg_err_code == PGUNDEFINED;
77 } catch (...) {
78 res->success = false;
79
80 }
81 res->error_message = pg_parser_state.pg_err_msg;
82 res->error_location = pg_parser_state.pg_err_pos;
83}
84
85
86void pg_parser_cleanup() {
87 for (size_t ptr_idx = 0; ptr_idx < pg_parser_state.malloc_ptr_idx; ptr_idx++) {
88 char *ptr = pg_parser_state.malloc_ptrs[ptr_idx];
89 if (ptr) {
90 free(ptr);
91 pg_parser_state.malloc_ptrs[ptr_idx] = nullptr;
92 }
93 }
94}
95
96int ereport(int code, ...) {
97 std::string err = "parser error : " + std::string(pg_parser_state.pg_err_msg);
98 throw std::runtime_error(err);
99}
100void elog(int code, const char* fmt,...) {
101 throw std::runtime_error("elog NOT IMPLEMENTED");
102}
103int errcode(int sqlerrcode) {
104 pg_parser_state.pg_err_code = sqlerrcode;
105 return 1;
106}
107int errmsg(const char* fmt, ...) {
108 va_list argptr;
109 va_start(argptr, fmt);
110 vsnprintf(pg_parser_state.pg_err_msg, BUFSIZ, fmt, argptr);
111 va_end(argptr);
112 return 1;
113}
114int errhint(const char* msg) {
115 throw std::runtime_error("errhint NOT IMPLEMENTED");
116}
117int errmsg_internal(const char *fmt,...) {
118 throw std::runtime_error("errmsg_internal NOT IMPLEMENTED");
119}
120int errdetail(const char *fmt,...) {
121 throw std::runtime_error("errdetail NOT IMPLEMENTED");
122}
123int errposition(int cursorpos) {
124 pg_parser_state.pg_err_pos = cursorpos;
125 return 1;
126}
127
128
129char *
130psprintf(const char *fmt,...) {
131 char buf[BUFSIZ];
132 va_list args;
133 size_t newlen;
134
135 // attempt one: use stack buffer and determine length
136 va_start(args, fmt);
137 newlen = vsnprintf(buf, BUFSIZ, fmt, args);
138 va_end(args);
139 if (newlen < BUFSIZ) {
140 return pstrdup(buf);
141 }
142
143 // attempt two, malloc
144 char* mbuf = (char*) palloc(newlen);
145 va_start(args, fmt);
146 vsnprintf(mbuf, newlen, fmt, args);
147 va_end(args);
148 return mbuf;
149}
150
151char *pstrdup(const char *in) {
152 char* new_str = (char*) palloc(strlen(in)+1);
153 memcpy(new_str, in, strlen(in));
154 return new_str;
155}
156
157void pfree(void* ptr) {
158 // nop, we free up entire context on parser cleanup
159}
160void* palloc0fast(size_t n) { // very fast
161 return palloc(n);
162}
163void* repalloc(void* ptr, size_t n) {
164 return palloc(n);
165}
166char *NameListToString(PGList *names) {
167 throw std::runtime_error("NameListToString NOT IMPLEMENTED");
168}
169void * copyObject(const void *from) {
170 throw std::runtime_error("copyObject NOT IMPLEMENTED");
171}
172bool equal(const void *a, const void *b) {
173 throw std::runtime_error("equal NOT IMPLEMENTED");
174}
175int exprLocation(const PGNode *expr) {
176 throw std::runtime_error("exprLocation NOT IMPLEMENTED");
177}
178bool pg_verifymbstr(const char *mbstr, int len, bool noError) {
179 throw std::runtime_error("pg_verifymbstr NOT IMPLEMENTED");
180}
181
182int pg_database_encoding_max_length(void) {
183 return 4; // UTF8
184}
185
186static int
187pg_utf_mblen(const unsigned char *s)
188{
189 int len;
190
191 if ((*s & 0x80) == 0)
192 len = 1;
193 else if ((*s & 0xe0) == 0xc0)
194 len = 2;
195 else if ((*s & 0xf0) == 0xe0)
196 len = 3;
197 else if ((*s & 0xf8) == 0xf0)
198 len = 4;
199#ifdef NOT_USED
200 else if ((*s & 0xfc) == 0xf8)
201 len = 5;
202 else if ((*s & 0xfe) == 0xfc)
203 len = 6;
204#endif
205 else
206 len = 1;
207 return len;
208}
209
210
211int pg_mbstrlen_with_len(const char *mbstr, int limit) {
212 int len = 0;
213 while (limit > 0 && *mbstr) {
214 int l = pg_utf_mblen((const unsigned char*) mbstr);
215 limit -= l;
216 mbstr += l;
217 len++;
218 }
219 return len;
220}
221
222
223int pg_mbcliplen(const char *mbstr, int len, int limit) {
224 throw std::runtime_error("pg_mbcliplen NOT IMPLEMENTED");
225}
226int pg_mblen(const char *mbstr) {
227 throw std::runtime_error("pg_mblen NOT IMPLEMENTED");
228}
229PGDefElem * defWithOids(bool value) {
230 throw std::runtime_error("defWithOids NOT IMPLEMENTED");
231}
232unsigned char *unicode_to_utf8(pg_wchar c, unsigned char *utf8string) {
233 throw std::runtime_error("unicode_to_utf8 NOT IMPLEMENTED");
234}
235
236