agoo 2.7.0 → 2.8.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of agoo might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/ext/agoo/agoo.c +25 -20
- data/ext/agoo/con.c +35 -35
- data/ext/agoo/error_stream.c +10 -8
- data/ext/agoo/gqlcobj.c +25 -0
- data/ext/agoo/gqlcobj.h +14 -0
- data/ext/agoo/gqleval.c +24 -11
- data/ext/agoo/gqleval.h +2 -0
- data/ext/agoo/gqlintro.c +30 -54
- data/ext/agoo/gqljson.c +36 -32
- data/ext/agoo/gqlvalue.c +105 -52
- data/ext/agoo/gqlvalue.h +3 -0
- data/ext/agoo/graphql.c +110 -80
- data/ext/agoo/graphql.h +17 -13
- data/ext/agoo/log.c +16 -12
- data/ext/agoo/rack_logger.c +4 -1
- data/ext/agoo/request.c +7 -9
- data/ext/agoo/rgraphql.c +41 -30
- data/ext/agoo/rresponse.c +7 -6
- data/ext/agoo/rserver.c +35 -22
- data/ext/agoo/sdl.c +234 -117
- data/ext/agoo/server.c +5 -5
- data/ext/agoo/text.c +23 -9
- data/lib/agoo/version.rb +1 -1
- data/test/graphql_test.rb +33 -27
- metadata +2 -2
data/ext/agoo/rserver.c
CHANGED
@@ -11,6 +11,7 @@
|
|
11
11
|
#include <ruby/thread.h>
|
12
12
|
#include <ruby/encoding.h>
|
13
13
|
|
14
|
+
#include "atomic.h"
|
14
15
|
#include "bind.h"
|
15
16
|
#include "con.h"
|
16
17
|
#include "debug.h"
|
@@ -33,7 +34,8 @@
|
|
33
34
|
#include "upgraded.h"
|
34
35
|
#include "websocket.h"
|
35
36
|
|
36
|
-
extern void
|
37
|
+
extern void agoo_shutdown();
|
38
|
+
extern sig_atomic_t agoo_stop;
|
37
39
|
|
38
40
|
static VALUE server_mod = Qundef;
|
39
41
|
|
@@ -160,7 +162,7 @@ configure(agooErr err, int port, const char *root, VALUE options) {
|
|
160
162
|
if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("bind"))))) {
|
161
163
|
int len;
|
162
164
|
int i;
|
163
|
-
|
165
|
+
|
164
166
|
switch (rb_type(v)) {
|
165
167
|
case T_STRING:
|
166
168
|
url_bind(v);
|
@@ -171,7 +173,7 @@ configure(agooErr err, int port, const char *root, VALUE options) {
|
|
171
173
|
url_bind(rb_ary_entry(v, i));
|
172
174
|
}
|
173
175
|
break;
|
174
|
-
default:
|
176
|
+
default:
|
175
177
|
rb_raise(rb_eArgError, "bind option must be a String or Array of Strings.");
|
176
178
|
break;
|
177
179
|
}
|
@@ -317,7 +319,7 @@ rescue_error(VALUE x) {
|
|
317
319
|
int blen = RARRAY_LEN(bt);
|
318
320
|
int i;
|
319
321
|
VALUE rline;
|
320
|
-
|
322
|
+
|
321
323
|
for (i = 0; i < blen; i++) {
|
322
324
|
rline = rb_ary_entry(bt, i);
|
323
325
|
}
|
@@ -357,7 +359,7 @@ header_cb(VALUE key, VALUE value, agooText *tp) {
|
|
357
359
|
const char *vs = StringValuePtr(value);
|
358
360
|
int vlen = (int)RSTRING_LEN(value);
|
359
361
|
struct _agooErr err = AGOO_ERR_INIT;
|
360
|
-
|
362
|
+
|
361
363
|
if (agoo_server.pedantic) {
|
362
364
|
if (AGOO_ERR_OK != agoo_http_header_ok(&err, ks, klen, vs, vlen)) {
|
363
365
|
rb_raise(rb_eArgError, "%s", err.msg);
|
@@ -436,7 +438,7 @@ handle_rack_inner(void *x) {
|
|
436
438
|
rb_raise(rb_eArgError, "invalid rack call() response body does not respond to each.");
|
437
439
|
}
|
438
440
|
if (NULL == (t = agoo_text_allocate(1024))) {
|
439
|
-
rb_raise(
|
441
|
+
rb_raise(rb_eNoMemError, "Failed to allocate memory for a response.");
|
440
442
|
}
|
441
443
|
if (T_ARRAY == rb_type(bv)) {
|
442
444
|
int i;
|
@@ -629,7 +631,7 @@ handle_push_inner(void *x) {
|
|
629
631
|
break;
|
630
632
|
}
|
631
633
|
agoo_upgraded_release(req->up);
|
632
|
-
|
634
|
+
|
633
635
|
return Qfalse;
|
634
636
|
}
|
635
637
|
|
@@ -678,8 +680,8 @@ handle_protected(agooReq req, bool gvi) {
|
|
678
680
|
agoo_queue_wakeup(&agoo_server.con_queue);
|
679
681
|
break;
|
680
682
|
default: {
|
681
|
-
char
|
682
|
-
int
|
683
|
+
char buf[256];
|
684
|
+
int cnt = snprintf(buf, sizeof(buf), "HTTP/1.1 500 Internal Error\r\nConnection: Close\r\nContent-Length: 0\r\n\r\n");
|
683
685
|
agooText message = agoo_text_create(buf, cnt);
|
684
686
|
|
685
687
|
req->res->close = true;
|
@@ -693,13 +695,17 @@ handle_protected(agooReq req, bool gvi) {
|
|
693
695
|
static void*
|
694
696
|
process_loop(void *ptr) {
|
695
697
|
agooReq req;
|
696
|
-
|
698
|
+
|
697
699
|
atomic_fetch_add(&agoo_server.running, 1);
|
698
700
|
while (agoo_server.active) {
|
699
701
|
if (NULL != (req = (agooReq)agoo_queue_pop(&agoo_server.eval_queue, 0.1))) {
|
700
702
|
handle_protected(req, true);
|
701
703
|
agoo_req_destroy(req);
|
702
704
|
}
|
705
|
+
if (agoo_stop) {
|
706
|
+
agoo_shutdown();
|
707
|
+
break;
|
708
|
+
}
|
703
709
|
}
|
704
710
|
atomic_fetch_sub(&agoo_server.running, 1);
|
705
711
|
|
@@ -727,9 +733,9 @@ rserver_start(VALUE self) {
|
|
727
733
|
struct _agooErr err = AGOO_ERR_INIT;
|
728
734
|
VALUE agoo = rb_const_get_at(rb_cObject, rb_intern("Agoo"));
|
729
735
|
VALUE v = rb_const_get_at(agoo, rb_intern("VERSION"));
|
730
|
-
|
736
|
+
|
731
737
|
*the_rserver.worker_pids = getpid();
|
732
|
-
|
738
|
+
|
733
739
|
// If workers then set the loop_max based on the expected number of
|
734
740
|
// threads per worker.
|
735
741
|
if (1 < the_rserver.worker_cnt) {
|
@@ -774,11 +780,15 @@ rserver_start(VALUE self) {
|
|
774
780
|
} else {
|
775
781
|
rb_thread_schedule();
|
776
782
|
}
|
777
|
-
|
783
|
+
if (agoo_stop) {
|
784
|
+
agoo_shutdown();
|
785
|
+
break;
|
786
|
+
}
|
778
787
|
}
|
779
788
|
} else {
|
780
|
-
the_rserver.eval_threads = (VALUE*)AGOO_MALLOC(sizeof(VALUE) * (agoo_server.thread_cnt + 1))
|
781
|
-
|
789
|
+
if (NULL == (the_rserver.eval_threads = (VALUE*)AGOO_MALLOC(sizeof(VALUE) * (agoo_server.thread_cnt + 1)))) {
|
790
|
+
rb_raise(rb_eNoMemError, "Failed to allocate memory for the thread pool.");
|
791
|
+
}
|
782
792
|
for (i = agoo_server.thread_cnt, vp = the_rserver.eval_threads; 0 < i; i--, vp++) {
|
783
793
|
*vp = rb_thread_create(wrap_process_loop, NULL);
|
784
794
|
}
|
@@ -834,7 +844,7 @@ rserver_shutdown(VALUE self) {
|
|
834
844
|
int status;
|
835
845
|
int exit_cnt = 1;
|
836
846
|
int j;
|
837
|
-
|
847
|
+
|
838
848
|
for (i = 1; i < the_rserver.worker_cnt; i++) {
|
839
849
|
kill(the_rserver.worker_pids[i], SIGKILL);
|
840
850
|
}
|
@@ -912,7 +922,7 @@ handle(VALUE self, VALUE method, VALUE pattern, VALUE handler) {
|
|
912
922
|
if (Qtrue == rb_funcall(handler, static_id, 0, Qnil)) {
|
913
923
|
VALUE res = rb_funcall(handler, call_id, 1, Qnil);
|
914
924
|
VALUE bv;
|
915
|
-
|
925
|
+
|
916
926
|
rb_check_type(res, T_ARRAY);
|
917
927
|
if (3 != RARRAY_LEN(res)) {
|
918
928
|
rb_raise(rb_eArgError, "a rack call() response must be an array of 3 members.");
|
@@ -932,6 +942,9 @@ handle(VALUE self, VALUE method, VALUE pattern, VALUE handler) {
|
|
932
942
|
v = rb_ary_entry(bv, i);
|
933
943
|
t = agoo_text_append(t, StringValuePtr(v), (int)RSTRING_LEN(v));
|
934
944
|
}
|
945
|
+
if (NULL == t) {
|
946
|
+
rb_raise(rb_eNoMemError, "Failed to allocate memory for a response.");
|
947
|
+
}
|
935
948
|
if (NULL == agoo_page_immutable(&err, pat, t->text, t->len)) {
|
936
949
|
rb_raise(rb_eArgError, "%s", err.msg);
|
937
950
|
}
|
@@ -973,7 +986,7 @@ handle_not_found(VALUE self, VALUE handler) {
|
|
973
986
|
rb_raise(rb_eStandardError, "out of memory.");
|
974
987
|
}
|
975
988
|
rb_gc_register_address((VALUE*)&agoo_server.hook404->handler);
|
976
|
-
|
989
|
+
|
977
990
|
return Qnil;
|
978
991
|
}
|
979
992
|
|
@@ -987,7 +1000,7 @@ handle_not_found(VALUE self, VALUE handler) {
|
|
987
1000
|
static VALUE
|
988
1001
|
add_mime(VALUE self, VALUE suffix, VALUE type) {
|
989
1002
|
struct _agooErr err = AGOO_ERR_INIT;
|
990
|
-
|
1003
|
+
|
991
1004
|
if (AGOO_ERR_OK != mime_set(&err, StringValuePtr(suffix), StringValuePtr(type))) {
|
992
1005
|
rb_raise(rb_eArgError, "%s", err.msg);
|
993
1006
|
}
|
@@ -1014,7 +1027,7 @@ path_group(VALUE self, VALUE path, VALUE dirs) {
|
|
1014
1027
|
int i;
|
1015
1028
|
int dcnt = (int)RARRAY_LEN(dirs);
|
1016
1029
|
VALUE entry;
|
1017
|
-
|
1030
|
+
|
1018
1031
|
for (i = dcnt - 1; 0 <= i; i--) {
|
1019
1032
|
entry = rb_ary_entry(dirs, i);
|
1020
1033
|
if (T_STRING != rb_type(entry)) {
|
@@ -1047,7 +1060,7 @@ path_group(VALUE self, VALUE path, VALUE dirs) {
|
|
1047
1060
|
static VALUE
|
1048
1061
|
header_rule(VALUE self, VALUE path, VALUE mime, VALUE key, VALUE value) {
|
1049
1062
|
struct _agooErr err = AGOO_ERR_INIT;
|
1050
|
-
|
1063
|
+
|
1051
1064
|
rb_check_type(path, T_STRING);
|
1052
1065
|
rb_check_type(mime, T_STRING);
|
1053
1066
|
rb_check_type(key, T_STRING);
|
@@ -1086,7 +1099,7 @@ server_init(VALUE mod) {
|
|
1086
1099
|
on_message_id = rb_intern("on_message");
|
1087
1100
|
on_request_id = rb_intern("on_request");
|
1088
1101
|
to_i_id = rb_intern("to_i");
|
1089
|
-
|
1102
|
+
|
1090
1103
|
connect_sym = ID2SYM(rb_intern("CONNECT")); rb_gc_register_address(&connect_sym);
|
1091
1104
|
delete_sym = ID2SYM(rb_intern("DELETE")); rb_gc_register_address(&delete_sym);
|
1092
1105
|
get_sym = ID2SYM(rb_intern("GET")); rb_gc_register_address(&get_sym);
|
data/ext/agoo/sdl.c
CHANGED
@@ -9,14 +9,16 @@
|
|
9
9
|
#include "graphql.h"
|
10
10
|
#include "sdl.h"
|
11
11
|
|
12
|
-
static const char query_str[] = "query";
|
13
|
-
static const char union_str[] = "union";
|
14
12
|
static const char enum_str[] = "enum";
|
13
|
+
static const char extend_str[] = "extend";
|
14
|
+
static const char input_str[] = "input";
|
15
|
+
static const char interface_str[] = "interface";
|
15
16
|
static const char mutation_str[] = "mutation";
|
17
|
+
static const char query_str[] = "query";
|
18
|
+
static const char schema_str[] = "schema";
|
16
19
|
static const char subscription_str[] = "subscription";
|
17
|
-
static const char interface_str[] = "interface";
|
18
|
-
static const char input_str[] = "input";
|
19
20
|
static const char type_str[] = "type";
|
21
|
+
static const char union_str[] = "union";
|
20
22
|
|
21
23
|
static int make_sel(agooErr err, agooDoc doc, gqlDoc gdoc, gqlOp op, gqlSel *parentp);
|
22
24
|
|
@@ -80,56 +82,6 @@ extract_name(agooErr err, agooDoc doc, const char *key, int klen, char *name, si
|
|
80
82
|
return AGOO_ERR_OK;
|
81
83
|
}
|
82
84
|
|
83
|
-
static int
|
84
|
-
make_scalar(agooErr err, agooDoc doc, const char *desc, int len) {
|
85
|
-
char name[256];
|
86
|
-
|
87
|
-
if (AGOO_ERR_OK != extract_name(err, doc, "scalar", 6, name, sizeof(name))) {
|
88
|
-
return err->code;
|
89
|
-
}
|
90
|
-
gql_scalar_create(err, name, desc, len);
|
91
|
-
|
92
|
-
return AGOO_ERR_OK;
|
93
|
-
}
|
94
|
-
|
95
|
-
static int
|
96
|
-
read_type(agooErr err, agooDoc doc, gqlType *typep, bool *required) {
|
97
|
-
agoo_doc_skip_white(doc);
|
98
|
-
if ('[' == *doc->cur) {
|
99
|
-
gqlType base;
|
100
|
-
bool not_empty = false;
|
101
|
-
|
102
|
-
doc->cur++;
|
103
|
-
if (AGOO_ERR_OK != read_type(err, doc, &base, ¬_empty)) {
|
104
|
-
return err->code;
|
105
|
-
}
|
106
|
-
agoo_doc_skip_white(doc);
|
107
|
-
if (']' != *doc->cur) {
|
108
|
-
return agoo_doc_err(doc, err, "List type not terminated with a ]");
|
109
|
-
}
|
110
|
-
doc->cur++;
|
111
|
-
if (NULL == (*typep = gql_assure_list(err, base, not_empty))) {
|
112
|
-
return err->code;
|
113
|
-
}
|
114
|
-
} else {
|
115
|
-
char name[256];
|
116
|
-
|
117
|
-
if (0 == read_name(err, doc, name, sizeof(name))) {
|
118
|
-
return err->code;
|
119
|
-
}
|
120
|
-
if (NULL == (*typep = gql_assure_type(err, name))) {
|
121
|
-
return err->code;
|
122
|
-
}
|
123
|
-
}
|
124
|
-
*required = false;
|
125
|
-
agoo_doc_skip_white(doc);
|
126
|
-
if ('!' == *doc->cur) {
|
127
|
-
*required = true;
|
128
|
-
doc->cur++;
|
129
|
-
}
|
130
|
-
return AGOO_ERR_OK;
|
131
|
-
}
|
132
|
-
|
133
85
|
static int
|
134
86
|
make_use_arg(agooErr err, agooDoc doc, gqlDirUse use) {
|
135
87
|
char name[256];
|
@@ -195,7 +147,66 @@ extract_dir_use(agooErr err, agooDoc doc, gqlDirUse *uses) {
|
|
195
147
|
}
|
196
148
|
|
197
149
|
static int
|
198
|
-
|
150
|
+
make_scalar(agooErr err, agooDoc doc, const char *desc, int len, bool x) {
|
151
|
+
char name[256];
|
152
|
+
gqlType type;
|
153
|
+
|
154
|
+
if (AGOO_ERR_OK != extract_name(err, doc, "scalar", 6, name, sizeof(name))) {
|
155
|
+
return err->code;
|
156
|
+
}
|
157
|
+
if (x) {
|
158
|
+
if (NULL == (type = gql_type_get(name))) {
|
159
|
+
return agoo_doc_err(doc, err, "%s not defined. Can not be extended.", name);
|
160
|
+
}
|
161
|
+
} else if (NULL == (type = gql_scalar_create(err, name, desc, len))) {
|
162
|
+
return err->code;
|
163
|
+
}
|
164
|
+
if (AGOO_ERR_OK != extract_dir_use(err, doc, &type->dir)) {
|
165
|
+
return err->code;
|
166
|
+
}
|
167
|
+
return AGOO_ERR_OK;
|
168
|
+
}
|
169
|
+
|
170
|
+
static int
|
171
|
+
read_type(agooErr err, agooDoc doc, gqlType *typep, bool *required) {
|
172
|
+
agoo_doc_skip_white(doc);
|
173
|
+
if ('[' == *doc->cur) {
|
174
|
+
gqlType base;
|
175
|
+
bool not_empty = false;
|
176
|
+
|
177
|
+
doc->cur++;
|
178
|
+
if (AGOO_ERR_OK != read_type(err, doc, &base, ¬_empty)) {
|
179
|
+
return err->code;
|
180
|
+
}
|
181
|
+
agoo_doc_skip_white(doc);
|
182
|
+
if (']' != *doc->cur) {
|
183
|
+
return agoo_doc_err(doc, err, "List type not terminated with a ]");
|
184
|
+
}
|
185
|
+
doc->cur++;
|
186
|
+
if (NULL == (*typep = gql_assure_list(err, base, not_empty))) {
|
187
|
+
return err->code;
|
188
|
+
}
|
189
|
+
} else {
|
190
|
+
char name[256];
|
191
|
+
|
192
|
+
if (0 == read_name(err, doc, name, sizeof(name))) {
|
193
|
+
return err->code;
|
194
|
+
}
|
195
|
+
if (NULL == (*typep = gql_assure_type(err, name))) {
|
196
|
+
return err->code;
|
197
|
+
}
|
198
|
+
}
|
199
|
+
*required = false;
|
200
|
+
agoo_doc_skip_white(doc);
|
201
|
+
if ('!' == *doc->cur) {
|
202
|
+
*required = true;
|
203
|
+
doc->cur++;
|
204
|
+
}
|
205
|
+
return AGOO_ERR_OK;
|
206
|
+
}
|
207
|
+
|
208
|
+
static int
|
209
|
+
make_enum(agooErr err, agooDoc doc, const char *desc, size_t dlen, bool x) {
|
199
210
|
char name[256];
|
200
211
|
const char *start;
|
201
212
|
gqlType type;
|
@@ -214,8 +225,11 @@ make_enum(agooErr err, agooDoc doc, const char *desc, size_t dlen) {
|
|
214
225
|
return agoo_doc_err(doc, err, "Expected '{'");
|
215
226
|
}
|
216
227
|
doc->cur++;
|
217
|
-
|
218
|
-
|
228
|
+
if (x) {
|
229
|
+
if (NULL == (type = gql_type_get(name))) {
|
230
|
+
return agoo_doc_err(doc, err, "%s not defined. Can not be extended.", name);
|
231
|
+
}
|
232
|
+
} else if (NULL == (type = gql_enum_create(err, name, desc, dlen))) {
|
219
233
|
return err->code;
|
220
234
|
}
|
221
235
|
type->dir = uses;
|
@@ -224,60 +238,69 @@ make_enum(agooErr err, agooDoc doc, const char *desc, size_t dlen) {
|
|
224
238
|
uses = NULL;
|
225
239
|
|
226
240
|
if (AGOO_ERR_OK != extract_desc(err, doc, &desc, &dlen)) {
|
227
|
-
|
241
|
+
goto ERROR;
|
228
242
|
}
|
229
243
|
start = doc->cur;
|
230
244
|
agoo_doc_read_token(doc);
|
231
245
|
len = doc->cur - start;
|
232
246
|
if (AGOO_ERR_OK != extract_dir_use(err, doc, &uses)) {
|
233
|
-
|
247
|
+
goto ERROR;
|
234
248
|
}
|
235
249
|
if (doc->cur == start) {
|
236
250
|
if ('}' == *doc->cur) {
|
237
251
|
doc->cur++;
|
238
252
|
break;
|
239
253
|
}
|
240
|
-
|
254
|
+
agoo_doc_err(doc, err, "Invalid Enum value");
|
255
|
+
goto ERROR;
|
241
256
|
}
|
242
257
|
if (NULL == (ev = gql_enum_append(err, type, start, len, desc, dlen))) {
|
243
|
-
|
258
|
+
goto ERROR;
|
244
259
|
}
|
245
260
|
ev->dir = uses;
|
246
261
|
}
|
247
262
|
return AGOO_ERR_OK;
|
263
|
+
ERROR:
|
264
|
+
if (!x) {
|
265
|
+
gql_type_destroy(type);
|
266
|
+
}
|
267
|
+
return err->code;
|
248
268
|
}
|
249
269
|
|
250
270
|
static int
|
251
|
-
make_union(agooErr err, agooDoc doc, const char *desc, int len) {
|
271
|
+
make_union(agooErr err, agooDoc doc, const char *desc, int len, bool x) {
|
252
272
|
char name[256];
|
253
273
|
gqlType type;
|
254
|
-
gqlDirUse uses = NULL;
|
255
274
|
gqlType member;
|
256
275
|
bool required;
|
257
276
|
|
258
277
|
if (AGOO_ERR_OK != extract_name(err, doc, union_str, sizeof(union_str) - 1, name, sizeof(name))) {
|
259
278
|
return err->code;
|
260
279
|
}
|
261
|
-
if (
|
280
|
+
if (x) {
|
281
|
+
if (NULL == (type = gql_type_get(name))) {
|
282
|
+
return agoo_doc_err(doc, err, "%s not defined. Can not be extended.", name);
|
283
|
+
}
|
284
|
+
} else if (NULL == (type = gql_union_create(err, name, desc, len))) {
|
262
285
|
return err->code;
|
263
286
|
}
|
287
|
+
if (AGOO_ERR_OK != extract_dir_use(err, doc, &type->dir)) {
|
288
|
+
goto ERROR;
|
289
|
+
}
|
264
290
|
agoo_doc_skip_white(doc);
|
265
291
|
if ('=' != *doc->cur) {
|
266
|
-
|
292
|
+
agoo_doc_err(doc, err, "Expected '='");
|
293
|
+
goto ERROR;
|
267
294
|
}
|
268
295
|
doc->cur++;
|
269
296
|
agoo_doc_skip_white(doc);
|
270
297
|
|
271
|
-
if (NULL == (type = gql_union_create(err, name, desc, len))) {
|
272
|
-
return err->code;
|
273
|
-
}
|
274
|
-
type->dir = uses;
|
275
298
|
while (doc->cur < doc->end) {
|
276
299
|
if (AGOO_ERR_OK != read_type(err, doc, &member, &required)) {
|
277
|
-
|
300
|
+
goto ERROR;
|
278
301
|
}
|
279
302
|
if (AGOO_ERR_OK != gql_union_add(err, type, member)) {
|
280
|
-
|
303
|
+
goto ERROR;
|
281
304
|
}
|
282
305
|
agoo_doc_skip_white(doc);
|
283
306
|
if ('|' != *doc->cur) {
|
@@ -286,6 +309,11 @@ make_union(agooErr err, agooDoc doc, const char *desc, int len) {
|
|
286
309
|
doc->cur++; // skip |
|
287
310
|
}
|
288
311
|
return AGOO_ERR_OK;
|
312
|
+
ERROR:
|
313
|
+
if (!x) {
|
314
|
+
gql_type_destroy(type);
|
315
|
+
}
|
316
|
+
return err->code;
|
289
317
|
}
|
290
318
|
|
291
319
|
static int
|
@@ -570,8 +598,6 @@ make_input_arg(agooErr err, agooDoc doc, gqlType type) {
|
|
570
598
|
if (AGOO_ERR_OK != extract_dir_use(err, doc, &uses)) {
|
571
599
|
return err->code;
|
572
600
|
}
|
573
|
-
// TBD zzzzzzzz
|
574
|
-
|
575
601
|
if (NULL == (arg = gql_input_arg(err, type, name, return_type, desc, dlen, dval, required))) {
|
576
602
|
return err->code;
|
577
603
|
}
|
@@ -581,77 +607,90 @@ make_input_arg(agooErr err, agooDoc doc, gqlType type) {
|
|
581
607
|
}
|
582
608
|
|
583
609
|
static int
|
584
|
-
make_interface(agooErr err, agooDoc doc, const char *desc, int len) {
|
610
|
+
make_interface(agooErr err, agooDoc doc, const char *desc, int len, bool x) {
|
585
611
|
char name[256];
|
586
612
|
gqlType type;
|
587
|
-
gqlDirUse uses = NULL;
|
588
613
|
|
589
614
|
if (AGOO_ERR_OK != extract_name(err, doc, interface_str, sizeof(interface_str) - 1, name, sizeof(name))) {
|
590
615
|
return err->code;
|
591
616
|
}
|
592
|
-
if (
|
617
|
+
if (x) {
|
618
|
+
if (NULL == (type = gql_type_get(name))) {
|
619
|
+
return agoo_doc_err(doc, err, "%s not defined. Can not be extended.", name);
|
620
|
+
}
|
621
|
+
} else if (NULL == (type = gql_interface_create(err, name, desc, len))) {
|
593
622
|
return err->code;
|
594
623
|
}
|
624
|
+
if (AGOO_ERR_OK != extract_dir_use(err, doc, &type->dir)) {
|
625
|
+
goto ERROR;
|
626
|
+
}
|
595
627
|
agoo_doc_skip_white(doc);
|
596
628
|
if ('{' != *doc->cur) {
|
597
|
-
|
629
|
+
goto ERROR;
|
598
630
|
}
|
599
631
|
doc->cur++;
|
600
632
|
agoo_doc_skip_white(doc);
|
601
633
|
|
602
|
-
if (NULL == (type = gql_interface_create(err, name, desc, len))) {
|
603
|
-
return err->code;
|
604
|
-
}
|
605
|
-
type->dir = uses;
|
606
634
|
while (doc->cur < doc->end) {
|
607
635
|
if ('}' == *doc->cur) {
|
608
636
|
doc->cur++; // skip }
|
609
637
|
break;
|
610
638
|
}
|
611
639
|
if (AGOO_ERR_OK != make_field(err, doc, type)) {
|
612
|
-
|
640
|
+
goto ERROR;
|
613
641
|
}
|
614
642
|
agoo_doc_skip_white(doc);
|
615
643
|
}
|
616
644
|
return AGOO_ERR_OK;
|
645
|
+
ERROR:
|
646
|
+
if (!x) {
|
647
|
+
gql_type_destroy(type);
|
648
|
+
}
|
649
|
+
return err->code;
|
617
650
|
}
|
618
651
|
|
619
652
|
static int
|
620
|
-
make_input(agooErr err, agooDoc doc, const char *desc, int len) {
|
653
|
+
make_input(agooErr err, agooDoc doc, const char *desc, int len, bool x) {
|
621
654
|
char name[256];
|
622
655
|
gqlType type;
|
623
|
-
gqlDirUse uses = NULL;
|
624
656
|
|
625
657
|
if (AGOO_ERR_OK != extract_name(err, doc, input_str, sizeof(input_str) - 1, name, sizeof(name))) {
|
626
658
|
return err->code;
|
627
659
|
}
|
628
|
-
if (
|
660
|
+
if (x) {
|
661
|
+
if (NULL == (type = gql_type_get(name))) {
|
662
|
+
return agoo_doc_err(doc, err, "%s not defined. Can not be extended.", name);
|
663
|
+
}
|
664
|
+
} else if (NULL == (type = gql_input_create(err, name, desc, len))) {
|
629
665
|
return err->code;
|
630
666
|
}
|
667
|
+
if (AGOO_ERR_OK != extract_dir_use(err, doc, &type->dir)) {
|
668
|
+
goto ERROR;
|
669
|
+
}
|
631
670
|
agoo_doc_skip_white(doc);
|
632
671
|
if ('{' != *doc->cur) {
|
633
|
-
|
672
|
+
agoo_doc_err(doc, err, "Expected '{'");
|
673
|
+
goto ERROR;
|
634
674
|
}
|
635
675
|
doc->cur++;
|
636
676
|
agoo_doc_skip_white(doc);
|
637
677
|
|
638
|
-
if (NULL == (type = gql_input_create(err, name, desc, len))) {
|
639
|
-
return err->code;
|
640
|
-
}
|
641
|
-
type->dir = uses;
|
642
|
-
|
643
678
|
while (doc->cur < doc->end) {
|
644
679
|
if ('}' == *doc->cur) {
|
645
680
|
doc->cur++; // skip }
|
646
681
|
break;
|
647
682
|
}
|
648
|
-
// TBD zzzzzzzzzz make_arg
|
649
683
|
if (AGOO_ERR_OK != make_input_arg(err, doc, type)) {
|
650
|
-
|
684
|
+
goto ERROR;
|
651
685
|
}
|
652
686
|
agoo_doc_skip_white(doc);
|
653
687
|
}
|
654
688
|
return AGOO_ERR_OK;
|
689
|
+
ERROR:
|
690
|
+
if (!x) {
|
691
|
+
gql_type_destroy(type);
|
692
|
+
}
|
693
|
+
return err->code;
|
655
694
|
}
|
656
695
|
|
657
696
|
static int
|
@@ -705,33 +744,82 @@ extract_interfaces(agooErr err, agooDoc doc, gqlTypeLink *interfacesp) {
|
|
705
744
|
}
|
706
745
|
|
707
746
|
static int
|
708
|
-
make_type(agooErr err, agooDoc doc, const char *desc, int len) {
|
747
|
+
make_type(agooErr err, agooDoc doc, const char *desc, int len, bool x) {
|
709
748
|
char name[256];
|
710
749
|
gqlType type;
|
711
|
-
gqlDirUse uses = NULL;
|
712
|
-
gqlTypeLink interfaces = NULL;
|
713
750
|
|
714
751
|
if (AGOO_ERR_OK != extract_name(err, doc, type_str, sizeof(type_str) - 1, name, sizeof(name))) {
|
715
752
|
return err->code;
|
716
753
|
}
|
717
|
-
if (
|
754
|
+
if (x) {
|
755
|
+
if (NULL == (type = gql_type_get(name))) {
|
756
|
+
return agoo_doc_err(doc, err, "%s not defined. Can not be extended.", name);
|
757
|
+
}
|
758
|
+
} else if (NULL == (type = gql_type_create(err, name, desc, len, NULL))) {
|
718
759
|
return err->code;
|
719
760
|
}
|
720
|
-
if (AGOO_ERR_OK !=
|
721
|
-
|
761
|
+
if (AGOO_ERR_OK != extract_interfaces(err, doc, &type->interfaces)) {
|
762
|
+
goto ERROR;
|
763
|
+
}
|
764
|
+
if (AGOO_ERR_OK != extract_dir_use(err, doc, &type->dir)) {
|
765
|
+
goto ERROR;
|
722
766
|
}
|
723
767
|
agoo_doc_skip_white(doc);
|
724
768
|
if ('{' != *doc->cur) {
|
725
|
-
|
769
|
+
agoo_doc_err(doc, err, "Expected '{'");
|
770
|
+
goto ERROR;
|
726
771
|
}
|
727
772
|
doc->cur++;
|
728
773
|
agoo_doc_skip_white(doc);
|
729
774
|
|
730
|
-
|
731
|
-
|
775
|
+
while (doc->cur < doc->end) {
|
776
|
+
if ('}' == *doc->cur) {
|
777
|
+
doc->cur++; // skip }
|
778
|
+
break;
|
779
|
+
}
|
780
|
+
if (AGOO_ERR_OK != make_field(err, doc, type)) {
|
781
|
+
goto ERROR;
|
782
|
+
}
|
783
|
+
agoo_doc_skip_white(doc);
|
732
784
|
}
|
733
|
-
|
785
|
+
return AGOO_ERR_OK;
|
786
|
+
ERROR:
|
787
|
+
if (!x) {
|
788
|
+
gql_type_destroy(type);
|
789
|
+
}
|
790
|
+
return err->code;
|
791
|
+
}
|
792
|
+
|
793
|
+
static int
|
794
|
+
make_schema(agooErr err, agooDoc doc, const char *desc, int len, bool x) {
|
795
|
+
gqlType type;
|
734
796
|
|
797
|
+
if (0 != strncmp(doc->cur, schema_str, sizeof(schema_str) - 1)) {
|
798
|
+
return agoo_doc_err(doc, err, "Expected schema key word");
|
799
|
+
}
|
800
|
+
doc->cur += sizeof(schema_str) - 1;
|
801
|
+
if (0 == agoo_doc_skip_white(doc)) {
|
802
|
+
return agoo_doc_err(doc, err, "Expected schema key word");
|
803
|
+
}
|
804
|
+
if (x) {
|
805
|
+
if (NULL == (type = gql_type_get(schema_str))) {
|
806
|
+
return agoo_doc_err(doc, err, "schema not defined. Can not be extended.");
|
807
|
+
}
|
808
|
+
} else if (NULL == (type = gql_schema_create(err, desc, len))) {
|
809
|
+
return err->code;
|
810
|
+
}
|
811
|
+
if (AGOO_ERR_OK != extract_dir_use(err, doc, &type->dir)) {
|
812
|
+
return err->code;
|
813
|
+
}
|
814
|
+
agoo_doc_skip_white(doc);
|
815
|
+
if ('{' != *doc->cur) {
|
816
|
+
if (!x) {
|
817
|
+
gql_type_destroy(type);
|
818
|
+
}
|
819
|
+
return agoo_doc_err(doc, err, "Expected '{'");
|
820
|
+
}
|
821
|
+
doc->cur++;
|
822
|
+
agoo_doc_skip_white(doc);
|
735
823
|
while (doc->cur < doc->end) {
|
736
824
|
if ('}' == *doc->cur) {
|
737
825
|
doc->cur++; // skip }
|
@@ -745,11 +833,24 @@ make_type(agooErr err, agooDoc doc, const char *desc, int len) {
|
|
745
833
|
return AGOO_ERR_OK;
|
746
834
|
}
|
747
835
|
|
836
|
+
static int
|
837
|
+
extend(agooErr err, agooDoc doc) {
|
838
|
+
if (0 != strncmp(doc->cur, extend_str, sizeof(extend_str) - 1)) {
|
839
|
+
return agoo_doc_err(doc, err, "Expected extend key word");
|
840
|
+
}
|
841
|
+
doc->cur += sizeof(extend_str) - 1;
|
842
|
+
if (0 == agoo_doc_skip_white(doc)) {
|
843
|
+
return agoo_doc_err(doc, err, "Expected extend key word");
|
844
|
+
}
|
845
|
+
return AGOO_ERR_OK;
|
846
|
+
}
|
847
|
+
|
748
848
|
int
|
749
849
|
sdl_parse(agooErr err, const char *str, int len) {
|
750
850
|
struct _agooDoc doc;
|
751
851
|
const char *desc = NULL;
|
752
852
|
size_t dlen = 0;
|
853
|
+
bool extend_next = false;
|
753
854
|
|
754
855
|
agoo_doc_init(&doc, str, len);
|
755
856
|
|
@@ -761,32 +862,47 @@ sdl_parse(agooErr err, const char *str, int len) {
|
|
761
862
|
return err->code;
|
762
863
|
}
|
763
864
|
break;
|
764
|
-
case 's': // scalar
|
765
|
-
if (
|
766
|
-
|
865
|
+
case 's': // schema or scalar
|
866
|
+
if (6 < (doc.end - doc.cur) && 'c' == doc.cur[1]) {
|
867
|
+
if ('a' == doc.cur[2]) {
|
868
|
+
if (AGOO_ERR_OK != make_scalar(err, &doc, desc, dlen, extend_next)) {
|
869
|
+
return err->code;
|
870
|
+
}
|
871
|
+
desc = NULL;
|
872
|
+
dlen = 0;
|
873
|
+
break;
|
874
|
+
} else {
|
875
|
+
if (AGOO_ERR_OK != make_schema(err, &doc, desc, dlen, extend_next)) {
|
876
|
+
return err->code;
|
877
|
+
}
|
878
|
+
desc = NULL;
|
879
|
+
dlen = 0;
|
880
|
+
break;
|
881
|
+
}
|
767
882
|
}
|
768
|
-
|
769
|
-
|
770
|
-
break;
|
771
|
-
case 'e': // enum, and extend interface or type
|
883
|
+
return agoo_doc_err(&doc, err, "Unknown directive");
|
884
|
+
case 'e': // enum or extend
|
772
885
|
if (4 < (doc.end - doc.cur)) {
|
773
886
|
if ('n' == doc.cur[1]) {
|
774
|
-
if (AGOO_ERR_OK != make_enum(err, &doc, desc, dlen)) {
|
887
|
+
if (AGOO_ERR_OK != make_enum(err, &doc, desc, dlen, extend_next)) {
|
775
888
|
return err->code;
|
776
889
|
}
|
777
890
|
desc = NULL;
|
778
891
|
dlen = 0;
|
779
892
|
break;
|
780
893
|
} else {
|
781
|
-
|
894
|
+
if (AGOO_ERR_OK != extend(err, &doc)) {
|
895
|
+
return err->code;
|
896
|
+
}
|
782
897
|
desc = NULL;
|
783
898
|
dlen = 0;
|
899
|
+
extend_next = true;
|
784
900
|
break;
|
785
901
|
}
|
786
902
|
}
|
787
903
|
return agoo_doc_err(&doc, err, "Unknown directive");
|
788
904
|
case 'u': // union
|
789
|
-
if (AGOO_ERR_OK != make_union(err, &doc, desc, dlen)) {
|
905
|
+
if (AGOO_ERR_OK != make_union(err, &doc, desc, dlen, extend_next)) {
|
790
906
|
return err->code;
|
791
907
|
}
|
792
908
|
desc = NULL;
|
@@ -800,7 +916,7 @@ sdl_parse(agooErr err, const char *str, int len) {
|
|
800
916
|
dlen = 0;
|
801
917
|
break;
|
802
918
|
case 't': // type
|
803
|
-
if (AGOO_ERR_OK != make_type(err, &doc, desc, dlen)) {
|
919
|
+
if (AGOO_ERR_OK != make_type(err, &doc, desc, dlen, extend_next)) {
|
804
920
|
return err->code;
|
805
921
|
}
|
806
922
|
desc = NULL;
|
@@ -809,14 +925,14 @@ sdl_parse(agooErr err, const char *str, int len) {
|
|
809
925
|
case 'i': // interface, input
|
810
926
|
if (5 < (doc.end - doc.cur) && 'n' == doc.cur[1]) {
|
811
927
|
if ('p' == doc.cur[2]) {
|
812
|
-
if (AGOO_ERR_OK != make_input(err, &doc, desc, dlen)) {
|
928
|
+
if (AGOO_ERR_OK != make_input(err, &doc, desc, dlen, extend_next)) {
|
813
929
|
return err->code;
|
814
930
|
}
|
815
931
|
desc = NULL;
|
816
932
|
dlen = 0;
|
817
933
|
break;
|
818
934
|
} else {
|
819
|
-
if (AGOO_ERR_OK != make_interface(err, &doc, desc, dlen)) {
|
935
|
+
if (AGOO_ERR_OK != make_interface(err, &doc, desc, dlen, extend_next)) {
|
820
936
|
return err->code;
|
821
937
|
}
|
822
938
|
desc = NULL;
|
@@ -1352,6 +1468,7 @@ lookup_field_type(gqlType type, const char *field, bool qroot) {
|
|
1352
1468
|
gqlType ftype = NULL;
|
1353
1469
|
|
1354
1470
|
switch (type->kind) {
|
1471
|
+
case GQL_SCHEMA:
|
1355
1472
|
case GQL_OBJECT:
|
1356
1473
|
case GQL_INPUT:
|
1357
1474
|
case GQL_INTERFACE: {
|
@@ -1425,7 +1542,7 @@ validate_doc(agooErr err, gqlDoc doc) {
|
|
1425
1542
|
gqlFrag frag;
|
1426
1543
|
int cnt;
|
1427
1544
|
|
1428
|
-
if (NULL == (schema =
|
1545
|
+
if (NULL == (schema = gql_root_type())) {
|
1429
1546
|
return agoo_err_set(err, AGOO_ERR_EVAL, "No root (schema) type defined.");
|
1430
1547
|
}
|
1431
1548
|
for (frag = doc->frags; NULL != frag; frag = frag->next) {
|