-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathformalization.tex
1197 lines (959 loc) · 81 KB
/
formalization.tex
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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
% !TEX root = ./main.tex
\section{\gcoql}\label{sec:form}
In this section we describe our formalization of \gql in \coq. We start by defining a schema and its properties (\S\ref{subsec:schema}), then the graph data model (\S\ref{subsec:graph}), and finally present queries (\S\ref{subsec:query}) and their semantics (\S\ref{subsec:semantics}). We highlight key connections with the \spec~\cite{gqlspec} and \HP~\cite{gqlph} along the way, and end this section with a discussion of various design considerations (\S\ref{subsec:discussion}).
% The definitions are as close as possible with respect to the \spec. This eyeball correspondence between the definitions in prose and the code gives a first level of trust that our formalization is correct.%, following the examples of X, Y and Z.
% Whenever there is a mismatch we point it out and explain the reasoning behind each decision.
\subsection{Schema}\label{subsec:schema}
We formalize schemas and type definitions following the \spec. A
schema is represented as a record, containing a list of type
definitions and a root query type that specifies the entry points to the
dataset. A \texttt{Name} is simply a string, according to the \spec.
% available selections (\eg \texttt{Query} in the example from Figure \ref{fig:schema_ex}):
%
\begin{minted}[bgcolor=coqbg]{coq}
Record graphQLSchema := GraphQLSchema {
query_type : Name;
type_definitions : seq TypeDefinition
}.
\end{minted}
%
Schemas may also include additional root types for specifying
mutations and subscriptions (\cf \cite[\S3.2.1]{gqlspec}). These operations are, however, out of the scope of this work.
Type definitions in \gcoql closely follow the \spec, as
depicted in Figure~ \ref{fig:types_def}. A type may be a scalar type,
an object type, which possibly implements a set of interfaces, an
interface type, a union type or an enumeration type. Object and
interface type definitions comprise a set of fields; union
types are defined by a set of type names and enumeration types by a
set of scalar values.
% As can be seen from the figure, our implementation looses information about non-emptiness of fields, union and enum members. We push this validation to a posterior predicate, as well as the discussion about the reasons behind this decision, to the following paragraphs.
% As can be seen in the figure, we tried to match the \spec's
% definition as much as possible. This eyeball correspondence gives us
% a degree of confidence about the implementation. % We currently do
% not include the \textit{Input Object} types, as well as anything
% related to \textit{introspection}.
The mere syntax of schema and types does not ensure that only valid schemas are defined. For instance, one can build
an object that implements scalar types or use a nonexistent type as
the root query type. To avoid this problem, the \spec provides several
validation rules (\cf~\cite[\S3]{gqlspec}). % , scattered throughout the
% In this regard, observe that the provided definitions of schema and
% types allow building ``invalid'' schemas.
% document (many can be found
% \eg in \cite[\S3]{gqlspec}\td{They may all be found there, but many
% are in the Validation section of each type} \fo{Then they are not ``scattered throughout the document''}
% \td{Also, this notation is a bit different from the other cases, is it ok?}).
% % the \textbf{Type Validation} subsection of each type described in ..
We refer to these rules as the \textit{well-formedness}
condition of a \gql schema:\footnote{In \HP, this condition is
referred to as the {\em consistency} of schemas.}
\begin{definition}
A \gql schema is \textit{well-formed} if:
\begin{itemize}
\item its query root type (is defined and) is an object type,
\item there are no duplicated type names, and
\item every type definition is \textit{well-formed}.
\end{itemize}
\end{definition}
In \gcoql, this is captured by the Boolean predicate below. %As mentioned in the introduction, our formalization heavily relies on Boolean reflection, following the SSReflect mindset.
%
\begin{minted}[bgcolor=coqbg]{coq}
Definition is_a_wf_schema (s : graphQLSchema) : bool :=
is_object_type s s.(query_type) &&
uniq s.(type_names) &&
all is_a_wf_type_def s.(type_definitions).
\end{minted}
%
% \et{naming inconsistency between is\_a\_wf\_schema and is\_wf\_typedef: skip the "a" in the case of schema}
% \td{I had actually renamed it is\_a\_wf\_typedef. I prefer with the "a" tbh}
The notion of well-formedness for type definitions requires \eg that
the members of union types are existent object types and that object and
interface types contain at least one field. %Due to space limitations,
% we omit the f
Note that the \spec syntactically requires certain sets of elements to be non-empty (see the grammar on the left of
Figure~\ref{fig:types_def}). This requirement is not enforced at the level of a type definition in \gcoql, but is instead part of the well-formedness check.
Full definitions can be found in our
\coq development. %file \texttt{SchemaWellFormedness.v}.
%We will, though, resume the discussion about non-emptiness of fields, union and enum members, which are included in the predicate. The main reason behind this decision is that, even though the \spec embeds this information in the grammar, it still includes it in their validation rules later on. We believe that it is simpler to use common lists instead of defining new structures or using dependent types, from an implementation point of view, while still preserving the correspondence to the algorithmic description given by the \spec.
%\td{Not sure if correctly worded... but it was just simpler to use lists. A non-empty list structure required coercions to lists and then redefining some lemmas and things. Or using dependent types (sigma type) adds complexity when proving and defining things (at least that was the case for me)}
% There are two main reasons why we push this rule to a separate predicate instead of embedding it in the structure itself. The first one is that, even though the \spec embeds it in the grammar, it still includes it in a validation rule later on. To match their definition and preserve the eyeball correspondence, we also include it. The second reason is that we use SSReflect and it is simpler to use \mintinline{coq}{seq} directly and all its theory, instead of defining coercions and repeating definitions for a new structure.
For convenience, we encapsulate schemas with their well-formedness
proof in a single structure.
%This structure also contains the
%predicate \mintinline{coq}{is_a_valid_value}, which determines whether
%a value used in a query or a node's property indeed matches the scalar type expected by the
% schema. For example, if a field argument has type \texttt{Float}, the
% \spec requires that the actual argument value represents a double-precision fractional number\footnote{The \spec declares a set of minimal scalar values and how they should be represented, such as floating-point values adhering to IEEE 754. We do not include this base restrictions but leave it open to implementation.}. To model values across our development, we parameterize each module with a type \texttt{Value} (of type \texttt{eqType}, \ie \mintinline{coq}{Variable (Value : eqType)}).
% An element in \texttt{Value} is either a scalar or a list of other values.
%
\begin{minted}[bgcolor=coqbg]{coq}
Record wfGraphQLSchema := WFGraphQLSchema {
schema : graphQLSchema;
_ : schema.(is_a_wf_schema);
}.
\end{minted}
%\fo{Mention what \texttt{Vals} represents (used here for the first
% time, but not defined)}
% This predicate is necessary to establish when a value used in a query or in the graph actually matches the scalar type expected by the schema. For instance, if an argument requires a \texttt{Float} value, then the actual value passed to the query must be something that represents a double-precision fractional value\footnote{The \spec declares a set of minimal scalar values and how they should be represented, such as floating-point values adhering to IEEE 754. We do not include this base restrictions but leave it open to implementation.}. This predicate validates that this is satisfied.
% Due to space constraints, we omit the definition of \textit{well-formedness} for type definitions. This property includes things such as: interfaces and objects must declare at least one field, objects correctly implement their declared interfaces, union types are not empty and contain only object types, amongst others. These definitions are collected from the \spec \td{Scattered throughout the \spec*}.
% Having reviewed our formalization of schemas, we now discuss our formalization of the data model.
\subsection{Data Model}\label{subsec:graph}
Following \HP, we adopt a data model based on graphs, where datasets are
modeled as directed property graphs, with labeled edges and typed
nodes. Nodes contain a type and a set of properties (key-value pairs)
and edges contain single labels. Properties and labels may contain a list of
arguments (key-value pairs). Values are either scalars or
lists of values. %Refer to Figure~\ref{fig:graph_ex} for an example.
%
%To represent the values associated to properties and arguments, we consider the type \Vals.
% A value in \Vals may be a single scalar value or a list of values\td{This choice is based on the limitations of the model}.\fo{I think we should address this in the Discussion section, where we discuss the limitations of our formalization. We could even remove the last sentence from the paragraph.}
%
\begin{definition}
A \emph{\gql graph} is defined by:
\begin{itemize}
\item a root node, and
\item a collection of edges of the form ($u$, $\fld$, $v$), where $u, v$ are nodes and
$\fld$ is a label with arguments.
\end{itemize}
\end{definition}
%
\noindent To model graphs in \coq, we first model values. This requires fixing a
domain of scalar values with decidable equality.
% the values in a graph, as well as across the rest of our development, we define an inductive type \texttt{Value}, representing
% either scalar or lists of values. The corresponding modules are then parameterized by the
% \texttt{Scalar} type.
\begin{minted}[bgcolor=coqbg]{coq}
Variable Scalar : eqType.
Inductive Value : Type :=
| SValue : Scalar -> Value
| LValue : seq Value -> Value.
\end{minted}
Labels, nodes and graphs are all represented as records:
\begin{minted}[bgcolor=coqbg]{coq}
Record label :=
Label { lname : string; args : seq (string * Value) }.
Record node :=
Node { ntype : Name; nprops : seq (label * Value) }.
Record graphQLGraph :=
GraphQLGraph { root : node;
edges : seq (node * label * node) }.
\end{minted}
% The root node of a \gql graph represents the starting point from where
% queries are evaluated.
Note that graphs are modeled using sequences---rather than sets---of edges.
In our experience, this design decision led to a simpler
formalization, as verifying edge unicity extrinsically is straightforward.
% but this design decision would be fairly easy to revisit if needed.
% \td{Added this}
% \begin{figure*}[t!]
% \centering
% \begin{subfigure}{.5\textwidth}
% \begin{displaymath}
% \begin{array}{rcl}
% \query & ::= & \texttt{query } (\name)^{?} \texttt{ \{} \sset \texttt{\}} \\
% && \\
% \sel & ::= & \fld \\
% & | & \afld \\
% & | & \nfld{\sset} \\
% & | & \anfld{\sset} \\
% & | & \ifrag{t}{\sset} \\
% \end{array}
% \end{displaymath}
% \iffalse
% \begin{grammar}
% <Query> ::= [\textbf{\texttt{query}} [<name>]] \textbf{\texttt{\{}} <Selection>$^{+}$ \textbf{\texttt{\}}}
% <Selection> ::= <name> \textbf{\texttt{(}} <Arg>* \textbf{\texttt{)}}
% \alt <alias> \textbf{\texttt{:}} <name> [\textbf{\texttt{(}} <Arg>$^{+}$ \textbf{\texttt{)}}]
% \alt <name> [\textbf{\texttt{(}} <Arg>$^{+}$ \textbf{\texttt{)}}] \textbf{\texttt{\{}} <Selection>$^{+}$ \textbf{\texttt{\}}}
% \alt <alias> \textbf{\texttt{:}} <name> [\textbf{\texttt{(}} <Arg>$^{+}$ \textbf{\texttt{)}}] \textbf{\texttt{\{}} <Selection>$^{+}$ \textbf{\texttt{\}}}
% \alt \textbf{\texttt{... on}} <name> \textbf{\texttt{\{}} <Selection>$^{+}$ \textbf{\texttt{\}}}
% <Arg> ::= <name> \textbf{\texttt{:}} <value>
% \end{grammar}
% \fi
% \end{subfigure}%
% \begin{subfigure}{.5\textwidth}
% \begin{minted}[bgcolor=coqbg]{coq}
% Record query :=
% Query { qname : option string;
% selection_set : seq Selection }.
% Inductive Selection : Type :=
% | SingleField (name : Name)
% (arguments : seq (Name * Value))
% | SingleAliasedField (alias : Name)
% (name : Name)
% (arguments : seq (Name * Value))
% | NestedField (name : Name)
% (arguments : seq (Name * Value))
% (subselections : seq Selection)
% | NestedAliasedField (alias : Name)
% (name : Name)
% (arguments : seq (Name * Value))
% (subselections : seq Selection)
% | InlineFragment (type_condition : Name)
% (subselections : seq Selection).
% \end{minted}
% \end{subfigure}
% \caption{Definition of \gql queries:
% (left) \spec grammar;
% (right) \gcoql definition. %\et{why Vals instead of Val?}\td{This was to keep close similarity to \HP (way at the beginning) -- do you think Val is better?}
% \newline{\footnotesize Symbols \texttt{f}, \texttt{a} and \texttt{t}
% correspond to identifiers for field names, field renames or aliases and type conditions, respectively.
% Symbol $\alpha$ stands for key-value pair.}}
% \label{fig:query_def}
% \end{figure*}
Intuitively, the dataset modeled by a \gql graph is built following a
schema. However, the definition of \gql graph above is fully
independent of any schema. To capture this relationship, we employ
the following notion of \textit{conformance}, partially based
on \HP:
%\td{Over here we should start including the notion of Value type + valid scalar}
%
\begin{definition}\label{def:graphConform}
A \gql graph $\mathcal{G}$ \textit{conforms} to a schema $\mathcal{S}$ if:
%\td{Should this definition include the predicate? \eg, with a value validation predicate bleble}\et{instead say that the value validation predicate is a global (module) parameter -- ok, seems you're doing that in the next paragraph below}
\begin{itemize}
\item the types of $\mathcal{G}$ root node and $\mathcal{S}$ query
root coincide,
\item every node of $\mathcal{G}$ \textit{conforms} to
$\mathcal{S}$, and
\item every edge of $\mathcal{G}$ \textit{conforms} to
$\mathcal{S}$.
\end{itemize}
\end{definition}
%
The conformance of nodes validates that a node's type is declared as
an object type in the schema and that its properties conform. In turn,
a property \emph{conforms} if its key and arguments are defined in a
field in the corresponding object type, and any value, either in an
argument or the property's value, is \emph{valid} \wrt the expected
types described in the schema. For instance, if a field has type
\texttt{Float}, the \spec dictates that a node property matching the
field must have a value that represents a double-precision fractional
value (\cf~\cite[\S3.5.2]{gqlspec}). % \footnote{The \spec
% declares a set of minimal scalar values and how they should be
% represented, such as floating-point values adhering to IEEE 754
% (\cf~\cite[\S3.5.2]{gqlspec}). We do not include these base
% restrictions, leaving it open to the implementation.}
To model this validation of values, we parameterize the \coq development
with a Boolean predicate $\mathit{\vscalar} : \mathit{graphQLSchema}
\to \mathit{Name} \to \mathit{Scalar} \to \mathit{Bool}$.
% \td{Include that conformance does not imply completeness of data (?)}
The conformance of edges imposes some final natural restrictions on
graphs. For instance, given an edge, it requires that the label match
some field in the type of the source node, and that the type of the
target node be compatible with the type of the matched field.
% The full
% definition can be found in the \coq development.
It is worth noting that, in accordance with the flexibility advocated
by graph databases, the notion of conformance does not require that a
graph contain full information about the represented
objects. More precisely, a node need not provide values for all the fields
in its type. For instance, in our running example in
Figure~\ref{fig:graph_ex}, the bottommost node of type \texttt{Book} need not
contain a property defining the book title.
% Finally, the conformance of edges validates that: (1) the label
% matches some field in the type of the source node, (2) the type of the
% target node is compatible with the type of the matched field (by being
% either the same type, an implementation of or member of a union), (3)
% if the type of the field is not a list type, then there should be
% no other outgoing edge from the source node and with the same label, and (4), the
% arguments of the label are defined in the corresponding field in the schema and
% their values are valid \wrt their expected types. \fo{I'm not sure
% whether it is worth giving so many details here. If space is needed,
% maybe we can cut off here.}
% \td{+1}
%includes rules such as checking that a node
%type is declared as an object type in the schema and that its
%properties are defined as fields in the corresponding type. Among
%others, the conformance of edges ensures that edge labels are declared
%as a field in the source node's type and the target node has a type
%compatible with the field's return type. Full definitions of both
%these notions can be found in the \coq development. %are found in file \texttt{GraphConformance.v}.
With this in mind, the notion of conformance of a graph \wrt a schema is formalized as follows:
%
\begin{minted}[bgcolor=coqbg, escapeinside=||]{coq}
Variable |\vscalar| :
graphQLSchema -> Name -> Scalar -> bool.
Definition is_a_conforming_graph
(s : wfGraphQLSchema)
(g : graphQLGraph) : bool :=
root_type_conforms s g.(root) &&
edges_conform s g &&
nodes_conform s g.(nodes).
\end{minted}
%
% As a side note, this notion was only loosely defined in \HP, but it is properly addressed in a recent work of one of its authors ~\cite{olafschema}.
Similarly to \gql schemas, we define a structure that encapsulates the notion of a \textit{conformed} graph, containing a graph and a proof of its conformance to a particular schema.
%\td{Since I mention above that it uses this predicate and show it as a variable, maybe we can skip it?} \et{yes}
\begin{minted}[bgcolor=coqbg, escapeinside=||]{coq}
Record conformedGraph (s : wfGraphQLSchema) :=
ConformedGraph {
graph : graphQLGraph;
_ : is_a_conforming_graph s graph |\vscalar| }.
\end{minted}
%These properties include validation rules such as: every node must have an object type and their properties must be defined in their associated type, or an edge's label must be declared as a field in the source node's type and the target node must have a type compatible to the field's return type, among other things.
%With both the schema and the underlying data model we can proceed to define \gql queries and their semantics.
\subsection{Queries}\label{subsec:query}
To define queries we faithfully follow the \spec, as shown in
Figure~\ref{fig:query_def}. A query consists of a list of selections, and can optionally be named.
% consists of an optional name
% \fo{We should mention this also in \S 2}\td{Not really necessary, or is it?} and a list of selections.
A \emph{selection} $\sel$
can be a single field with arguments ($\fld$), a field
with arguments followed by a set of subselections
($\fld \texttt{\{} \sset \texttt{\}}$) or an inline fragment
comprising a type condition and a set of subselections
($\ifrag{t}{\sset}$). Fields can be aliased ($\afld$, $\afld \texttt{\{} \sset \texttt{\}}$).
For notational simplicity, when a field selection contains an empty list
of arguments, we omit it and simply write the field name.
% Fields can be accompanied by a list of arguments and can also be renamed.
Intuitively, a query has a tree structure, where leaves correspond to
fields of scalar types and inner nodes correspond to either fields of
some object type or abstract type (\ie~ an interface or union),
% \fo{abstract type not defined}\td{Ok like this?}
or to inline fragments that condition when their subselections are evaluated.
\iffalse
%For instance, the query in Figure \ref{fig:qres_ex} can be depicted as the tree in Figure \ref{fig:query_tree}.
\begin{figure}
\centering
\includegraphics[scale=0.33]{imgs/query_tree.png}
\caption{\gql query as a tree.}
\label{fig:query_tree}
\end{figure}
\fi
% Similar to the schema definition, we follow the \spec's grammar as closely as possible, as can be seen from Figure~\ref{fig:query_def}. We do not embed the property of non-emptiness of subqueries in the definition because the \spec pushes it to a different validation rule, even though it is already embedded in the grammar, and we believe it is simpler to reuse the \texttt{seq} library and its existent functionalities.
Observe that the definition of queries in Figure~\ref{fig:query_def}
is not bound to any schema, thus requiring a separate validation
process to ensure that they adhere to a given schema. We introduce the
notion of query \textit{conformance}, based on a set of validation
rules scattered throughout the \spec (\cf \cite[\S5]{gqlspec}). The
validity of queries depends on the validity of their selection sets,
which in turn requires the notion of \textit{type in scope}%
%\begin{minipage}[t]{.25\textwidth}
\begin{wrapfigure}[10]{r}{.20\textwidth}
\vspace{-1.3ex}
\begin{flushright}
\begin{minted}[escapeinside=||, mathescape=true]{text}
query {
movie[id:2000] {
|$\ldots$| on Animation {
title
style
}
|$\ldots$| on Fiction {
title
style
} } }
\end{minted}
\end{flushright}
\end{wrapfigure}
%\end{minipage}%
% \begin{minipage}[t]{.25\textwidth}
% \begin{minted}[escapeinside=||, mathescape=true]{js}
% type Human {
% age: Int
% }
% type Martian {
% age: Float
% }
% \end{minted}
% \end{minipage}
%\et{for space reason, we may want to take some liberties wrt the formatting of queries and responses (see some examples on this page)}
%
at a given selection location. % \footnote{The \spec refers to it as the \emph{type in scope} or \emph{parent type}. Some algorithmic descriptions make use of the types in scope but are not explicit in their signatures.} % Since queries are selections over the fields of types, it is important to know exactly to what type they are being applied.
To illustrate this, consider the query to the right with two occurrences of field \texttt{title}.
\noindent In the first occurrence, the field is requesting information about the
\animation type, while in the second it is requesting information
about the \fiction type. The distinction is important because some
field selections might be valid in some contexts but not in others. %
% \td{Better? I feel there is something wrong, but not sure what}\fo{I
% think it's good}
For instance, this is the case of field \texttt{style}, which is valid in the scope of the \texttt{Animation} type but it is invalid in the scope of the \texttt{Fiction} type, as the \texttt{Fiction} type does not contain any such field. %Similarly, the above query would also be invalid if \texttt{Pig} type contained a so-called field, but of type different from \texttt{Toy} ---the type of the same field in type \texttt{Dog}.
%Just as in the case of well-formedness of schemas or conformance of graphs, queries must go through a validation process. We define the property of \textit{conformance} of queries, based on validation rules scattered throughout the \textit{Validation} section of the \spec\footnote{https://graphql.github.io/graphql-spec/June2018/\#sec-Validation}.
% Before describing the validation process, it is very important to address the notion of \textit{type in scope} where queries are defined and used. The type in scope is the type over which a user might be requesting information on its fields. To illustrate this, consider the following query. The first selection, namely \texttt{goodboi}, is requesting information about the query type, meaning that it is used in the context of the \texttt{Query} type. Moving onto the \texttt{name} subselection, it is not direct which is. In one case, the type in scope is \texttt{Dog}, while in the other the field is used in the context of the \texttt{Pig} type.
% The importance of this type in scope is that fields or inline fragments might be valid in certain cases but not in others. Similarly, a field may have a particular return type in one case and a different one in another type, like in the following example. Both types have an \texttt{age} field, but in one case it returns an integer value while in the other a floating point value. If that field is encountered in a query, it is necessary to know to which type it is being requested.
\begin{figure}[t]
\centering
\begin{displaymath}
\begin{array}{rcl}
\query & ::= & \texttt{query } (\name)^{?} \texttt{ \{} \sset \texttt{\}} \\
&& \\
\sel & ::= & \fld \\
& | & \afld \\
& | & \nfld{\sset} \\
& | & \anfld{\sset} \\
& | & \ifrag{t}{\sset} \\
\end{array}
\end{displaymath}
\begin{minted}[bgcolor=coqbg]{coq}
Record query :=
Query { qname : option string;
selection_set : seq Selection }.
Inductive Selection : Type :=
| SingleField (name : Name)
(arguments : seq (Name * Value))
| SingleAliasedField (alias : Name)
(name : Name)
(arguments : seq (Name * Value))
| NestedField (name : Name)
(arguments : seq (Name * Value))
(subselections : seq Selection)
| NestedAliasedField (alias : Name)
(name : Name)
(arguments : seq (Name * Value))
(subselections : seq Selection)
| InlineFragment (type_condition : Name)
(subselections : seq Selection).
\end{minted}
\caption{Definition of \gql queries:
(top) \spec grammar;
(bottom) \gcoql definition. %\et{why Vals instead of Val?}\td{This was to keep close similarity to \HP (way at the beginning) -- do you think Val is better?}
\newline{\footnotesize In the \spec grammar, symbols \texttt{f}, \texttt{a} and \texttt{t}
correspond to identifiers for field name, field alias, and type condition, respectively.
Symbol $\alpha$ corresponds to a key-value pair.}}
\label{fig:query_def}
\end{figure}
Now that we have clarified the notion of type in scope, we
define the notion of conformance for selection sets.
%\td{A query conforms when its selections conform to the Query type}
\begin{definition}
A \gql selection set $\sset$ \textit{conforms} to a schema $\schema$
over a type in scope $\mathit{ts}$ if:
\begin{itemize}
\item every selection in $\sset$ is well-formed w.r.t $\mathit{ts}$, and
\item any two field selections in $\sset$
are type-compatible and
renaming-consistent.\footnote{In the \spec, these two notions roughly correspond to \emph{SameResponseShape} and
\emph{FieldsInSetCanMerge}, respectively (\cf~\cite[\S5.3.2]{gqlspec}).}
\end{itemize}
\end{definition}
The first rule ensures that every selection is well-formed on its own,
\wrt the type in scope. This requirement depends on the
kind of selection. For instance, if the selection is a field, the rule
checks that the field is part of the type in scope and that its
arguments are correctly provided; if the selection is an inline
fragment, then the type condition must share at least one subtype with
the type in scope. This rule also includes validating the values used
in arguments, similarly to the case of graphs.
In the second rule, the type-compatibility requirement forbids the
selection set to produce results of different types for the same key; \eg the following query
\begin{minipage}[t]{.22\textwidth}
\begin{minted}[escapeinside=||,mathescape=true]{js}
query {
artist[id:1000] {
artworks[role:ACTOR] {
|$\ldots$| on Animation {
title
}
|$\ldots$| on Fiction {
title:year
} } } }
\end{minted}
\end{minipage}%
\begin{minipage}[t]{.22\textwidth}
\begin{minted}[escapeinside=||,mathescape=true]{js}
// Possible invalid output
{
"artist": {
"artworks": [
{ "title": "Toy Story" },
{ "title": 1994 }
]
}
}
\end{minted}
\end{minipage}
\medskip
\noindent is invalid because its evaluation produces results with the same key
(\texttt{title}) but associated to values of different types (\ie
string and integer).
%\td{We are not exactly capturing that the fields can be inside fragments, is it ok?}\et{I don't get it}
Formally, the definition of field \emph{type-compatibility} is
recursive. Two nested field selections are type-compatible if whenever
they have the same response name, any two fields in the concatenation
of their subselections (possibly reached traversing inline fragments)
are also type-compatible. Two single field selections are always
type-compatible, unless they have the same response name and
different %(scalar or enum)
type.
Finally, the renaming-consistency condition ensures that fields with
the same response name refer to the same piece of
information. Consider, for instance, the following query:
% \td{This leaves a lot of empty space :/}
\begin{minted}[escapeinside=||,mathescape=true]{js}
query {
movie[id:2000] {
title
|$\ldots$| on Animation {
title:style
} } }
\end{minted}
\medskip
\noindent The query is considered invalid because the fields with response name \texttt{title} both refer to distinct pieces of information;
the first occurrence refers to the field \texttt{title} of a \texttt{Movie}, while the second
occurrence refers to the field \texttt{style} of an \texttt{Animation}.
%\fo{Add example and briefly explain}
Formally, two field selections are \emph{renaming-consistent} if
whenever they have the same response name and lie under types in scope
with at least one common subtype,
% \fo{@Eric, is there any standard terminology for this
% ``overlapping'', meaning that they share at least one subtype?},
% \et{sharing a subtype means that their "(subtyping) meet/glb" exists--is that what you're referring to?}
% \td{Yeah, at least I believe it is}
they have the same (actual) name, the same arguments and any two
fields in the concatenation of their subselections (possibly reached
traversing inline fragments) are also renaming-consistent.
%
In the \spec, the last two rules are defined as a single validation
rule (\cf~\cite[\S5.3.2]{gqlspec}).
%
We chose to split them because it simplified both their implementation and reasoning about them.\footnote{\gcoql uses an optimized
version of the algorithm in the \spec. Recently, a team at XING
developed another optimized algorithm~\cite{xingalg}.}
With the notion of conformance for selection sets at hand, the notion
of conformance for queries is straightforward:
\begin{definition}
A \gql query $\query$ \textit{conforms} to a schema $\schema$ if its selection set conforms to $\schema$ over the query root type.
\end{definition}
%\et{this is the beginning of the problem I'm having with your statements about queries. There is the notion of *a query*, noted $\varphi$, yet from now on your statements are about *queries*. The definition below mixes "the content" (consistency, compatible response, etc.) with "the sequence" (all, list comprehension, etc). Worse, later on in the development, you use $\varphi$ as the variable name of type "seq Queries" (while fig6 uses a bar over). See also my later comments about your "plural formulations"}
\noindent In \gcoql, this is captured by the following predicates:
%\td{Updated}
%\td{Need to adjust names}
%The implementation can be seen in the code below, however due to space limitations we only informally describe the %three mentioned rules. The complete definitions can be found in the file \texttt{QueryConformance.v}.
%\td{Similar case}
\begin{minted}[bgcolor=coqbg, escapeinside=@@, mathescape=true]{coq}
Definition query_conforms
(s : wfGraphQLSchema) (@$\query$@ : query) : bool :=
selections_conform s s.(query_type) @$\query$@.(selection_set).
Definition selections_conform (s : wfGraphQLSchema)
(ts : Name) (@$\sel$@s : seq Selection) : bool :=
let @$\sel$@s_with_scope := [seq (ts, @$\sel$@) | @$\sel$@ <- @$\sel$@s] in
all (is_consistent ts) @$\sel$@s &&
@$\sel$@s_with_scope.(are_type_compatible) &&
@$\sel$@s_with_scope.(are_renaming_consistent).
\end{minted}
% This concludes the definition of \gql queries, the validation process and the notion of size of selections.
As a technical observation, most of our recursive definitions over
selection sets are well-founded according to the following notion of
size:
\begin{definition}[\cite{gqlph}]
% \td{It is in essence the same, except that they define selections along with queries}
The \emph{size} of a selection $\sel$ and selection set $\sset$, noted $\ssize{\cdot}$, is recursively defined as:
\begin{small}
\begin{align*}
\ssize{\fld} = \ssize{\afld} &= 1\\
\ssize{\nfld{\sset}} = \ssize{\anfld{\sset}} = \ssize{\ifrag{t}{\sset}} &= 1 + \ssize{\sset}\\
\ssize{\sset} &= \textstyle\sum_{\sel_{i} \in\; \sset}{\ssize{\sel_{i}}}
\end{align*}
\end{small}
\end{definition}
% For the reminder of our presentation, we assume that queries conform to a given schema.
%\td{Cannot define $\sset$ in Coq (lexer error), so I had to go with $\sel$ instead of the selection set and simply \texttt{sel} for an atomic selection}
%\et{you can use "$\sel$s"}
%\fo{This introduces the conformance of a query \wrt a schema, but the schema is never mentioned in the definition. It needs to be fixed!!!}
%has to be valid with respect to the type in scope \fo{when can it not be valid?}\td{If both the type condition and the type in scope do not share at least one subtype (subtype is reflexive). Not sure if this is relevant here though}.%The \spec defines this rule in several different sections.
% The second rule validates when fields can be correctly merged during evaluation, which is an essential aspect of the semantics, since it ensures that repeated fields are only evaluated once. To illustrate this, consider the following query, where a user requests information on the fields \texttt{name} and \texttt{oink} of pigs. The user decides to rename the field \texttt{oink} to \texttt{name}, however this is invalid, since both fields cannot be merged and evaluated once; both fields refer to distinct pieces of information in the system.
% \begin{minted}[escapeinside=||,mathescape=true]{js}
% query {
% goodboi {
% name
% |$\ldots$| on Pig {
% name
% toy:oink
% }
% |$\ldots$| on Dog {
% name
% toy:age
% }
% } } }
% \end{minted}
% The last rule is necessary to check when fields generate consistent values when evaluated. For instance, in the query below a user might request the names of dogs and the oinkness of pigs, but renaming the latter to have the same response name as the former. This query is considered invalid because evaluating it might produce a response that contains entries where the key \texttt{name} is associated to both string values and floating point numbers.
% \begin{minipage}[t]{.22\textwidth}
% \begin{minted}[escapeinside=||,mathescape=true]{js}
% query {
% goodboi {
% friends {
% |$\ldots$| on Dog {
% name
% }
% |$\ldots$| on Pig {
% name:oink
% } } } }
% \end{minted}
% \end{minipage}%
% \begin{minipage}[t]{.22\textwidth}
% \begin{minted}[escapeinside=||,mathescape=true]{js}
% // Possible invalid output
% {
% "goodboi" : {
% "friends" : [
% { "name" : "Marle" },
% { "name" : 9000 }
% ]
% } }
% \end{minted}
% \end{minipage}
% The main issue is that the \spec allows for what we call \textit{invalid fragments}, originally described in an issue in the \spec's repository\footnote{https://github.com/graphql/graphql-spec/issues/367}. In a nutshell, the \spec allows using fragments with type conditions that can span to multiple unrelated types. These end up not being evaluated due to posterior checks\footnote{https://graphql.github.io/graphql-spec/June2018/\#DoesFragmentTypeApply()}.
% \td{This looks a bit weird... Should it be a "definition" or just inline it as \HP does?}
\subsection{Semantics}\label{subsec:semantics}
\begin{figure*}[t!]
\centering
\begin{subfigure}{.5\textwidth}
\begin{displaymath}
\begin{array}{rcl}
\response & ::= & \texttt{v}\\
& | & \texttt{\{} (\fkey : \response) \ldots (\fkey : \response) \texttt{\}} \\
& | & \texttt{[} \response \ldots \response \texttt{]}
\end{array}
\end{displaymath}
\iffalse
\begin{grammar}
<ResponseValue> ::= <value>
\alt \textbf{\texttt{\{}} (<name> \textbf{\texttt{:}} <ResponseValue>)* \textbf{\texttt{\}}}
\alt \textbf{\texttt{[}} <ResponseValue>* \textbf{\texttt{]}}
\end{grammar}
\fi
\end{subfigure}%
\begin{subfigure}{.5\textwidth}
\begin{minted}[bgcolor=coqbg]{coq}
Inductive ResponseValue : Type :=
| Leaf : option Scalar -> ResponseValue
| Object : seq (Name * ResponseValue) -> ResponseValue
| Array : seq ResponseValue -> ResponseValue.
Definition GraphQLResponse := seq (Name * ResponseValue).
\end{minted}
\end{subfigure}
\caption{Definition of \gql responses: (left) grammar à la
JSON; (right) \gcoql definition.
%\et{the @ sign here shouldn't be necessary since A is an explicit parameter (I suspect in your Coq dev it's implicit)}\et{wait, that definition of ResponseValue cannot possibly be correct: if A is an explicit parameter, you can't use those constructor signatures, so you should declare with curly brackets.}
%\et{Explain in the text what's going on with the parametrization over eqType.}
\newline{\footnotesize The keywords \texttt{v} and \fkey\ represent leaf values and keys in a key-value pair, respectively.}
}
\label{fig:response_def}
\end{figure*}
Now we have all the prerequisites to define the semantics of \gql queries and their selection sets. We begin by briefly examining the responses generated by executing queries and then we give an informal description of the semantics, finishing with the formal definition. %We finish by discussing some implementation choices and comparison with the \spec and \HP.
Roughly speaking, a \gql response maps keys (field names) to response
values. We model response values with a tree structure, similar to
JSON. Concretely, a response value can be either a value in
\texttt{Scalar} or the distinguished value \texttt{null}, an object
mapping keys to other response values, or an array of response
values. Full definition is provided in Figure~\ref{fig:response_def}.
% Null values in the leaves of the response tree are represented with option types.%\et{fix once fig 6 defs is clarified}
% \et{this is not an appropriate description of the Coq definition: explain the parametrization that's going on. Then, if one accepts your parametrization by the eqType, why not baking the option in the Leaf constructor directly? (ie. Leaf : option A $\rightarrow$ RV)}
% \td{Is it ok with the changes?}
%
%\fo{What is the role of \texttt{ArrayResponse}? When presenting our domain of values \textit{Vals} you mentioned that it can be a scalar value, or a ``list'' of values. Is the \texttt{ArrayResponse} the counterpart of this ``list''? }
%\fo{Explain the role of each constructor}
%\fo{Shouldn't the ObjectResponse constructor take a GraphQLResponse argument?}
%\begin{figure}[h]
%\caption{Implementation in Coq of \gql responses.}
%\label{fig:responses}
%\end{figure}
% As we described in \S\ref{subsec:graph}, the underlying data model we use is a graph, therefore the semantics are instantiated to this setting. %In a following paragraph we briefly explore an alternative that is closer to the \spec, in the sense that it can be detached from a particular data model.
%\td{Maybe merge this informal description with the description of the figure?}
%\et{yes}
As a first step to define the semantics of queries, we observe that it
is not compositional, in the sense that the result of a sequence of
selections is not obtained by simply concatenating the results of
individual selections. Therefore, the evaluation function takes as
input a (whole) selection set, rather than single selections.
Informally, the evaluation of a selection set represents a navigation
over a graph, starting from the root node, traversing its edges and
collecting data from its nodes. To build the response, the values in
nodes are coerced into proper response values. If this coercion
fails or the data requested by the selection set is not present in the
graph, the evaluation function simply returns \texttt{null}.
This validating transformation from values within graph nodes into
values within responses is captured by the function
$\mathit{complete\_value}$ (\cf~\cite[\S6.4.3]{gqlspec}). To carry out
the transformation the function relies on two auxiliary functions:
$\mathit{coerce}$ that coerces scalar values and $\mathit{\vscalar}$
that checks whether the resulting values have the expected type
according to the schema.\footnote{Function $\mathit{\vscalar}$ is also used
for verifying the conformance of graphs \wrt schemas; see \S
\ref{subsec:graph}.}
% This data retrieval from nodes can,
% however, be unsuccessful for several reasons. For instance, a query
% might request non-existent information or might yield a response value
% of an unexpected type.
% % (Bear in mind that the evaluation function is
% % total and accepts queries that conform to the corresponding schema as
% % well as queries that do not.)
% In these cases, the evaluation function simple returns
% \texttt{null}. On the other hand, values in nodes that are indeed
% employed for constructing a query response are \emph{coerced} into
% proper response values.
With this in mind, we can now define the evaluation function of
selection sets.
\begin{figure*}[h!]
\small
\begin{flushright}
\fbox{$\eval{\cdot}{u} ~\colon~ \textit{seq Selection} \rightarrow \textit{GraphQLResponse}$}
\end{flushright}
\centering
\vspace{-1ex}
\begin{align*}
% signature
% & \\[2ex]
% Empty
& (1) & \eval{\cdot}{u} &~=~ [\cdot] \\
% SingleField
& (2) & \evalu{\fld :: \sset} &~=~
\resp{(\mathit{complete\_value(\ftype{u.type}{\fkey}, u.property(\fld))})} :: \evalfilteru{\sset}{\fkey} \\
% Nested field
& (3) & \evalu{\nfld{\overline{\beta}} :: \sset} &~=~
\begin{cases}
\resp{\texttt{[} \mathit{map}\; (\lambda v_{i}.\; \texttt{\{} \eval{\overline{\beta} \mdoubleplus \mathit{merge (\collect{u.type}{\fkey}{\sset})}}{v_{i}} \texttt{\}})\; \mathit{u.neighbors_{\graph}(\fld)} \texttt{]}} :: \evalfilteru{\sset}{\fkey} \\
\qquad \qquad \qquad \qquad \qquad \qquad
\text{ if }
\mathit{\ftype{u.type}{\fkey}} = \mathit{list} \text{ and } \{v_{1}, \ldots, v_{k}\} =
\{v_{i} \mid (u, \fkey[\alpha], v_{i}) \in \mathit{edges}(\graph)\} \\
%
\fkey:\texttt{\{}\eval{\overline{\beta} \mdoubleplus \mathit{merge (\collect{u.type}{\fkey}{\sset})}}{v}\texttt{\}} :: \evalfilteru{\sset}{\fkey} \\
\qquad \qquad \qquad \qquad \qquad \qquad \qquad
\text{ if }
\mathit{\ftype{u.type}{\fkey}} \neq \mathit{list} \text{ and } (u, \fkey[\alpha], v) \in \mathit{edges}(\graph) \\
%
\resp{\nval} :: \evalfilteru{\sset}{\fkey}
\qquad \qquad \qquad \qquad
\text{ if } \mathit{\ftype{u.type}{\fkey}} \neq \mathit{list} \text{ and } \nexists v \text{ s.t. } (u, \fkey[\alpha], v) \in \mathit{edges}(\graph) \\
\end{cases}\\
%inline fragment
& (4) & \evalu{\ifrag{t}{\overline{\beta}} :: \sset} &~=~
\begin{cases}
\evalu{\overline{\beta} \mdoubleplus \sset}
& \text{ if }\mathit{fragment\_type\_applies(u.type, \texttt{t})}\\
\evalu{\sset}
& \text{ otherwise}
\end{cases}
\end{align*}
\caption{Semantics of \gql selection sets, adapted from~\HP and the \spec.
% \td{$\mathit{fragment\_type\_applies}$ is actually called $\mathit{does\_fragment\_type\_applies}$ in the spec (as I had it before).
% This one is simpler to read and makes more sense, but I
% wondered if it shouldn't be the other name}\fo{Added as a
% footnote, in the text.}
\newline {\footnotesize
As usual, notation $x :: y$ on the left denotes pattern matching deconstruction of a list into its head $x$ and tail $y$; on the right, it denotes list construction.\newline
$\mathit{property}$ and $\mathit{type}$ are accessors to a node property and type. $\mathit{neighbors}$ gets the neighbors of a node whose edge is labeled with the given field.
%\td{To make it look cleaner, we can maybe use "u.property($\fld$)"
% and "u.type"}\fo{fully agree; the same for neighbors}
%\td{Not forget to update the simplified semantics} \fo{please, go
% for it}
$\mathit{edges}$ gets the set of edges of a graph.
$\mathit{ftype}$ retrieves the type of a field from the underlying
schema. $\mathit{list}$ represents the list type (over any other type).}}
%The $\mathit{property}$ function is an accessor to a node's property value. The $\mathit{filter}$ function removes all fields with the given response name, while $\mathit{collect}$ gathers all fields that match the given response name.
%Meanwhile, $\mathit{merge}$ joins the subqueries of the input selections. The $\mathit{type}$ function retrieves the type of the given field in the node's type.
%The $\mathit{fragment\_type\_applies}$ predicate checks if the fragment's type condition is related to the node's type and whether its contents should be evaluated in the given node.
%Finally, $E$ are the graph's edges, while $L_{t}$ is simply the list type.
% \et{then why the $_t$ subscript?}\td{Simply bc its "List type" -- I took the same notation as in \HP to somehow show the similarity between both definitions.}\et{remove it, it's confusingly suggesting that the L type is indexed by some t}}
% % \fo{This definition is given using syntax you have never introduced (what does :: mean? what does f:v mean? what does ++ mean?, etc, etc). Also, you must explain what all auxiliary functions (filter, property, merge, neighbors, etc, etc) do}
% \et{explain also what are $u$ $G$ $L_t$ and $E$}
% \et{rename does\_fragment\_type\_apply to fragment\_type\_applies (and make it hide the $=$ true.)}
\label{fig:semantics}
\end{figure*}
% Because \gql is not tied to any technology, the resolution of selections in a query might produce invalid results\td{Actually, I mean that they might not exist -- null} or in a different format than expected (\eg integer values as strings).
% In order to resolve these potential issues, the \spec considers invalid results as null values and
% requires that valid ones are \emph{coerced} into proper values, which must also respect the expected types (otherwise are also considered null).
%\begin{itemize}
% \item A field selection represents either accessing a node's property or traversing an edge to a neighboring node.
% \item An inline fragment conditions whether using a node to access its properties or to traverse to other nodes.
% \item Subselections are evaluations over neighboring nodes.
%\end{itemize}
\begin{definition}
Let $\graph$ be a graph and $\sset$ a selection set, both conforming
to a schema $\schema$. The evaluation $\llbracket \sset
\rrbracket^{u}_{\graph}$ of $\sset$ over graph $\graph$
from node $u \in \mathit{nodes}(\graph)$ % \footnote{Where
% $\mathit{nodes}$ is a function that retrieves all nodes from a
% graph.}
is defined by the rules in Figure~\ref{fig:semantics}. The evaluation function is parametrized by a coercing function
$\mathit{coerce} \colon \mathit{Scalar} \to \mathit{Scalar}$ and a
value validation predicate
$\mathit{\vscalar} \colon \mathit{graphQLSchema} \to \mathit{Name}
\to \mathit{Scalar} \ \to \mathit{Bool}$. % required to define function
% $\mathit{complete\_value}$, used in rule (2) of the figure.
\end{definition}
In order not to clutter the notation, we omit the underlying schema
when defining $\llbracket \sset \rrbracket^{u}_{\graph}$ in
Figure~\ref{fig:semantics}. The schema is implicitly used \eg when
invoking function $\mathit{complete\_value}$.
%Informally, the evaluation of a query's selection set represents a navigation over a graph, starting from the root node, traversing its edges and collecting data from its nodes.
The definition starts with the base case of empty selection set (1),
which results in an empty response. Single fields (2) correspond to
accessing a node's property that matches the field name and using
function $\mathit{complete\_value}$ to coerce and validate the
requested value. This function is implemented by simply calling
$\mathit{coerce}$ and $\mathit{\vscalar}$.
% . To ensure
% that only valid results are produced, the function
% $\mathit{complete\_value}$ (\cf~\cite[\S6.4.3]{gqlspec}) transforms
% invalid values into \texttt{null} and coerces valid ones, after
% checking that they adhere to their expected types according to the
% schema\td{Maybe correction here also, about invalid coercion resulting in null values as well?}. % The coercion function is included as a parameter in the
% % corresponding modules.
Nested fields (3) represent a traversal to neighboring nodes: the
evaluation function searches for nodes that are connected to the
current node by an edge whose label matches the field name and then
evaluates the subselections on these nodes. If the field has list
type, there is no constraint on the number of such neighboring nodes
to recursively continue the evaluation. On the contrary, if the field
does not have list type, then there should be exactly one neighboring
node to successfully continue the recursive evaluation on this node
(the case of multiple neighboring nodes is discarded by the
conformance assumption); if there is no neighbor, the result is
considered
\texttt{null}. %\td{Rewrote this to use "at most" and simplify text}
To avoid the duplication of responses, rules (2) and (3) handling the
evaluation of fields ensure that within a selection set, fields with the same
response name are evaluated only once. This is achieved by collecting
and merging all fields in subsequent selections that have the same
response name as the current field being evaluated (using auxiliary functions
$\mathit{collect}$ and $\mathit{merge}$) and removing these fields
from subsequent selections (using auxiliary function
$\mathit{filter}$), before they are evaluated.
Finally, inline fragments (4) simply condition whether their
subselections are evaluated (in the current node) or not. The decision
is based on the $\mathit{fragment\_type\_applies}$ predicate (\cf
\cite[\S6.3.2]{gqlspec}) that verifies whether the guard type matches
the current node type or supertype thereof.\footnote{Function
$\mathit{fragment\_type\_applies}$ is called
$\mathit{does\_fragment\_type\_applies}$ in the \spec.}
For space reason, Figure~\ref{fig:semantics} does not present aliased fields. They are evaluated the same way as unaliased fields, but differ in that the
produced key-value pairs are renamed accordingly.
%The definition of the evaluation function for selections, displayed in Figure~\ref{fig:semantics}, only refers to the base case of an empty list, field selections without renaming and inline fragments. The complete definition can be found in the file \texttt{QuerySemantics.v}.
\begin{definition}
Let $\graph$ be a graph and $\query$ a query, both conforming to a schema $\schema$. The result of