Convert AST to LCP
Reviewers: teon.banek, llugovic Reviewed By: teon.banek Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D1628
This commit is contained in:
parent
ed335e38ff
commit
db52b35ab6
2
.gitignore
vendored
2
.gitignore
vendored
@ -66,6 +66,8 @@ src/distributed/token_sharing_rpc_messages.capnp
|
||||
src/distributed/token_sharing_rpc_messages.hpp
|
||||
src/distributed/updates_rpc_messages.capnp
|
||||
src/distributed/updates_rpc_messages.hpp
|
||||
src/query/frontend/ast/ast.capnp
|
||||
src/query/frontend/ast/ast.hpp
|
||||
src/query/plan/distributed_ops.capnp
|
||||
src/query/plan/distributed_ops.hpp
|
||||
src/query/plan/operator.hpp
|
||||
|
@ -117,6 +117,8 @@ add_capnp(distributed/dynamic_worker_rpc_messages.capnp)
|
||||
|
||||
# distributed_ops.lcp is leading the capnp code generation, so we don't need
|
||||
# to generate any capnp for operator.lcp
|
||||
add_lcp(query/frontend/ast/ast.lcp CAPNP_SCHEMA @0xb107d3d6b4b1600b)
|
||||
add_capnp(query/frontend/ast/ast.capnp)
|
||||
add_lcp(query/plan/operator.lcp)
|
||||
add_lcp(query/plan/distributed_ops.lcp CAPNP_SCHEMA @0xe5cae8d045d30c42
|
||||
DEPENDS query/plan/operator.lcp)
|
||||
@ -134,7 +136,6 @@ add_custom_target(generate_lcp DEPENDS ${generated_lcp_files})
|
||||
|
||||
add_capnp(communication/rpc/messages.capnp)
|
||||
add_capnp(durability/recovery.capnp)
|
||||
add_capnp(query/frontend/ast/ast.capnp)
|
||||
add_capnp(query/frontend/semantic/symbol.capnp)
|
||||
add_capnp(query/serialization.capnp)
|
||||
add_capnp(storage/serialization.capnp)
|
||||
|
@ -272,6 +272,7 @@ produces:
|
||||
;; Extra arguments to the generated save function. List of (name cpp-type).
|
||||
(save-args nil :read-only t)
|
||||
(load-args nil :read-only t)
|
||||
(construct nil :read-only t)
|
||||
;; Explicit instantiation of template to generate schema with enum.
|
||||
(type-args nil :read-only t)
|
||||
;; In case of multiple inheritance, list of classes which should be handled
|
||||
@ -291,7 +292,8 @@ produces:
|
||||
(private :initarg :private :initform nil :accessor cpp-class-private)
|
||||
(capnp-opts :type (or null capnp-opts) :initarg :capnp-opts :initform nil
|
||||
:reader cpp-class-capnp-opts)
|
||||
(inner-types :initarg :inner-types :initform nil :reader cpp-class-inner-types))
|
||||
(inner-types :initarg :inner-types :initform nil :reader cpp-class-inner-types)
|
||||
(abstractp :initarg :abstractp :initform nil :reader cpp-class-abstractp))
|
||||
(:documentation "Meta information on a C++ class (or struct)."))
|
||||
|
||||
(defvar *cpp-classes* nil "List of defined classes from LCP file")
|
||||
@ -759,7 +761,7 @@ encoded as union inheritance in Cap'n Proto."
|
||||
(write-line (capnp-schema inner) s)))
|
||||
(when union-subclasses
|
||||
(with-cpp-block-output (s :name "union")
|
||||
(when union-parents
|
||||
(when (not (cpp-class-abstractp cpp-class))
|
||||
;; Allow instantiating classes in the middle of inheritance
|
||||
;; hierarchy.
|
||||
(format s " ~A @~A :Void;~%"
|
||||
@ -935,7 +937,7 @@ Proto schema."
|
||||
(format nil "Save(~A, &~A~{, ~A~});"
|
||||
member-name member-builder extra-args))))))
|
||||
|
||||
(defun capnp-save-members (cpp-class &key instance-access)
|
||||
(defun capnp-save-members (cpp-class builder &key instance-access)
|
||||
"Generate Cap'n Proto saving code for members of CPP-CLASS. INSTANCE-ACCESS
|
||||
is a C++ string which is prefixed to member access. For example,
|
||||
INSTANCE-ACCESS could be `my_struct->`"
|
||||
@ -954,7 +956,7 @@ Proto schema."
|
||||
(cond
|
||||
((and (not (cpp-member-capnp-save member))
|
||||
(capnp-primitive-type-p (capnp-type-of-member member)))
|
||||
(format s " builder->set~A(~A);~%" capnp-name member-access))
|
||||
(format s " ~A->set~A(~A);~%" builder capnp-name member-access))
|
||||
(t
|
||||
;; Enclose larger save code in new scope
|
||||
(with-cpp-block-output (s)
|
||||
@ -965,9 +967,9 @@ Proto schema."
|
||||
"")))
|
||||
(if (and (cpp-member-capnp-init member)
|
||||
(not (find-cpp-enum (cpp-member-type member))))
|
||||
(format s " auto ~A = builder->init~A(~A);~%"
|
||||
member-builder capnp-name size)
|
||||
(setf member-builder "builder")))
|
||||
(format s " auto ~A = ~A->init~A(~A);~%"
|
||||
member-builder builder capnp-name size)
|
||||
(setf member-builder builder)))
|
||||
(if (cpp-member-capnp-save member)
|
||||
(format s " ~A~%"
|
||||
(cpp-code (funcall (cpp-member-capnp-save member)
|
||||
@ -976,84 +978,60 @@ Proto schema."
|
||||
member-builder capnp-name)
|
||||
s))))))))))
|
||||
|
||||
(defun capnp-save-parents (cpp-class save-parent)
|
||||
"Generate Cap'n Proto code for serializing parent classes of CPP-CLASS.
|
||||
SAVE-PARENT is a function which generates the code for serializing a parent.
|
||||
It takes a parent class symbol."
|
||||
(declare (type cpp-class cpp-class))
|
||||
(declare (type (function (symbol) string) save-parent))
|
||||
(multiple-value-bind (direct-union-parents compose-parents)
|
||||
(capnp-union-and-compose-parents cpp-class)
|
||||
(declare (ignore direct-union-parents))
|
||||
;; Handle the union inheritance calls first.
|
||||
(with-output-to-string (s)
|
||||
(let ((parents (capnp-union-parents-rec cpp-class)))
|
||||
(when parents
|
||||
(let ((first-parent (first parents)))
|
||||
(write-line (funcall save-parent first-parent) s))
|
||||
(if (or compose-parents (cpp-class-members cpp-class))
|
||||
(progn
|
||||
(format s " auto ~A_builder = base_builder->~{get~A().~}init~A();~%"
|
||||
(cpp-variable-name (cpp-type-base-name cpp-class))
|
||||
(mapcar #'cpp-type-name (cdr (reverse parents)))
|
||||
(cpp-type-name cpp-class))
|
||||
(format s " auto *builder = &~A_builder;~%"
|
||||
(cpp-variable-name (cpp-type-base-name cpp-class))))
|
||||
(format s " base_builder->~{get~A().~}init~A();~%"
|
||||
(mapcar #'cpp-type-name (cdr (reverse parents)))
|
||||
(cpp-type-name cpp-class)))
|
||||
(when (capnp-union-subclasses cpp-class)
|
||||
;; We are in the middle of inheritance hierarchy, so set our
|
||||
;; union Void field.
|
||||
(format s " builder->set~A();" (cpp-type-name cpp-class)))))
|
||||
;; Now handle composite inheritance calls.
|
||||
(dolist (parent compose-parents)
|
||||
(with-cpp-block-output (s)
|
||||
(let* ((builder (format nil "~A_builder" (cpp-variable-name parent))))
|
||||
(format s " auto ~A = builder->init~A();~%" builder (cpp-type-name parent))
|
||||
(format s " auto *builder = &~A;~%" builder)
|
||||
(write-line (funcall save-parent parent) s)))))))
|
||||
|
||||
(defun capnp-save-function-code (cpp-class)
|
||||
"Generate Cap'n Proto save code for CPP-CLASS."
|
||||
(declare (type cpp-class cpp-class))
|
||||
(labels ((save-class (cpp-class cpp-out)
|
||||
"Output the serialization code for members of this and parent class."
|
||||
(write-line (capnp-save-parents cpp-class #'save-parent) cpp-out)
|
||||
;; Set the template instantiations
|
||||
(when (and (capnp-opts-type-args (cpp-class-capnp-opts cpp-class))
|
||||
(/= 1 (list-length (cpp-type-type-params cpp-class))))
|
||||
(error "Don't know how to save templated class ~A" (cpp-type-base-name cpp-class)))
|
||||
(let ((type-param (first (mapcar #'cpp-type-name (cpp-type-type-params cpp-class)))))
|
||||
(dolist (type-arg (mapcar #'cpp-type-name
|
||||
(capnp-opts-type-args (cpp-class-capnp-opts cpp-class))))
|
||||
(write-string
|
||||
(raw-cpp-string
|
||||
#>cpp
|
||||
if (std::is_same<${type-arg}, ${type-param}>::value) {
|
||||
builder->set${type-arg}();
|
||||
}
|
||||
cpp<#)
|
||||
cpp-out)))
|
||||
(write-line (capnp-save-members cpp-class :instance-access "self.") cpp-out))
|
||||
(save-parent (parent)
|
||||
"Generate serialization code for parent class."
|
||||
(let ((cpp-class (find-cpp-class parent)))
|
||||
(with-output-to-string (s)
|
||||
(with-cpp-block-output (s)
|
||||
(format s "// Save base class ~A~%" (cpp-type-name parent))
|
||||
(save-class cpp-class s))))))
|
||||
(labels ((save-class (cpp-class builder cpp-out &key (force-builder nil))
|
||||
"Output the serialization code for CPP-CLASS and its parent classes."
|
||||
(let* ((compose-parents (nth-value 1 (capnp-union-and-compose-parents cpp-class)))
|
||||
(parents (capnp-union-parents-rec cpp-class))
|
||||
(first-parent (find-cpp-class (first parents))))
|
||||
(when first-parent
|
||||
(with-cpp-block-output (cpp-out)
|
||||
(format cpp-out "// Save parent class ~A~%" (cpp-type-name first-parent))
|
||||
(save-class first-parent builder cpp-out)))
|
||||
;; Initialize CPP-CLASS builder
|
||||
(when parents
|
||||
(if (or force-builder compose-parents (cpp-class-members cpp-class))
|
||||
(progn
|
||||
(format cpp-out "auto ~A_builder = ~A->~{get~A().~}init~A();~%"
|
||||
(cpp-variable-name (cpp-type-base-name cpp-class))
|
||||
builder
|
||||
(mapcar #'cpp-type-name (cdr (reverse parents)))
|
||||
(cpp-type-name cpp-class))
|
||||
(format cpp-out "auto *builder = &~A_builder;~%"
|
||||
(cpp-variable-name (cpp-type-base-name cpp-class)))
|
||||
(setf builder "builder"))
|
||||
(format cpp-out "~A->~{get~A().~}init~A();~%"
|
||||
builder
|
||||
(mapcar #'cpp-type-name (cdr (reverse parents)))
|
||||
(cpp-type-name cpp-class))))
|
||||
;; Save composed parent classes
|
||||
(dolist (parent compose-parents)
|
||||
(with-cpp-block-output (cpp-out)
|
||||
(let* ((parent-builder (format nil "~A_builder" (cpp-variable-name parent))))
|
||||
(format cpp-out "// Save composed class ~A~%" (cpp-type-name parent))
|
||||
(format cpp-out "auto ~A = ~A->init~A();~%"
|
||||
parent-builder builder (cpp-type-name parent))
|
||||
(format cpp-out "Save(self, &~A~{, ~A~});"
|
||||
parent-builder
|
||||
(mapcar (lambda (name-and-type)
|
||||
(cpp-variable-name (first name-and-type)))
|
||||
(capnp-extra-args (find-cpp-class parent) :save))))))
|
||||
;; Save members
|
||||
(write-string (capnp-save-members cpp-class builder :instance-access "self.") cpp-out))))
|
||||
(with-output-to-string (cpp-out)
|
||||
(let ((subclasses (direct-subclasses-of cpp-class)))
|
||||
(let ((subclasses (capnp-union-subclasses cpp-class))
|
||||
(builder (if (capnp-union-parents-rec cpp-class)
|
||||
"base_builder"
|
||||
"builder")))
|
||||
(when subclasses
|
||||
(write-line "// Forward serialization to most derived type" cpp-out)
|
||||
(dolist (subclass subclasses)
|
||||
(let ((derived-name (cpp-type-name subclass))
|
||||
(save-args
|
||||
(format nil "~A~{, ~A~}"
|
||||
(if (capnp-union-parents-rec cpp-class)
|
||||
"base_builder"
|
||||
"builder")
|
||||
builder
|
||||
(mapcar (lambda (name-and-type)
|
||||
(cpp-variable-name (first name-and-type)))
|
||||
(capnp-extra-args cpp-class :save))))
|
||||
@ -1077,8 +1055,18 @@ It takes a parent class symbol."
|
||||
return Save(*derived, ${save-args});
|
||||
}
|
||||
cpp<#)
|
||||
cpp-out))))))
|
||||
(save-class cpp-class cpp-out))))
|
||||
cpp-out)))))
|
||||
(cond
|
||||
((cpp-class-abstractp cpp-class)
|
||||
(format cpp-out
|
||||
"LOG(FATAL) << \"Should not get here -- `~A` should be an abstract class!\";"
|
||||
(cpp-type-name cpp-class)))
|
||||
((capnp-union-subclasses cpp-class)
|
||||
;; We are in the middle of inheritance hierarchy, so set our
|
||||
;; union Void field.
|
||||
(save-class cpp-class builder cpp-out :force-builder t)
|
||||
(format cpp-out "builder->set~A();~%" (cpp-type-name cpp-class)))
|
||||
(t (save-class cpp-class builder cpp-out)))))))
|
||||
|
||||
(defun capnp-save-function-definition (cpp-class)
|
||||
"Generate Cap'n Proto save function."
|
||||
@ -1124,7 +1112,7 @@ It takes a parent class symbol."
|
||||
'reader)
|
||||
(format nil "const capnp::~A::Reader &" top-parent-class)))
|
||||
(out-arg (list 'self
|
||||
(if (or parents (direct-subclasses-of cpp-class))
|
||||
(if (or parents (capnp-union-subclasses cpp-class))
|
||||
(format nil "std::unique_ptr<~A> *" (cpp-type-decl cpp-class :namespace nil))
|
||||
(format nil "~A *" (cpp-type-decl cpp-class :namespace nil))))))
|
||||
(cpp-function-declaration
|
||||
@ -1178,7 +1166,7 @@ reader variable. CAPNP-NAME is the name of the member in Cap'n Proto schema."
|
||||
(format nil "Load(&~A, ~A~{, ~A~});"
|
||||
member-name member-reader extra-args))))))
|
||||
|
||||
(defun capnp-load-members (cpp-class &key instance-access)
|
||||
(defun capnp-load-members (cpp-class reader &key instance-access)
|
||||
"Generate Cap'n Proto loading code for members of CPP-CLASS.
|
||||
INSTANCE-ACCESS is a C++ string which will be prefixed to member access. For
|
||||
example, INSTANCE-ACCESS could be `my_struct->`"
|
||||
@ -1196,14 +1184,14 @@ example, INSTANCE-ACCESS could be `my_struct->`"
|
||||
(cond
|
||||
((and (not (cpp-member-capnp-load member))
|
||||
(capnp-primitive-type-p (capnp-type-of-member member)))
|
||||
(format s " ~A = reader.get~A();~%" member-access capnp-name))
|
||||
(format s " ~A = ~A.get~A();~%" member-access reader capnp-name))
|
||||
(t
|
||||
;; Enclose larger load code in new scope
|
||||
(with-cpp-block-output (s)
|
||||
(if (and (cpp-member-capnp-init member)
|
||||
(not (find-cpp-enum (cpp-member-type member))))
|
||||
(format s " auto ~A = reader.get~A();~%" member-reader capnp-name)
|
||||
(setf member-reader "reader"))
|
||||
(format s " auto ~A = ~A.get~A();~%" member-reader reader capnp-name)
|
||||
(setf member-reader reader))
|
||||
(if (cpp-member-capnp-load member)
|
||||
(format s " ~A~%"
|
||||
(cpp-code (funcall (cpp-member-capnp-load member)
|
||||
@ -1212,56 +1200,56 @@ example, INSTANCE-ACCESS could be `my_struct->`"
|
||||
(cpp-member-type member)
|
||||
member-reader capnp-name) s))))))))))
|
||||
|
||||
(defun capnp-load-parents (cpp-class load-parent)
|
||||
"Generate Cap'n Proto code for loading parent classes of CPP-CLASS.
|
||||
LOAD-PARENT is a function which generates the code for loading parent members.
|
||||
It takes a parent class symbol."
|
||||
(declare (type cpp-class cpp-class))
|
||||
(declare (type (function (symbol) string) load-parent))
|
||||
(with-output-to-string (s)
|
||||
(multiple-value-bind (direct-union-parents compose-parents)
|
||||
(capnp-union-and-compose-parents cpp-class)
|
||||
(declare (ignore direct-union-parents))
|
||||
;; Handle the union inheritance calls first.
|
||||
(let ((parents (capnp-union-parents-rec cpp-class)))
|
||||
(when parents
|
||||
(let ((first-parent (first parents)))
|
||||
(write-line (funcall load-parent first-parent) s))
|
||||
(when (or compose-parents (cpp-class-members cpp-class))
|
||||
(format s " auto reader = base_reader.~{get~A().~}get~A();~%"
|
||||
(mapcar #'cpp-type-name (cdr (reverse parents)))
|
||||
(cpp-type-name cpp-class)))
|
||||
;; Now handle composite inheritance calls.
|
||||
(dolist (parent compose-parents)
|
||||
(with-cpp-block-output (s)
|
||||
(let ((reader (format nil "~A_reader" (cpp-variable-name parent))))
|
||||
(format s " auto ~A = reader.get~A();~%" reader (cpp-type-name parent))
|
||||
(format s " const auto &reader = ~A;" reader)
|
||||
(write-line (funcall load-parent parent) s)))))))))
|
||||
|
||||
(defun capnp-load-function-code (cpp-class)
|
||||
"Generate Cap'n Proto loadd code for CPP-CLASS."
|
||||
"Generate Cap'n Proto load code for CPP-CLASS."
|
||||
(declare (type cpp-class cpp-class))
|
||||
(let ((instance-access (if (or (direct-subclasses-of cpp-class)
|
||||
(let ((instance-access (if (or (capnp-union-subclasses cpp-class)
|
||||
(capnp-union-parents-rec cpp-class))
|
||||
"self->get()->"
|
||||
"self->")))
|
||||
(labels ((load-class (cpp-class)
|
||||
(with-output-to-string (s)
|
||||
(write-line (capnp-load-parents cpp-class #'load-parent) s)
|
||||
(write-line (capnp-load-members cpp-class :instance-access instance-access) s)))
|
||||
(load-parent (parent)
|
||||
(with-output-to-string (s)
|
||||
(with-cpp-block-output (s)
|
||||
(format s "// Load base class ~A~%" (cpp-type-name parent))
|
||||
(write-line (load-class (find-cpp-class parent)) s)))))
|
||||
(labels ((load-class (cpp-class reader cpp-out)
|
||||
(let* ((compose-parents (nth-value 1 (capnp-union-and-compose-parents cpp-class)))
|
||||
(parents (capnp-union-parents-rec cpp-class))
|
||||
(first-parent (find-cpp-class (first parents))))
|
||||
(when first-parent
|
||||
(with-cpp-block-output (cpp-out)
|
||||
(format cpp-out "// Load parent class ~A~%" (cpp-type-name first-parent))
|
||||
(load-class first-parent reader cpp-out)))
|
||||
;; Initialize CPP-CLASS reader
|
||||
(when (and parents (or compose-parents (cpp-class-members cpp-class)))
|
||||
(progn
|
||||
(format cpp-out "auto reader = ~A.~{get~A().~}get~A();"
|
||||
reader
|
||||
(mapcar #'cpp-type-name (cdr (reverse parents)))
|
||||
(cpp-type-name cpp-class))
|
||||
(setf reader "reader")))
|
||||
;; Load composed parent classes
|
||||
(dolist (parent compose-parents)
|
||||
(with-cpp-block-output (cpp-out)
|
||||
(let ((parent-reader (format nil "~A_reader" (cpp-variable-name parent))))
|
||||
(format cpp-out "// Load composed class ~A~%" (cpp-type-name parent))
|
||||
(format cpp-out "auto ~A = ~A.get~A();~%"
|
||||
parent-reader reader (cpp-type-name parent))
|
||||
(format cpp-out "Load(self->get(), ~A~{, ~A~});~%"
|
||||
parent-reader
|
||||
(mapcar (lambda (name-and-type)
|
||||
(cpp-variable-name (first name-and-type)))
|
||||
(capnp-extra-args (find-cpp-class parent) :load))))))
|
||||
;; Load members
|
||||
(write-string (capnp-load-members cpp-class reader :instance-access instance-access) cpp-out))))
|
||||
(with-output-to-string (s)
|
||||
(cond
|
||||
((and (capnp-union-and-compose-parents cpp-class)
|
||||
(not (direct-subclasses-of cpp-class)))
|
||||
;; CPP-CLASS is the most derived class, so construct and load.
|
||||
(format s "*self = std::make_unique<~A>();~%" (cpp-type-decl cpp-class :namespace nil))
|
||||
(write-line (load-class cpp-class) s))
|
||||
(if (and (cpp-class-capnp-opts cpp-class)
|
||||
(capnp-opts-construct (cpp-class-capnp-opts cpp-class)))
|
||||
(write-line (funcall
|
||||
(capnp-opts-construct (cpp-class-capnp-opts cpp-class))
|
||||
(cpp-type-decl cpp-class :namespace nil))
|
||||
s)
|
||||
(format s "*self = std::make_unique<~A>();~%" (cpp-type-decl cpp-class :namespace nil)))
|
||||
(load-class cpp-class "base_reader" s))
|
||||
((capnp-union-subclasses cpp-class)
|
||||
;; Forward the load to most derived class by switching on reader.which()
|
||||
(let ((parents (capnp-union-parents-rec cpp-class)))
|
||||
@ -1297,19 +1285,19 @@ It takes a parent class symbol."
|
||||
;; Regular forward to derived
|
||||
(load-derived (cpp-type-name subclass))))
|
||||
(write-line "break;" s))
|
||||
(when (capnp-union-and-compose-parents cpp-class)
|
||||
(when (not (cpp-class-abstractp cpp-class))
|
||||
;; We are in the middle of the hierarchy, so allow constructing and loading us.
|
||||
(with-cpp-block-output (s :name (format nil "case capnp::~A::~A:"
|
||||
(cpp-type-name cpp-class)
|
||||
(cpp-constant-name (cpp-type-base-name cpp-class))))
|
||||
(format s "*self = std::make_unique<~A>();~%"
|
||||
(cpp-type-decl cpp-class :namespace nil))
|
||||
(write-line (load-class cpp-class) s)))))
|
||||
(load-class cpp-class "base_reader" s)))))
|
||||
(t
|
||||
;; Regular load for absolutely no inheritance class
|
||||
(assert (not (capnp-union-subclasses cpp-class)))
|
||||
(assert (not (capnp-union-and-compose-parents cpp-class)))
|
||||
(write-line (load-class cpp-class) s)))))))
|
||||
(load-class cpp-class "reader" s)))))))
|
||||
|
||||
(defun capnp-load-function-definition (cpp-class)
|
||||
"Generate Cap'n Proto load function."
|
||||
@ -1382,6 +1370,7 @@ element."
|
||||
(declare (type string capnp-type cpp-type)
|
||||
(type (or null string) lambda-code))
|
||||
;; TODO: Why not use our `capnp-save-default' for this?
|
||||
;; TODO: namespace doesn't work for enums nested in classes
|
||||
(let* ((namespace (format nil "~{~A::~}"
|
||||
(cpp-type-namespace (parse-cpp-type-declaration cpp-type))))
|
||||
(lambda-code (if lambda-code
|
||||
@ -1554,6 +1543,8 @@ Currently supported class-options are:
|
||||
* :serialize -- only :capnp is a valid value. Setting :capnp will generate
|
||||
the Cap'n Proto serialization code for the class members. You may
|
||||
specifiy additional options after :capnp to fill the `CAPNP-OPTS' slots.
|
||||
* :abstractp -- if t, marks that this class cannot be instantiated
|
||||
(currently only useful in serialization code)
|
||||
|
||||
Larger example:
|
||||
|
||||
@ -1590,7 +1581,8 @@ Generates C++:
|
||||
(class-name (if (consp name) (car name) name))
|
||||
(type-params (when (consp name) (cdr name)))
|
||||
(class (gensym (format nil "CLASS-~A" name)))
|
||||
(serialize (cdr (assoc :serialize options))))
|
||||
(serialize (cdr (assoc :serialize options)))
|
||||
(abstractp (second (assoc :abstractp options))))
|
||||
`(let ((,class
|
||||
(let ((*cpp-inner-types* nil)
|
||||
(*cpp-enclosing-class* ',class-name))
|
||||
@ -1606,6 +1598,7 @@ Generates C++:
|
||||
:capnp-opts ,(when (member :capnp serialize)
|
||||
`(and *capnp-serialize-p*
|
||||
(make-capnp-opts ,@(cdr (member :capnp serialize)))))
|
||||
:abstractp ,abstractp
|
||||
:namespace (reverse *cpp-namespaces*)
|
||||
;; Set inner types at the end. This works
|
||||
;; because CL standard specifies order of
|
||||
|
@ -1,466 +0,0 @@
|
||||
@0xb107d3d6b4b1600b;
|
||||
|
||||
using Cxx = import "/capnp/c++.capnp";
|
||||
$Cxx.namespace("query::capnp");
|
||||
|
||||
using Storage = import "/storage/serialization.capnp";
|
||||
using Symbols = import "/query/frontend/semantic/symbol.capnp";
|
||||
|
||||
struct Tree {
|
||||
uid @0 :Int64;
|
||||
|
||||
union {
|
||||
expression @1 :Expression;
|
||||
where @2 :Where;
|
||||
namedExpression @3 :NamedExpression;
|
||||
patternAtom @4 :PatternAtom;
|
||||
pattern @5 :Pattern;
|
||||
clause @6 :Clause;
|
||||
singleQuery @7 :SingleQuery;
|
||||
cypherUnion @8 :CypherUnion;
|
||||
query @9 :Query;
|
||||
}
|
||||
}
|
||||
|
||||
struct Expression {
|
||||
union {
|
||||
binaryOperator @0 :BinaryOperator;
|
||||
unaryOperator @1 :UnaryOperator;
|
||||
baseLiteral @2 :BaseLiteral;
|
||||
listSlicingOperator @3 :ListSlicingOperator;
|
||||
ifOperator @4 :IfOperator;
|
||||
identifier @5 :Identifier;
|
||||
propertyLookup @6 :PropertyLookup;
|
||||
labelsTest @7 :LabelsTest;
|
||||
function @8 :Function;
|
||||
reduce @9 :Reduce;
|
||||
all @10 :All;
|
||||
single @11 :Single;
|
||||
parameterLookup @12 :ParameterLookup;
|
||||
extract @13 :Extract;
|
||||
}
|
||||
}
|
||||
|
||||
struct Where {
|
||||
expression @0 :Tree;
|
||||
}
|
||||
|
||||
struct NamedExpression {
|
||||
name @0 :Text;
|
||||
expression @1 :Tree;
|
||||
tokenPosition @2 :Int32;
|
||||
}
|
||||
|
||||
struct PatternAtom {
|
||||
union {
|
||||
nodeAtom @0 :NodeAtom;
|
||||
edgeAtom @1 :EdgeAtom;
|
||||
}
|
||||
identifier @2 :Tree;
|
||||
}
|
||||
|
||||
struct Pair(First, Second) {
|
||||
first @0 :First;
|
||||
second @1 :Second;
|
||||
}
|
||||
|
||||
struct NodeAtom {
|
||||
properties @0 :List(Entry);
|
||||
struct Entry {
|
||||
key @0 :Pair(Text, Storage.Common);
|
||||
value @1 :Tree;
|
||||
}
|
||||
|
||||
labels @1 :List(Storage.Common);
|
||||
}
|
||||
|
||||
struct EdgeAtom {
|
||||
enum Type {
|
||||
single @0;
|
||||
depthFirst @1;
|
||||
breadthFirst @2;
|
||||
weightedShortestPath @3;
|
||||
}
|
||||
type @0 :Type;
|
||||
|
||||
enum Direction {
|
||||
in @0;
|
||||
out @1;
|
||||
both @2;
|
||||
}
|
||||
direction @1 :Direction;
|
||||
|
||||
properties @2 :List(Entry);
|
||||
struct Entry {
|
||||
key @0 :Pair(Text, Storage.Common);
|
||||
value @1 :Tree;
|
||||
}
|
||||
|
||||
lowerBound @3 :Tree;
|
||||
upperBound @4 :Tree;
|
||||
|
||||
filterLambda @5 :Lambda;
|
||||
weightLambda @6 :Lambda;
|
||||
struct Lambda {
|
||||
innerEdge @0 :Tree;
|
||||
innerNode @1 :Tree;
|
||||
expression @2 :Tree;
|
||||
}
|
||||
|
||||
totalWeight @7 :Tree;
|
||||
edgeTypes @8 :List(Storage.Common);
|
||||
}
|
||||
|
||||
struct Pattern {
|
||||
identifier @0 :Tree;
|
||||
atoms @1 :List(Tree);
|
||||
}
|
||||
|
||||
struct Clause {
|
||||
union {
|
||||
create @0 :Create;
|
||||
match @1 :Match;
|
||||
return @2 :Return;
|
||||
with @3 :With;
|
||||
delete @4 :Delete;
|
||||
setProperty @5 :SetProperty;
|
||||
setProperties @6 :SetProperties;
|
||||
setLabels @7 :SetLabels;
|
||||
removeProperty @8 :RemoveProperty;
|
||||
removeLabels @9 :RemoveLabels;
|
||||
merge @10 :Merge;
|
||||
unwind @11 :Unwind;
|
||||
createIndex @12 :CreateIndex;
|
||||
authQuery @13 :AuthQuery;
|
||||
createStream @14 :CreateStream;
|
||||
dropStream @15 :DropStream;
|
||||
showStreams @16 :ShowStreams;
|
||||
startStopStream @17 :StartStopStream;
|
||||
startStopAllStreams @18 :StartStopAllStreams;
|
||||
testStream @19 :TestStream;
|
||||
}
|
||||
}
|
||||
|
||||
struct SingleQuery {
|
||||
clauses @0 :List(Tree);
|
||||
}
|
||||
|
||||
struct CypherUnion {
|
||||
singleQuery @0 :Tree;
|
||||
distinct @1 :Bool;
|
||||
unionSymbols @2 :List(Symbols.Symbol);
|
||||
}
|
||||
|
||||
struct Query {
|
||||
singleQuery @0 :Tree;
|
||||
cypherUnions @1 :List(Tree);
|
||||
explain @2 :Bool;
|
||||
}
|
||||
|
||||
struct BinaryOperator {
|
||||
union {
|
||||
orOperator @0 :OrOperator;
|
||||
xorOperator @1 :XorOperator;
|
||||
andOperator @2 :AndOperator;
|
||||
additionOperator @3 :AdditionOperator;
|
||||
subtractionOperator @4 :SubtractionOperator;
|
||||
multiplicationOperator @5 :MultiplicationOperator;
|
||||
divisionOperator @6 :DivisionOperator;
|
||||
modOperator @7 :ModOperator;
|
||||
notEqualOperator @8 :NotEqualOperator;
|
||||
equalOperator @9 :EqualOperator;
|
||||
lessOperator @10 :LessOperator;
|
||||
greaterOperator @11 :GreaterOperator;
|
||||
lessEqualOperator @12 :LessEqualOperator;
|
||||
greaterEqualOperator @13 :GreaterEqualOperator;
|
||||
inListOperator @14 :InListOperator;
|
||||
subscriptOperator @15 :SubscriptOperator;
|
||||
aggregation @16 :Aggregation;
|
||||
}
|
||||
expression1 @17 :Tree;
|
||||
expression2 @18 :Tree;
|
||||
}
|
||||
|
||||
struct OrOperator {}
|
||||
struct XorOperator {}
|
||||
struct AndOperator {}
|
||||
struct AdditionOperator {}
|
||||
struct SubtractionOperator {}
|
||||
struct MultiplicationOperator {}
|
||||
struct DivisionOperator {}
|
||||
struct ModOperator {}
|
||||
struct NotEqualOperator {}
|
||||
struct EqualOperator {}
|
||||
struct LessOperator {}
|
||||
struct GreaterOperator {}
|
||||
struct LessEqualOperator {}
|
||||
struct GreaterEqualOperator {}
|
||||
struct InListOperator {}
|
||||
struct SubscriptOperator {}
|
||||
struct Aggregation {
|
||||
enum Op {
|
||||
count @0;
|
||||
min @1;
|
||||
max @2;
|
||||
sum @3;
|
||||
avg @4 ;
|
||||
collectList @5;
|
||||
collectMap @6;
|
||||
}
|
||||
op @0 :Op;
|
||||
}
|
||||
|
||||
struct UnaryOperator {
|
||||
union {
|
||||
notOperator @0 :NotOperator;
|
||||
unaryPlusOperator @1 :UnaryPlusOperator;
|
||||
unaryMinusOperator @2 :UnaryMinusOperator;
|
||||
isNullOperator @3 :IsNullOperator;
|
||||
}
|
||||
expression @4 :Tree;
|
||||
}
|
||||
|
||||
struct NotOperator {}
|
||||
struct UnaryPlusOperator {}
|
||||
struct UnaryMinusOperator {}
|
||||
struct IsNullOperator {}
|
||||
|
||||
struct BaseLiteral {
|
||||
union {
|
||||
primitiveLiteral @0 :PrimitiveLiteral;
|
||||
listLiteral @1 :ListLiteral;
|
||||
mapLiteral @2 :MapLiteral;
|
||||
}
|
||||
}
|
||||
|
||||
struct PrimitiveLiteral {
|
||||
tokenPosition @0 :Int32;
|
||||
value @1 :Storage.PropertyValue;
|
||||
}
|
||||
|
||||
struct ListLiteral {
|
||||
elements @0 :List(Tree);
|
||||
}
|
||||
|
||||
struct MapLiteral {
|
||||
elements @0 :List(Entry);
|
||||
struct Entry {
|
||||
key @0 :Pair(Text, Storage.Common);
|
||||
value @1 :Tree;
|
||||
}
|
||||
}
|
||||
|
||||
struct ListSlicingOperator {
|
||||
list @0 :Tree;
|
||||
lowerBound @1 :Tree;
|
||||
upperBound @2 :Tree;
|
||||
}
|
||||
|
||||
struct IfOperator {
|
||||
condition @0 :Tree;
|
||||
thenExpression @1 :Tree;
|
||||
elseExpression @2 :Tree;
|
||||
}
|
||||
|
||||
struct Identifier {
|
||||
name @0 :Text;
|
||||
userDeclared @1 :Bool;
|
||||
}
|
||||
|
||||
struct PropertyLookup {
|
||||
expression @0 :Tree;
|
||||
propertyName @1 :Text;
|
||||
property @2 :Storage.Common;
|
||||
}
|
||||
|
||||
struct LabelsTest {
|
||||
expression @0 :Tree;
|
||||
labels @1 :List(Storage.Common);
|
||||
}
|
||||
|
||||
struct Function {
|
||||
functionName @0 :Text;
|
||||
arguments @1 :List(Tree);
|
||||
}
|
||||
|
||||
struct Reduce {
|
||||
accumulator @0 :Tree;
|
||||
initializer @1 :Tree;
|
||||
identifier @2 :Tree;
|
||||
list @3 :Tree;
|
||||
expression @4 :Tree;
|
||||
}
|
||||
|
||||
struct Extract {
|
||||
identifier @0 :Tree;
|
||||
list @1 :Tree;
|
||||
expression @2 :Tree;
|
||||
}
|
||||
|
||||
struct All {
|
||||
identifier @0 :Tree;
|
||||
listExpression @1 :Tree;
|
||||
where @2 :Tree;
|
||||
}
|
||||
|
||||
struct Single {
|
||||
identifier @0 :Tree;
|
||||
listExpression @1 :Tree;
|
||||
where @2 :Tree;
|
||||
}
|
||||
|
||||
struct ParameterLookup {
|
||||
tokenPosition @0 :Int32;
|
||||
}
|
||||
|
||||
struct Create {
|
||||
patterns @0 :List(Tree);
|
||||
}
|
||||
|
||||
struct Match {
|
||||
patterns @0 :List(Tree);
|
||||
where @1 :Tree;
|
||||
optional @2 :Bool;
|
||||
}
|
||||
|
||||
enum Ordering {
|
||||
asc @0;
|
||||
desc @1;
|
||||
}
|
||||
|
||||
struct ReturnBody {
|
||||
distinct @0 :Bool;
|
||||
allIdentifiers @1 :Bool;
|
||||
namedExpressions @2 :List(Tree);
|
||||
orderBy @3 :List(Pair);
|
||||
|
||||
struct Pair {
|
||||
ordering @0 :Ordering;
|
||||
expression @1 :Tree;
|
||||
}
|
||||
|
||||
skip @4 :Tree;
|
||||
limit @5 :Tree;
|
||||
}
|
||||
|
||||
struct Return {
|
||||
returnBody @0 :ReturnBody;
|
||||
}
|
||||
|
||||
struct With {
|
||||
returnBody @0 :ReturnBody;
|
||||
where @1 :Tree;
|
||||
}
|
||||
|
||||
struct Delete {
|
||||
detach @0 :Bool;
|
||||
expressions @1 :List(Tree);
|
||||
}
|
||||
|
||||
struct SetProperty {
|
||||
propertyLookup @0 :Tree;
|
||||
expression @1 :Tree;
|
||||
}
|
||||
|
||||
struct SetProperties {
|
||||
identifier @0 :Tree;
|
||||
expression @1 :Tree;
|
||||
update @2 :Bool;
|
||||
}
|
||||
|
||||
struct SetLabels {
|
||||
identifier @0 :Tree;
|
||||
labels @1 :List(Storage.Common);
|
||||
}
|
||||
|
||||
struct RemoveProperty {
|
||||
propertyLookup @0 :Tree;
|
||||
}
|
||||
|
||||
struct RemoveLabels {
|
||||
identifier @0 :Tree;
|
||||
labels @1 :List(Storage.Common);
|
||||
}
|
||||
|
||||
struct Merge {
|
||||
pattern @0 :Tree;
|
||||
onMatch @1 :List(Tree);
|
||||
onCreate @2 :List(Tree);
|
||||
}
|
||||
|
||||
struct Unwind {
|
||||
namedExpression @0 :Tree;
|
||||
}
|
||||
|
||||
struct CreateIndex {
|
||||
label @0 :Storage.Common;
|
||||
property @1 :Storage.Common;
|
||||
}
|
||||
|
||||
struct AuthQuery {
|
||||
enum Action {
|
||||
createRole @0;
|
||||
dropRole @1;
|
||||
showRoles @2;
|
||||
createUser @3;
|
||||
setPassword @4;
|
||||
dropUser @5;
|
||||
showUsers @6;
|
||||
setRole @7;
|
||||
clearRole @8;
|
||||
grantPrivilege @9;
|
||||
denyPrivilege @10;
|
||||
revokePrivilege @11;
|
||||
showPrivileges @12;
|
||||
showRoleForUser @13;
|
||||
showUsersForRole @14;
|
||||
}
|
||||
enum Privilege {
|
||||
create @0;
|
||||
delete @1;
|
||||
match @2;
|
||||
merge @3;
|
||||
set @4;
|
||||
remove @5;
|
||||
index @6;
|
||||
auth @7;
|
||||
stream @8;
|
||||
}
|
||||
action @0 :Action;
|
||||
user @1 :Text;
|
||||
role @2 :Text;
|
||||
userOrRole @3 :Text;
|
||||
password @4 :Tree;
|
||||
privileges @5 :List(Privilege);
|
||||
}
|
||||
|
||||
struct CreateStream {
|
||||
streamName @0 :Text;
|
||||
streamUri @1 :Tree;
|
||||
streamTopic @2 :Tree;
|
||||
transformUri @3 :Tree;
|
||||
batchIntervalInMs @4 :Tree;
|
||||
batchSize @5 :Tree;
|
||||
}
|
||||
|
||||
struct DropStream {
|
||||
streamName @0: Text;
|
||||
}
|
||||
|
||||
struct ShowStreams {}
|
||||
|
||||
struct StartStopStream {
|
||||
streamName @0 :Text;
|
||||
isStart @1 :Bool;
|
||||
limitBatches @2: Tree;
|
||||
}
|
||||
|
||||
struct StartStopAllStreams {
|
||||
isStart @0 :Bool;
|
||||
}
|
||||
|
||||
struct TestStream {
|
||||
streamName @0 :Text;
|
||||
limitBatches @1: Tree;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2507
src/query/frontend/ast/ast.lcp
Normal file
2507
src/query/frontend/ast/ast.lcp
Normal file
File diff suppressed because it is too large
Load Diff
@ -638,9 +638,7 @@ antlrcpp::Any CypherMainVisitor::visitReturnBody(
|
||||
MemgraphCypher::ReturnBodyContext *ctx) {
|
||||
ReturnBody body;
|
||||
if (ctx->order()) {
|
||||
body.order_by = ctx->order()
|
||||
->accept(this)
|
||||
.as<std::vector<std::pair<Ordering, Expression *>>>();
|
||||
body.order_by = ctx->order()->accept(this).as<std::vector<SortItem>>();
|
||||
}
|
||||
if (ctx->skip()) {
|
||||
body.skip = static_cast<Expression *>(ctx->skip()->accept(this));
|
||||
@ -684,7 +682,7 @@ antlrcpp::Any CypherMainVisitor::visitReturnItem(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitOrder(MemgraphCypher::OrderContext *ctx) {
|
||||
std::vector<std::pair<Ordering, Expression *>> order_by;
|
||||
std::vector<SortItem> order_by;
|
||||
for (auto *sort_item : ctx->sortItem()) {
|
||||
order_by.push_back(sort_item->accept(this));
|
||||
}
|
||||
@ -693,9 +691,9 @@ antlrcpp::Any CypherMainVisitor::visitOrder(MemgraphCypher::OrderContext *ctx) {
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitSortItem(
|
||||
MemgraphCypher::SortItemContext *ctx) {
|
||||
return std::pair<Ordering, Expression *>(
|
||||
return SortItem{
|
||||
ctx->DESC() || ctx->DESCENDING() ? Ordering::DESC : Ordering::ASC,
|
||||
ctx->expression()->accept(this));
|
||||
ctx->expression()->accept(this)};
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitNodePattern(
|
||||
|
@ -358,12 +358,12 @@ class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor {
|
||||
MemgraphCypher::ReturnItemContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return vector<pair<Ordering, Expression*>>
|
||||
* @return vector<SortItem>
|
||||
*/
|
||||
antlrcpp::Any visitOrder(MemgraphCypher::OrderContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return pair<Ordering, Expression*>
|
||||
* @return SortItem
|
||||
*/
|
||||
antlrcpp::Any visitSortItem(MemgraphCypher::SortItemContext *ctx) override;
|
||||
|
||||
|
@ -84,7 +84,7 @@ void SymbolGenerator::VisitReturnBody(ReturnBody &body, Where *where) {
|
||||
}
|
||||
scope_.in_order_by = true;
|
||||
for (const auto &order_pair : body.order_by) {
|
||||
order_pair.second->Accept(*this);
|
||||
order_pair.expression->Accept(*this);
|
||||
}
|
||||
scope_.in_order_by = false;
|
||||
if (body.skip) {
|
||||
@ -318,7 +318,7 @@ bool SymbolGenerator::PreVisit(Aggregation &aggr) {
|
||||
// Create a virtual symbol for aggregation result.
|
||||
// Currently, we only have aggregation operators which return numbers.
|
||||
auto aggr_name =
|
||||
Aggregation::OpToString(aggr.op_) + std::to_string(aggr.uid());
|
||||
Aggregation::OpToString(aggr.op_) + std::to_string(aggr.uid_);
|
||||
symbol_table_[aggr] =
|
||||
symbol_table_.CreateSymbol(aggr_name, false, Symbol::Type::Number);
|
||||
scope_.in_aggregation = true;
|
||||
|
@ -19,10 +19,10 @@ class SymbolTable final {
|
||||
return Symbol(name, position, user_declared, type, token_position);
|
||||
}
|
||||
|
||||
auto &operator[](const Tree &tree) { return table_[tree.uid()]; }
|
||||
auto &operator[](const Tree &tree) { return table_[tree.uid_]; }
|
||||
|
||||
Symbol &at(const Tree &tree) { return table_.at(tree.uid()); }
|
||||
const Symbol &at(const Tree &tree) const { return table_.at(tree.uid()); }
|
||||
Symbol &at(const Tree &tree) { return table_.at(tree.uid_); }
|
||||
const Symbol &at(const Tree &tree) const { return table_.at(tree.uid_); }
|
||||
|
||||
// TODO: Remove these since members are public
|
||||
int max_position() const { return position_; }
|
||||
|
@ -377,16 +377,16 @@ class ExpressionEvaluator : public TreeVisitor<TypedValue> {
|
||||
for (size_t i = 0; i < function.arguments_.size(); ++i) {
|
||||
arguments[i] = function.arguments_[i]->Accept(*this);
|
||||
}
|
||||
return function.function()(arguments, function.arguments_.size(), *ctx_,
|
||||
dba_);
|
||||
return function.function_(arguments, function.arguments_.size(), *ctx_,
|
||||
dba_);
|
||||
} else {
|
||||
std::vector<TypedValue> arguments;
|
||||
arguments.reserve(function.arguments_.size());
|
||||
for (const auto &argument : function.arguments_) {
|
||||
arguments.emplace_back(argument->Accept(*this));
|
||||
}
|
||||
return function.function()(arguments.data(), arguments.size(), *ctx_,
|
||||
dba_);
|
||||
return function.function_(arguments.data(), arguments.size(), *ctx_,
|
||||
dba_);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1214,11 +1214,11 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor {
|
||||
}
|
||||
// Create a copy of OrderBy but with added symbols used in expressions, so
|
||||
// that they can be pulled.
|
||||
std::vector<std::pair<Ordering, Expression *>> ordering;
|
||||
std::vector<SortItem> ordering;
|
||||
ordering.reserve(order_by.order_by_.size());
|
||||
for (int i = 0; i < order_by.order_by_.size(); ++i) {
|
||||
ordering.emplace_back(order_by.compare_.ordering()[i],
|
||||
order_by.order_by_[i]);
|
||||
ordering.emplace_back(
|
||||
SortItem{order_by.compare_.ordering()[i], order_by.order_by_[i]});
|
||||
}
|
||||
auto worker_plan = std::make_shared<OrderBy>(
|
||||
order_by.input(), ordering,
|
||||
@ -1328,7 +1328,7 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor {
|
||||
auto make_merge_aggregation = [&](auto op, const auto &worker_sym) {
|
||||
auto *worker_ident = make_ident(worker_sym);
|
||||
auto merge_name = Aggregation::OpToString(op) +
|
||||
std::to_string(worker_ident->uid()) + "<-" +
|
||||
std::to_string(worker_ident->uid_) + "<-" +
|
||||
worker_sym.name();
|
||||
auto merge_sym = distributed_plan_.symbol_table.CreateSymbol(
|
||||
merge_name, false, Symbol::Type::Number);
|
||||
|
@ -81,8 +81,7 @@ bool Synchronize::Accept(HierarchicalLogicalOperatorVisitor &visitor) {
|
||||
|
||||
PullRemoteOrderBy::PullRemoteOrderBy(
|
||||
const std::shared_ptr<LogicalOperator> &input, int64_t plan_id,
|
||||
const std::vector<std::pair<Ordering, Expression *>> &order_by,
|
||||
const std::vector<Symbol> &symbols)
|
||||
const std::vector<SortItem> &order_by, const std::vector<Symbol> &symbols)
|
||||
: input_(input), plan_id_(plan_id), symbols_(symbols) {
|
||||
CHECK(input_ != nullptr)
|
||||
<< "PullRemoteOrderBy should always be constructed with input!";
|
||||
@ -90,8 +89,8 @@ PullRemoteOrderBy::PullRemoteOrderBy(
|
||||
ordering.reserve(order_by.size());
|
||||
order_by_.reserve(order_by.size());
|
||||
for (const auto &ordering_expression_pair : order_by) {
|
||||
ordering.emplace_back(ordering_expression_pair.first);
|
||||
order_by_.emplace_back(ordering_expression_pair.second);
|
||||
ordering.emplace_back(ordering_expression_pair.ordering);
|
||||
order_by_.emplace_back(ordering_expression_pair.expression);
|
||||
}
|
||||
compare_ = TypedValueVectorCompare(ordering);
|
||||
}
|
||||
|
@ -172,8 +172,7 @@ by having only one result from each worker.")
|
||||
PullRemoteOrderBy() {}
|
||||
PullRemoteOrderBy(
|
||||
const std::shared_ptr<LogicalOperator> &input, int64_t plan_id,
|
||||
const std::vector<std::pair<Ordering, Expression *>> &order_by,
|
||||
const std::vector<Symbol> &symbols);
|
||||
const std::vector<SortItem> &order_by, const std::vector<Symbol> &symbols);
|
||||
bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override;
|
||||
std::unique_ptr<Cursor> MakeCursor(
|
||||
database::GraphDbAccessor &db) const override;
|
||||
|
@ -2658,7 +2658,7 @@ void Limit::LimitCursor::Reset() {
|
||||
}
|
||||
|
||||
OrderBy::OrderBy(const std::shared_ptr<LogicalOperator> &input,
|
||||
const std::vector<std::pair<Ordering, Expression *>> &order_by,
|
||||
const std::vector<SortItem> &order_by,
|
||||
const std::vector<Symbol> &output_symbols)
|
||||
: input_(input), output_symbols_(output_symbols) {
|
||||
// split the order_by vector into two vectors of orderings and expressions
|
||||
@ -2666,8 +2666,8 @@ OrderBy::OrderBy(const std::shared_ptr<LogicalOperator> &input,
|
||||
ordering.reserve(order_by.size());
|
||||
order_by_.reserve(order_by.size());
|
||||
for (const auto &ordering_expression_pair : order_by) {
|
||||
ordering.emplace_back(ordering_expression_pair.first);
|
||||
order_by_.emplace_back(ordering_expression_pair.second);
|
||||
ordering.emplace_back(ordering_expression_pair.ordering);
|
||||
order_by_.emplace_back(ordering_expression_pair.expression);
|
||||
}
|
||||
compare_ = TypedValueVectorCompare(ordering);
|
||||
}
|
||||
|
@ -151,6 +151,7 @@ cpp<#
|
||||
|
||||
(lcp:define-class logical-operator ("::utils::Visitable<HierarchicalLogicalOperatorVisitor>")
|
||||
()
|
||||
(:abstractp t)
|
||||
(:documentation
|
||||
"Base class for logical operators.
|
||||
|
||||
@ -238,23 +239,27 @@ can serve as inputs to others and thus a sequence of operations is formed.")
|
||||
#>cpp
|
||||
if (${member}) {
|
||||
auto ${capnp-name}_builder = ${builder}->init${capnp-name}();
|
||||
${member}->Save(&${capnp-name}_builder, &helper->saved_ast_uids);
|
||||
Save(*${member}, &${capnp-name}_builder, &helper->saved_ast_uids);
|
||||
}
|
||||
cpp<#)
|
||||
|
||||
(defun load-ast-pointer (ast-type)
|
||||
(lambda (reader member capnp-name)
|
||||
#>cpp
|
||||
if (${reader}.has${capnp-name}())
|
||||
${member} = static_cast<${ast-type}>(helper->ast_storage.Load(${reader}.get${capnp-name}(), &helper->loaded_ast_uids));
|
||||
else
|
||||
${member} = nullptr;
|
||||
cpp<#))
|
||||
(let ((cpp-type (remove #\* ast-type)))
|
||||
#>cpp
|
||||
if (${reader}.has${capnp-name}()) {
|
||||
std::unique_ptr<${cpp-type}> tmp;
|
||||
Load(&tmp, ${reader}.get${capnp-name}(), &helper->ast_storage, &helper->loaded_ast_uids);
|
||||
${member} = helper->ast_storage.Take(std::move(tmp));
|
||||
} else {
|
||||
${member} = nullptr;
|
||||
}
|
||||
cpp<#)))
|
||||
|
||||
(defun save-ast-vector (ast-type)
|
||||
(lcp:capnp-save-vector "::query::capnp::Tree" ast-type
|
||||
"[helper](auto *builder, const auto &val) {
|
||||
val->Save(builder, &helper->saved_ast_uids);
|
||||
Save(*val, builder, &helper->saved_ast_uids);
|
||||
}"))
|
||||
|
||||
(defun load-ast-vector (ast-type)
|
||||
@ -262,9 +267,11 @@ can serve as inputs to others and thus a sequence of operations is formed.")
|
||||
(format
|
||||
nil
|
||||
"[helper](const auto &reader) {
|
||||
// We expect the unsafe downcast via static_cast to work.
|
||||
return static_cast<~A>(helper->ast_storage.Load(reader, &helper->loaded_ast_uids));
|
||||
}" ast-type)))
|
||||
std::unique_ptr<~A> tmp;
|
||||
Load(&tmp, reader, &helper->ast_storage, &helper->loaded_ast_uids);
|
||||
return helper->ast_storage.Take(std::move(tmp));
|
||||
}"
|
||||
(remove #\* ast-type))))
|
||||
|
||||
(defun save-operator-pointer (builder member-name capnp-name)
|
||||
(declare (ignore capnp-name))
|
||||
@ -547,7 +554,7 @@ given label.
|
||||
::utils::capnp::Bound<::query::capnp::Tree>::Type::INCLUSIVE :
|
||||
::utils::capnp::Bound<::query::capnp::Tree>::Type::EXCLUSIVE);
|
||||
auto value_builder = builder->initValue();
|
||||
bound.value()->Save(&value_builder, &helper->saved_ast_uids);
|
||||
Save(*bound.value(), &value_builder, &helper->saved_ast_uids);
|
||||
}"))
|
||||
(funcall (lcp:capnp-save-optional "::utils::capnp::Bound<::query::capnp::Tree>"
|
||||
"utils::Bound<Expression *>"
|
||||
@ -559,7 +566,9 @@ given label.
|
||||
"[helper](const auto &reader) {
|
||||
auto type = reader.getType() == ::utils::capnp::Bound<::query::capnp::Tree>::Type::INCLUSIVE
|
||||
? utils::BoundType::INCLUSIVE : utils::BoundType::EXCLUSIVE;
|
||||
auto *value = static_cast<Expression*>(helper->ast_storage.Load(reader.getValue(), &helper->loaded_ast_uids));
|
||||
std::unique_ptr<Tree> tmp;
|
||||
Load(&tmp, reader.getValue(), &helper->ast_storage, &helper->loaded_ast_uids);
|
||||
auto *value = static_cast<Expression *>(helper->ast_storage.Take(std::move(tmp)));
|
||||
return utils::Bound<Expression *>(value, type);
|
||||
}"))
|
||||
(funcall (lcp:capnp-load-optional "::utils::capnp::Bound<::query::capnp::Tree>"
|
||||
@ -818,16 +827,16 @@ pulled.")
|
||||
:capnp-save (lambda (builder member capnp-name)
|
||||
#>cpp
|
||||
if (${member}) {
|
||||
auto expression_builder = ${builder}->initExpression();
|
||||
${member}->Save(&expression_builder, saved_ast_uids);
|
||||
auto ${capnp-name}_builder = ${builder}->init${capnp-name}();
|
||||
Save(*${member}, &${capnp-name}_builder, saved_ast_uids);
|
||||
}
|
||||
cpp<#)
|
||||
:capnp-load (lambda (reader member capnp-name)
|
||||
#>cpp
|
||||
if (${reader}.hasExpression()) {
|
||||
${member} = static_cast<Expression *>(
|
||||
ast_storage->Load(${reader}.getExpression(),
|
||||
loaded_ast_uids));
|
||||
std::unique_ptr<Expression> tmp;
|
||||
Load(&tmp, ${reader}.getExpression(), ast_storage, loaded_ast_uids);
|
||||
${member} = ast_storage->Take(std::move(tmp));
|
||||
} else {
|
||||
${member} = nullptr;
|
||||
}
|
||||
@ -854,7 +863,7 @@ pulled.")
|
||||
:capnp-type "Ast.Tree" :capnp-init nil
|
||||
:capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "Expression *")
|
||||
:documentation "Optional upper bound of the variable length expansion, defaults are (1, inf)")
|
||||
(filter-lambda "ExpansionLambda"
|
||||
(filter-lambda "ExpansionLambda"
|
||||
:scope :public
|
||||
:capnp-save (lambda (builder member capnp-name)
|
||||
#>cpp
|
||||
@ -867,12 +876,12 @@ pulled.")
|
||||
(weight-lambda "std::experimental::optional<ExpansionLambda>" :scope :public
|
||||
:capnp-save (lcp:capnp-save-optional
|
||||
"capnp::ExpansionLambda" "ExpansionLambda"
|
||||
"[helper](auto *builder, const auto &val) {
|
||||
Save(val, builder, &helper->saved_ast_uids);
|
||||
"[helper](auto *builder, const auto &val) {
|
||||
Save(val, builder, &helper->saved_ast_uids);
|
||||
}")
|
||||
:capnp-load (lcp:capnp-load-optional
|
||||
"capnp::ExpansionLambda" "ExpansionLambda"
|
||||
"[helper](const auto &reader) {
|
||||
"[helper](const auto &reader) {
|
||||
ExpansionLambda val;
|
||||
Load(&val, reader, &helper->ast_storage, &helper->loaded_ast_uids);
|
||||
return val;
|
||||
@ -1832,7 +1841,7 @@ are valid for usage after the OrderBy operator.")
|
||||
OrderBy() {}
|
||||
|
||||
OrderBy(const std::shared_ptr<LogicalOperator> &input,
|
||||
const std::vector<std::pair<Ordering, Expression *>> &order_by,
|
||||
const std::vector<SortItem> &order_by,
|
||||
const std::vector<Symbol> &output_symbols);
|
||||
bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override;
|
||||
std::unique_ptr<Cursor> MakeCursor(
|
||||
|
@ -132,7 +132,7 @@ class ReturnBodyContext : public HierarchicalTreeVisitor {
|
||||
// about collecting used_symbols. Also, semantic analysis should
|
||||
// have prevented any aggregations from appearing here.
|
||||
for (const auto &order_pair : body.order_by) {
|
||||
order_pair.second->Accept(*this);
|
||||
order_pair.expression->Accept(*this);
|
||||
}
|
||||
if (where) {
|
||||
where->Accept(*this);
|
||||
|
@ -39,7 +39,7 @@ struct PropertyValue {
|
||||
|
||||
struct PropertyValueStore {
|
||||
properties @0 :List(Entry);
|
||||
|
||||
|
||||
struct Entry {
|
||||
id @0 :Common;
|
||||
value @1 :PropertyValue;
|
||||
|
@ -158,7 +158,7 @@ class CapnpAstGenerator : public Base {
|
||||
query::capnp::Tree::Builder builder =
|
||||
message.initRoot<query::capnp::Tree>();
|
||||
std::vector<int> saved_uids;
|
||||
visitor.query()->Save(&builder, &saved_uids);
|
||||
Save(*visitor.query(), &builder, &saved_uids);
|
||||
}
|
||||
|
||||
AstStorage new_ast;
|
||||
@ -332,8 +332,8 @@ TYPED_TEST(CypherMainVisitorTest, ReturnOrderBy) {
|
||||
ASSERT_EQ(return_clause->body_.order_by.size(), 3U);
|
||||
std::vector<std::pair<Ordering, std::string>> ordering;
|
||||
for (const auto &sort_item : return_clause->body_.order_by) {
|
||||
auto *identifier = dynamic_cast<Identifier *>(sort_item.second);
|
||||
ordering.emplace_back(sort_item.first, identifier->name_);
|
||||
auto *identifier = dynamic_cast<Identifier *>(sort_item.expression);
|
||||
ordering.emplace_back(sort_item.ordering, identifier->name_);
|
||||
}
|
||||
ASSERT_THAT(ordering, UnorderedElementsAre(Pair(Ordering::ASC, "z"),
|
||||
Pair(Ordering::ASC, "x"),
|
||||
@ -762,7 +762,7 @@ TYPED_TEST(CypherMainVisitorTest, Function) {
|
||||
auto *function = dynamic_cast<Function *>(
|
||||
return_clause->body_.named_expressions[0]->expression_);
|
||||
ASSERT_TRUE(function);
|
||||
ASSERT_TRUE(function->function());
|
||||
ASSERT_TRUE(function->function_);
|
||||
}
|
||||
|
||||
TYPED_TEST(CypherMainVisitorTest, StringLiteralDoubleQuotes) {
|
||||
|
@ -329,16 +329,14 @@ TEST_F(DistributedQueryPlan, PullRemoteOrderBy) {
|
||||
auto n_p = PROPERTY_LOOKUP("n", prop);
|
||||
ctx.symbol_table_[*n_p->expression_] = n.sym_;
|
||||
auto order_by = std::make_shared<plan::OrderBy>(
|
||||
n.op_,
|
||||
std::vector<std::pair<Ordering, Expression *>>{{Ordering::ASC, n_p}},
|
||||
n.op_, std::vector<SortItem>{{Ordering::ASC, n_p}},
|
||||
std::vector<Symbol>{n.sym_});
|
||||
|
||||
const int plan_id = 42;
|
||||
master().plan_dispatcher().DispatchPlan(plan_id, order_by, ctx.symbol_table_);
|
||||
|
||||
auto pull_remote_order_by = std::make_shared<plan::PullRemoteOrderBy>(
|
||||
order_by, plan_id,
|
||||
std::vector<std::pair<Ordering, Expression *>>{{Ordering::ASC, n_p}},
|
||||
order_by, plan_id, std::vector<SortItem>{{Ordering::ASC, n_p}},
|
||||
std::vector<Symbol>{n.sym_});
|
||||
|
||||
auto n_p_ne = NEXPR("n.prop", n_p);
|
||||
|
@ -57,7 +57,7 @@ auto ToMap(const TypedValue &t) {
|
||||
// Custom types for ORDER BY, SKIP, LIMIT, ON MATCH and ON CREATE expressions,
|
||||
// so that they can be used to resolve function calls.
|
||||
struct OrderBy {
|
||||
std::vector<std::pair<Ordering, Expression *>> expressions;
|
||||
std::vector<SortItem> expressions;
|
||||
};
|
||||
struct Skip {
|
||||
Expression *expression = nullptr;
|
||||
@ -75,7 +75,7 @@ struct OnCreate {
|
||||
// Helper functions for filling the OrderBy with expressions.
|
||||
auto FillOrderBy(OrderBy &order_by, Expression *expression,
|
||||
Ordering ordering = Ordering::ASC) {
|
||||
order_by.expressions.emplace_back(ordering, expression);
|
||||
order_by.expressions.push_back({ordering, expression});
|
||||
}
|
||||
template <class... T>
|
||||
auto FillOrderBy(OrderBy &order_by, Expression *expression, Ordering ordering,
|
||||
|
@ -151,9 +151,7 @@ TEST(QueryPlan, OrderBy) {
|
||||
auto n_p = PROPERTY_LOOKUP("n", prop);
|
||||
symbol_table[*n_p->expression_] = n.sym_;
|
||||
auto order_by = std::make_shared<plan::OrderBy>(
|
||||
n.op_,
|
||||
std::vector<std::pair<Ordering, Expression *>>{
|
||||
{order_value_pair.first, n_p}},
|
||||
n.op_, std::vector<SortItem>{{order_value_pair.first, n_p}},
|
||||
std::vector<Symbol>{n.sym_});
|
||||
auto n_p_ne = NEXPR("n.p", n_p);
|
||||
symbol_table[*n_p_ne] = symbol_table.CreateSymbol("n.p", true);
|
||||
@ -201,13 +199,12 @@ TEST(QueryPlan, OrderByMultiple) {
|
||||
// (p1: 0, p2: N-2)
|
||||
// ...
|
||||
// (p1: N-1, p2:0)
|
||||
auto order_by = std::make_shared<plan::OrderBy>(
|
||||
n.op_,
|
||||
std::vector<std::pair<Ordering, Expression *>>{
|
||||
{Ordering::ASC, n_p1},
|
||||
{Ordering::DESC, n_p2},
|
||||
},
|
||||
std::vector<Symbol>{n.sym_});
|
||||
auto order_by = std::make_shared<plan::OrderBy>(n.op_,
|
||||
std::vector<SortItem>{
|
||||
{Ordering::ASC, n_p1},
|
||||
{Ordering::DESC, n_p2},
|
||||
},
|
||||
std::vector<Symbol>{n.sym_});
|
||||
auto n_p1_ne = NEXPR("n.p1", n_p1);
|
||||
symbol_table[*n_p1_ne] = symbol_table.CreateSymbol("n.p1", true);
|
||||
auto n_p2_ne = NEXPR("n.p2", n_p2);
|
||||
@ -262,8 +259,7 @@ TEST(QueryPlan, OrderByExceptions) {
|
||||
auto n_p = PROPERTY_LOOKUP("n", prop);
|
||||
symbol_table[*n_p->expression_] = n.sym_;
|
||||
auto order_by = std::make_shared<plan::OrderBy>(
|
||||
n.op_,
|
||||
std::vector<std::pair<Ordering, Expression *>>{{Ordering::ASC, n_p}},
|
||||
n.op_, std::vector<SortItem>{{Ordering::ASC, n_p}},
|
||||
std::vector<Symbol>{});
|
||||
EXPECT_THROW(PullAll(order_by, dba, symbol_table), QueryRuntimeException);
|
||||
}
|
||||
|
@ -3201,7 +3201,7 @@ TEST(CapnpSerial, PullRemoteOrderBy) {
|
||||
AstStorage storage;
|
||||
std::vector<Symbol> symbols{
|
||||
Symbol("my_symbol", 2, true, Symbol::Type::Vertex, 3)};
|
||||
std::vector<std::pair<query::Ordering, query::Expression *>> order_by{
|
||||
std::vector<query::SortItem> order_by{
|
||||
{query::Ordering::ASC, IDENT("my_symbol")}};
|
||||
auto pull_remote_order_by =
|
||||
std::make_unique<PullRemoteOrderBy>(once, 42, order_by, symbols);
|
||||
|
Loading…
Reference in New Issue
Block a user