Implement plan cloning with LCP
Summary: Implement proper plan cloning using LCP instead of hacking it with serialization. depends on D1815 Reviewers: teon.banek, llugovic Reviewed By: teon.banek Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D1816
This commit is contained in:
parent
62e06d4b70
commit
914f40411a
@ -61,33 +61,54 @@ Usage example:
|
|||||||
(defun copy-object (source-name dest-name)
|
(defun copy-object (source-name dest-name)
|
||||||
(format nil "~A = ~A;" dest-name source-name))
|
(format nil "~A = ~A;" dest-name source-name))
|
||||||
|
|
||||||
|
;; TODO: This could be a common function in types.lisp if it were improved
|
||||||
|
;; a bit. It probably won't be necessary once we refactor LCP to use uniform
|
||||||
|
;; type designators.
|
||||||
|
(defun get-type (type-designator)
|
||||||
|
(ctypecase type-designator
|
||||||
|
(lcp::cpp-type type-designator)
|
||||||
|
(string (lcp::parse-cpp-type-declaration type-designator))
|
||||||
|
(symbol (lcp::cpp-type type-designator))))
|
||||||
|
|
||||||
(defun clone-by-copy-p (object-type)
|
(defun clone-by-copy-p (object-type)
|
||||||
(cond
|
(let ((object-type (get-type object-type)))
|
||||||
((string= "vector" (lcp::cpp-type-name object-type))
|
(cond
|
||||||
(clone-by-copy-p (car (lcp::cpp-type-type-args object-type))))
|
((string= "vector" (lcp::cpp-type-name object-type))
|
||||||
((string= "optional" (lcp::cpp-type-name object-type))
|
(clone-by-copy-p (car (lcp::cpp-type-type-args object-type))))
|
||||||
(clone-by-copy-p (car (lcp::cpp-type-type-args object-type))))
|
((string= "optional" (lcp::cpp-type-name object-type))
|
||||||
((string= "unordered_map" (lcp::cpp-type-name object-type))
|
(clone-by-copy-p (car (lcp::cpp-type-type-args object-type))))
|
||||||
(and (clone-by-copy-p (first (lcp::cpp-type-type-args object-type)))
|
((string= "unordered_map" (lcp::cpp-type-name object-type))
|
||||||
(clone-by-copy-p (second (lcp::cpp-type-type-args object-type)))))
|
(and (clone-by-copy-p (first (lcp::cpp-type-type-args object-type)))
|
||||||
((string= "pair" (lcp::cpp-type-name object-type))
|
(clone-by-copy-p (second (lcp::cpp-type-type-args object-type)))))
|
||||||
(and (clone-by-copy-p (first (lcp::cpp-type-type-args object-type)))
|
((string= "pair" (lcp::cpp-type-name object-type))
|
||||||
(clone-by-copy-p (second (lcp::cpp-type-type-args object-type)))))
|
(and (clone-by-copy-p (first (lcp::cpp-type-type-args object-type)))
|
||||||
((lcp::cpp-type-type-args object-type) nil)
|
(clone-by-copy-p (second (lcp::cpp-type-type-args object-type)))))
|
||||||
(t (or
|
((lcp::cpp-type-type-args object-type) nil)
|
||||||
(lcp::find-cpp-enum (lcp::cpp-type-name object-type))
|
((or (lcp::find-cpp-enum (lcp::cpp-type-name object-type))
|
||||||
(typep object-type 'lcp::cpp-primitive-type)
|
(typep object-type 'lcp::cpp-primitive-type)
|
||||||
(string= "string" (lcp::cpp-type-name object-type))
|
(string= "string" (lcp::cpp-type-name object-type))
|
||||||
(not (lcp::find-cpp-class (lcp::cpp-type-name object-type)))
|
;; TODO: We might want to forbid implicit copying of unknown types once
|
||||||
(not (lcp::cpp-class-clone-opts
|
;; there's a way to globally mark type as trivially copyable. Now it is
|
||||||
(lcp::find-cpp-class (lcp::cpp-type-name object-type))))))))
|
;; too annoying to add (:clone :copy) option everywhere.
|
||||||
|
(not (lcp::find-cpp-class (lcp::cpp-type-name object-type))))
|
||||||
|
t)
|
||||||
|
(t
|
||||||
|
;; We know now that we're dealing with a C++ class defined in
|
||||||
|
;; LCP. A class is cloneable by copy only if it doesn't have
|
||||||
|
;; `Clone` function defined, all of its members are cloneable
|
||||||
|
;; by copy and it is not a member of inheritance hierarchy.
|
||||||
|
(let ((cpp-class (lcp::find-cpp-class (lcp::cpp-type-name object-type))))
|
||||||
|
(assert cpp-class)
|
||||||
|
(and (not (lcp::cpp-class-clone-opts cpp-class))
|
||||||
|
(not (lcp::direct-subclasses-of cpp-class))
|
||||||
|
(not (lcp::cpp-class-super-classes cpp-class))
|
||||||
|
(every (lambda (member)
|
||||||
|
(or (eq (lcp::cpp-member-clone member) :copy)
|
||||||
|
(clone-by-copy-p (lcp::cpp-member-type member))))
|
||||||
|
(lcp::cpp-class-members cpp-class))))))))
|
||||||
|
|
||||||
(defun clone-object (object-type source-name dest-name &key args)
|
(defun clone-object (object-type source-name dest-name &key args)
|
||||||
(let ((object-type
|
(let ((object-type (get-type object-type))
|
||||||
(ctypecase object-type
|
|
||||||
(lcp::cpp-type object-type)
|
|
||||||
(string (lcp::parse-cpp-type-declaration object-type))
|
|
||||||
(symbol (lcp::cpp-type object-type))))
|
|
||||||
(arg-list (format nil "~{~A~^, ~}"
|
(arg-list (format nil "~{~A~^, ~}"
|
||||||
(mapcar (lambda (name-and-type)
|
(mapcar (lambda (name-and-type)
|
||||||
(lcp::cpp-variable-name (first name-and-type)))
|
(lcp::cpp-variable-name (first name-and-type)))
|
||||||
@ -115,9 +136,8 @@ Usage example:
|
|||||||
((and (lcp::find-cpp-class (lcp::cpp-type-name object-type))
|
((and (lcp::find-cpp-class (lcp::cpp-type-name object-type))
|
||||||
(lcp::cpp-class-clone-opts (lcp::find-cpp-class (lcp::cpp-type-name object-type))))
|
(lcp::cpp-class-clone-opts (lcp::find-cpp-class (lcp::cpp-type-name object-type))))
|
||||||
(format nil "~A = ~A.Clone(~A);" dest-name source-name arg-list))
|
(format nil "~A = ~A.Clone(~A);" dest-name source-name arg-list))
|
||||||
(t
|
(t (clone-error "Don't know how to clone object of type ~A"
|
||||||
(format nil "static_assert(false, \"Don't know how to clone object of type ~A\");"
|
(lcp::cpp-type-decl object-type))))))
|
||||||
(lcp::cpp-type-decl object-type))))))
|
|
||||||
|
|
||||||
(defun clone-vector (elem-type source-name dest-name &key args)
|
(defun clone-vector (elem-type source-name dest-name &key args)
|
||||||
(with-vars ((loop-counter "i"))
|
(with-vars ((loop-counter "i"))
|
||||||
|
@ -566,172 +566,190 @@
|
|||||||
'lcp.slk:slk-error)))
|
'lcp.slk:slk-error)))
|
||||||
|
|
||||||
(deftest "clone"
|
(deftest "clone"
|
||||||
(subtest "no inheritance"
|
(macrolet ((single-member-test (member expected)
|
||||||
(undefine-cpp-types)
|
(let ((class-sym (gensym)))
|
||||||
(let ((tree-class (lcp:define-class tree ()
|
`(let ((,class-sym (lcp:define-class my-class ()
|
||||||
((value :int32_t)
|
(,member)
|
||||||
(left "std::unique_ptr<Tree>")
|
(:clone))))
|
||||||
(right "std::unique_ptr<Tree>"))
|
,(etypecase expected
|
||||||
(:clone :return-type (lambda (typename)
|
(string
|
||||||
(format nil "std::unique_ptr<~A>" typename))
|
`(is-generated (lcp.clone:clone-function-definition-for-class ,class-sym)
|
||||||
:init-object (lambda (var typename)
|
(format nil "MyClass Clone() const {
|
||||||
(format nil "auto ~A = std::make_unique<~A>();"
|
MyClass object;
|
||||||
var typename)))))
|
~A
|
||||||
(forest-class (lcp:define-class forest ()
|
return object;
|
||||||
((name "std::string")
|
}"
|
||||||
(small-tree "std::unique_ptr<Tree>")
|
,expected)))
|
||||||
(big-tree "std::unique_ptr<Tree>"))
|
(symbol
|
||||||
(:clone))))
|
(assert (eq expected 'lcp.clone:clone-error))
|
||||||
(is-generated (lcp.clone:clone-function-definition-for-class tree-class)
|
`(is-error (lcp.clone:clone-function-definition-for-class ,class-sym)
|
||||||
"std::unique_ptr<Tree> Clone() const {
|
',expected)))))))
|
||||||
|
(subtest "no inheritance"
|
||||||
|
(undefine-cpp-types)
|
||||||
|
(let ((tree-class (lcp:define-class tree ()
|
||||||
|
((value :int32_t)
|
||||||
|
(left "std::unique_ptr<Tree>")
|
||||||
|
(right "std::unique_ptr<Tree>"))
|
||||||
|
(:clone :return-type (lambda (typename)
|
||||||
|
(format nil "std::unique_ptr<~A>" typename))
|
||||||
|
:init-object (lambda (var typename)
|
||||||
|
(format nil "auto ~A = std::make_unique<~A>();"
|
||||||
|
var typename)))))
|
||||||
|
(forest-class (lcp:define-class forest ()
|
||||||
|
((name "std::string")
|
||||||
|
(small-tree "std::unique_ptr<Tree>")
|
||||||
|
(big-tree "std::unique_ptr<Tree>"))
|
||||||
|
(:clone))))
|
||||||
|
(is-generated (lcp.clone:clone-function-definition-for-class tree-class)
|
||||||
|
"std::unique_ptr<Tree> Clone() const {
|
||||||
auto object = std::make_unique<Tree>();
|
auto object = std::make_unique<Tree>();
|
||||||
object->value_ = value_;
|
object->value_ = value_;
|
||||||
object->left_ = left_ ? left_->Clone() : nullptr;
|
object->left_ = left_ ? left_->Clone() : nullptr;
|
||||||
object->right_ = right_ ? right_->Clone() : nullptr;
|
object->right_ = right_ ? right_->Clone() : nullptr;
|
||||||
return object;
|
return object;
|
||||||
}")
|
}")
|
||||||
(is-generated (lcp.clone:clone-function-definition-for-class forest-class)
|
(is-generated (lcp.clone:clone-function-definition-for-class forest-class)
|
||||||
"Forest Clone() const {
|
"Forest Clone() const {
|
||||||
Forest object;
|
Forest object;
|
||||||
object.name_ = name_;
|
object.name_ = name_;
|
||||||
object.small_tree_ = small_tree_ ? small_tree_->Clone() : nullptr;
|
object.small_tree_ = small_tree_ ? small_tree_->Clone() : nullptr;
|
||||||
object.big_tree_ = big_tree_ ? big_tree_->Clone() : nullptr;
|
object.big_tree_ = big_tree_ ? big_tree_->Clone() : nullptr;
|
||||||
return object;
|
return object;
|
||||||
}")))
|
}")))
|
||||||
(subtest "single inheritance"
|
(subtest "single inheritance"
|
||||||
(undefine-cpp-types)
|
(undefine-cpp-types)
|
||||||
;; Simple case
|
;; Simple case
|
||||||
(let ((base-class (lcp:define-class base ()
|
(let ((base-class (lcp:define-class base ()
|
||||||
((int-member :int32_t)
|
((int-member :int32_t)
|
||||||
(string-member "std::string"))
|
(string-member "std::string"))
|
||||||
(:clone)))
|
(:clone)))
|
||||||
(child-class (lcp:define-class child (base)
|
(child-class (lcp:define-class child (base)
|
||||||
((another-int-member :int64_t))
|
((another-int-member :int64_t))
|
||||||
(:clone))))
|
(:clone))))
|
||||||
(is-generated (lcp.clone:clone-function-definition-for-class base-class)
|
(is-generated (lcp.clone:clone-function-definition-for-class base-class)
|
||||||
"virtual std::unique_ptr<Base> Clone() const {
|
"virtual std::unique_ptr<Base> Clone() const {
|
||||||
auto object = std::make_unique<Base>();
|
auto object = std::make_unique<Base>();
|
||||||
object->int_member_ = int_member_;
|
object->int_member_ = int_member_;
|
||||||
object->string_member_ = string_member_;
|
object->string_member_ = string_member_;
|
||||||
return object;
|
return object;
|
||||||
}")
|
}")
|
||||||
(is-generated (lcp.clone:clone-function-definition-for-class child-class)
|
(is-generated (lcp.clone:clone-function-definition-for-class child-class)
|
||||||
"std::unique_ptr<Base> Clone() const override {
|
"std::unique_ptr<Base> Clone() const override {
|
||||||
auto object = std::make_unique<Child>();
|
auto object = std::make_unique<Child>();
|
||||||
object->int_member_ = int_member_;
|
object->int_member_ = int_member_;
|
||||||
object->string_member_ = string_member_;
|
object->string_member_ = string_member_;
|
||||||
object->another_int_member_ = another_int_member_;
|
object->another_int_member_ = another_int_member_;
|
||||||
return object;
|
return object;
|
||||||
}"))
|
}"))
|
||||||
(undefine-cpp-types)
|
(undefine-cpp-types)
|
||||||
;; Abstract base class
|
;; Abstract base class
|
||||||
(let ((base-class (lcp:define-class base ()
|
(let ((base-class (lcp:define-class base ()
|
||||||
((int-member :int32_t)
|
((int-member :int32_t)
|
||||||
(string-member "std::string"))
|
(string-member "std::string"))
|
||||||
(:abstractp t)
|
(:abstractp t)
|
||||||
(:clone)))
|
(:clone)))
|
||||||
(child-class (lcp:define-class child (base)
|
(child-class (lcp:define-class child (base)
|
||||||
((another-int-member :int64_t))
|
((another-int-member :int64_t))
|
||||||
(:clone))))
|
(:clone))))
|
||||||
(is-generated (lcp.clone:clone-function-definition-for-class base-class)
|
(is-generated (lcp.clone:clone-function-definition-for-class base-class)
|
||||||
"virtual std::unique_ptr<Base> Clone() const = 0;")
|
"virtual std::unique_ptr<Base> Clone() const = 0;")
|
||||||
(is-generated (lcp.clone:clone-function-definition-for-class child-class)
|
(is-generated (lcp.clone:clone-function-definition-for-class child-class)
|
||||||
"std::unique_ptr<Base> Clone() const override {
|
"std::unique_ptr<Base> Clone() const override {
|
||||||
auto object = std::make_unique<Child>();
|
auto object = std::make_unique<Child>();
|
||||||
object->int_member_ = int_member_;
|
object->int_member_ = int_member_;
|
||||||
object->string_member_ = string_member_;
|
object->string_member_ = string_member_;
|
||||||
object->another_int_member_ = another_int_member_;
|
object->another_int_member_ = another_int_member_;
|
||||||
return object;
|
return object;
|
||||||
}"))
|
}"))
|
||||||
(undefine-cpp-types)
|
(undefine-cpp-types)
|
||||||
;; :return-type and :init-object propagation
|
;; :return-type and :init-object propagation
|
||||||
(let ((base-class (lcp:define-class base ()
|
(let ((base-class (lcp:define-class base ()
|
||||||
((int-member :int32_t)
|
((int-member :int32_t)
|
||||||
(string-member "std::string"))
|
(string-member "std::string"))
|
||||||
(:abstractp t)
|
(:abstractp t)
|
||||||
(:clone :return-type (lambda (typename)
|
(:clone :return-type (lambda (typename)
|
||||||
(format nil "~A*" typename))
|
(format nil "~A*" typename))
|
||||||
:init-object (lambda (var typename)
|
:init-object (lambda (var typename)
|
||||||
(format nil "~A* ~A = GlobalFactory::Create();"
|
(format nil "~A* ~A = GlobalFactory::Create();"
|
||||||
typename var)))))
|
typename var)))))
|
||||||
(child-class (lcp:define-class child (base)
|
(child-class (lcp:define-class child (base)
|
||||||
((another-int-member :int64_t))
|
((another-int-member :int64_t))
|
||||||
(:clone))))
|
(:clone))))
|
||||||
(is-generated (lcp.clone:clone-function-definition-for-class base-class)
|
(is-generated (lcp.clone:clone-function-definition-for-class base-class)
|
||||||
"virtual Base *Clone() const = 0;")
|
"virtual Base *Clone() const = 0;")
|
||||||
(is-generated (lcp.clone:clone-function-definition-for-class child-class)
|
(is-generated (lcp.clone:clone-function-definition-for-class child-class)
|
||||||
"Child *Clone() const override {
|
"Child *Clone() const override {
|
||||||
Child *object = GlobalFactory::Create();
|
Child *object = GlobalFactory::Create();
|
||||||
object->int_member_ = int_member_;
|
object->int_member_ = int_member_;
|
||||||
object->string_member_ = string_member_;
|
object->string_member_ = string_member_;
|
||||||
object->another_int_member_ = another_int_member_;
|
object->another_int_member_ = another_int_member_;
|
||||||
return object;
|
return object;
|
||||||
}"))
|
}"))
|
||||||
(undefine-cpp-types)
|
(undefine-cpp-types)
|
||||||
;; inheritance with :ignore-other-base-classes and :base
|
;; inheritance with :ignore-other-base-classes and :base
|
||||||
(let ((base-class (lcp:define-class base ("utils::TotalOrdering")
|
(let ((base-class (lcp:define-class base ("utils::TotalOrdering")
|
||||||
((int-member :int32_t)
|
((int-member :int32_t)
|
||||||
(string-member "std::string"))
|
(string-member "std::string"))
|
||||||
(:abstractp t)
|
(:abstractp t)
|
||||||
(:clone :base t
|
(:clone :base t
|
||||||
:return-type (lambda (typename)
|
:return-type (lambda (typename)
|
||||||
(format nil "~A*" typename))
|
(format nil "~A*" typename))
|
||||||
:init-object (lambda (var typename)
|
:init-object (lambda (var typename)
|
||||||
(format nil "~A* ~A = GlobalFactory::Create();"
|
(format nil "~A* ~A = GlobalFactory::Create();"
|
||||||
typename var)))))
|
typename var)))))
|
||||||
(child-class (lcp:define-class child (base "utils::TotalOrdering" "utils::TotalOrdering")
|
(child-class (lcp:define-class child (base "utils::TotalOrdering" "utils::TotalOrdering")
|
||||||
((another-int-member :int64_t))
|
((another-int-member :int64_t))
|
||||||
(:clone :ignore-other-base-classes t))))
|
(:clone :ignore-other-base-classes t))))
|
||||||
(is-generated (lcp.clone:clone-function-definition-for-class base-class)
|
(is-generated (lcp.clone:clone-function-definition-for-class base-class)
|
||||||
"virtual Base *Clone() const = 0;")
|
"virtual Base *Clone() const = 0;")
|
||||||
(is-generated (lcp.clone:clone-function-definition-for-class child-class)
|
(is-generated (lcp.clone:clone-function-definition-for-class child-class)
|
||||||
"Child *Clone() const override {
|
"Child *Clone() const override {
|
||||||
Child *object = GlobalFactory::Create();
|
Child *object = GlobalFactory::Create();
|
||||||
object->int_member_ = int_member_;
|
object->int_member_ = int_member_;
|
||||||
object->string_member_ = string_member_;
|
object->string_member_ = string_member_;
|
||||||
object->another_int_member_ = another_int_member_;
|
object->another_int_member_ = another_int_member_;
|
||||||
return object;
|
return object;
|
||||||
}")))
|
}")))
|
||||||
(subtest "extra args"
|
(subtest "extra args"
|
||||||
(undefine-cpp-types)
|
(undefine-cpp-types)
|
||||||
;; extra arguments are always passed when calling `Clone` function
|
;; extra arguments are always passed when calling `Clone` function
|
||||||
(let ((expression-class (lcp:define-class expression ()
|
(let ((expression-class (lcp:define-class expression ()
|
||||||
((lhs "Expression *")
|
((lhs "Expression *")
|
||||||
(rhs "Expression *"))
|
(rhs "Expression *"))
|
||||||
(:abstractp t)
|
(:abstractp t)
|
||||||
(:clone :return-type (lambda (typename)
|
(:clone :return-type (lambda (typename)
|
||||||
(format nil "~A*" typename))
|
(format nil "~A*" typename))
|
||||||
:init-object (lambda (var typename)
|
:init-object (lambda (var typename)
|
||||||
(format nil "~A* ~A = storage->Create<~A>();"
|
(format nil "~A* ~A = storage->Create<~A>();"
|
||||||
typename var typename))
|
typename var typename))
|
||||||
:args '((storage "ExpressionStorage *")))))
|
:args '((storage "ExpressionStorage *")))))
|
||||||
(and-class (lcp:define-class and (expression)
|
(and-class (lcp:define-class and (expression)
|
||||||
()
|
()
|
||||||
(:clone)))
|
(:clone)))
|
||||||
(or-class (lcp:define-class or (expression)
|
(or-class (lcp:define-class or (expression)
|
||||||
()
|
()
|
||||||
(:clone)))
|
(:clone)))
|
||||||
(filter-class (lcp:define-class filter ()
|
(filter-class (lcp:define-class filter ()
|
||||||
((expressions "std::vector<Expression *>"))
|
((expressions "std::vector<Expression *>"))
|
||||||
(:clone :args '((exp-storage "ExpressionStorage *"))))))
|
(:clone :args '((exp-storage "ExpressionStorage *"))))))
|
||||||
(is-generated (lcp.clone:clone-function-definition-for-class expression-class)
|
(is-generated (lcp.clone:clone-function-definition-for-class expression-class)
|
||||||
"virtual Expression *Clone(ExpressionStorage *storage) const = 0;")
|
"virtual Expression *Clone(ExpressionStorage *storage) const = 0;")
|
||||||
(is-generated (lcp.clone:clone-function-definition-for-class and-class)
|
(is-generated (lcp.clone:clone-function-definition-for-class and-class)
|
||||||
"And *Clone(ExpressionStorage *storage) const override {
|
"And *Clone(ExpressionStorage *storage) const override {
|
||||||
And *object = storage->Create<And>();
|
And *object = storage->Create<And>();
|
||||||
object->lhs_ = lhs_ ? lhs_->Clone(storage) : nullptr;
|
object->lhs_ = lhs_ ? lhs_->Clone(storage) : nullptr;
|
||||||
object->rhs_ = rhs_ ? rhs_->Clone(storage) : nullptr;
|
object->rhs_ = rhs_ ? rhs_->Clone(storage) : nullptr;
|
||||||
return object;
|
return object;
|
||||||
}")
|
}")
|
||||||
(is-generated (lcp.clone:clone-function-definition-for-class or-class)
|
(is-generated (lcp.clone:clone-function-definition-for-class or-class)
|
||||||
"Or *Clone(ExpressionStorage *storage) const override {
|
"Or *Clone(ExpressionStorage *storage) const override {
|
||||||
Or *object = storage->Create<Or>();
|
Or *object = storage->Create<Or>();
|
||||||
object->lhs_ = lhs_ ? lhs_->Clone(storage) : nullptr;
|
object->lhs_ = lhs_ ? lhs_->Clone(storage) : nullptr;
|
||||||
object->rhs_ = rhs_ ? rhs_->Clone(storage) : nullptr;
|
object->rhs_ = rhs_ ? rhs_->Clone(storage) : nullptr;
|
||||||
return object;
|
return object;
|
||||||
}")
|
}")
|
||||||
(is-generated (lcp.clone:clone-function-definition-for-class filter-class)
|
(is-generated (lcp.clone:clone-function-definition-for-class filter-class)
|
||||||
"Filter Clone(ExpressionStorage *exp_storage) const {
|
"Filter Clone(ExpressionStorage *exp_storage) const {
|
||||||
Filter object;
|
Filter object;
|
||||||
object.expressions_.resize(expressions_.size());
|
object.expressions_.resize(expressions_.size());
|
||||||
for (auto i1 = 0; i1 < expressions_.size(); ++i1) {
|
for (auto i1 = 0; i1 < expressions_.size(); ++i1) {
|
||||||
@ -740,59 +758,47 @@
|
|||||||
}
|
}
|
||||||
return object;
|
return object;
|
||||||
}")))
|
}")))
|
||||||
(subtest "unsupported"
|
(subtest "unsupported"
|
||||||
;; multiple inheritance
|
;; multiple inheritance
|
||||||
(undefine-cpp-types)
|
(undefine-cpp-types)
|
||||||
(lcp:define-class first-base ()
|
(lcp:define-class first-base ()
|
||||||
((int-member :int32_t))
|
((int-member :int32_t))
|
||||||
(:clone))
|
(:clone))
|
||||||
(lcp:define-class second-base ()
|
(lcp:define-class second-base ()
|
||||||
((private-member :int32_t :scope :private))
|
((private-member :int32_t :scope :private))
|
||||||
(:clone))
|
(:clone))
|
||||||
(let ((child-class (lcp:define-class child (first-base second-base)
|
(let ((child-class (lcp:define-class child (first-base second-base)
|
||||||
((name "std::string"))
|
((name "std::string"))
|
||||||
|
(:clone))))
|
||||||
|
(is-error (lcp.clone:clone-function-definition-for-class child-class)
|
||||||
|
'lcp.clone:clone-error))
|
||||||
|
;; template classes
|
||||||
|
(undefine-cpp-types)
|
||||||
|
(let ((container-class (lcp:define-class (my-container t-element) ()
|
||||||
|
((data "TElement *")
|
||||||
|
(size "size_t")))))
|
||||||
|
(is-error (lcp.clone:clone-function-definition-for-class container-class)
|
||||||
|
'lcp.clone:clone-error)))
|
||||||
|
(subtest "custom clone"
|
||||||
|
(undefine-cpp-types)
|
||||||
|
(let ((my-class (lcp:define-class my-class ()
|
||||||
|
((callback "std::function<void(int, int)>" :clone :copy)
|
||||||
|
(click-counter :int32_t :clone nil)
|
||||||
|
(widget "Widget"
|
||||||
|
:clone (lambda (source dest)
|
||||||
|
#>cpp
|
||||||
|
${dest} = WidgetFactory::Create(${source}.type());
|
||||||
|
cpp<#)))
|
||||||
(:clone))))
|
(:clone))))
|
||||||
(is-error (lcp.clone:clone-function-definition-for-class child-class)
|
(is-generated (lcp.clone:clone-function-definition-for-class my-class)
|
||||||
'lcp.clone:clone-error))
|
"MyClass Clone() const {
|
||||||
;; template classes
|
|
||||||
(undefine-cpp-types)
|
|
||||||
(let ((container-class (lcp:define-class (my-container t-element) ()
|
|
||||||
((data "TElement *")
|
|
||||||
(size "size_t")))))
|
|
||||||
(is-error (lcp.clone:clone-function-definition-for-class container-class)
|
|
||||||
'lcp.clone:clone-error)))
|
|
||||||
(subtest "custom clone"
|
|
||||||
(undefine-cpp-types)
|
|
||||||
(let ((my-class (lcp:define-class my-class ()
|
|
||||||
((callback "std::function<void(int, int)>" :clone :copy)
|
|
||||||
(click-counter :int32_t :clone nil)
|
|
||||||
(widget "Widget"
|
|
||||||
:clone (lambda (source dest)
|
|
||||||
#>cpp
|
|
||||||
${dest} = WidgetFactory::Create(${source}.type());
|
|
||||||
cpp<#)))
|
|
||||||
(:clone))))
|
|
||||||
(is-generated (lcp.clone:clone-function-definition-for-class my-class)
|
|
||||||
"MyClass Clone() const {
|
|
||||||
MyClass object;
|
MyClass object;
|
||||||
object.callback_ = callback_;
|
object.callback_ = callback_;
|
||||||
object.widget_ = WidgetFactory::Create(widget_.type());
|
object.widget_ = WidgetFactory::Create(widget_.type());
|
||||||
return object;
|
return object;
|
||||||
}")))
|
}")))
|
||||||
(subtest "types"
|
(subtest "types"
|
||||||
(undefine-cpp-types)
|
(undefine-cpp-types)
|
||||||
(macrolet ((single-member-test (member expected)
|
|
||||||
(let ((class-sym (gensym)))
|
|
||||||
`(let ((,class-sym (lcp:define-class my-class ()
|
|
||||||
(,member)
|
|
||||||
(:clone))))
|
|
||||||
(is-generated (lcp.clone:clone-function-definition-for-class ,class-sym)
|
|
||||||
(format nil "MyClass Clone() const {
|
|
||||||
MyClass object;
|
|
||||||
~A
|
|
||||||
return object;
|
|
||||||
}"
|
|
||||||
,expected))))))
|
|
||||||
(lcp:define-class klondike ()
|
(lcp:define-class klondike ()
|
||||||
()
|
()
|
||||||
(:clone))
|
(:clone))
|
||||||
@ -922,8 +928,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
object.member_ = std::make_pair(std::move(first1), std::move(second1));
|
object.member_ = std::make_pair(std::move(first1), std::move(second1));
|
||||||
}")
|
}"))
|
||||||
)
|
|
||||||
(subtest "pointers"
|
(subtest "pointers"
|
||||||
(single-member-test (member "Klondike *")
|
(single-member-test (member "Klondike *")
|
||||||
"object.member_ = member_ ? member_->Clone() : nullptr;")
|
"object.member_ = member_ ? member_->Clone() : nullptr;")
|
||||||
@ -939,4 +944,25 @@
|
|||||||
(single-member-test (member :int32_t)
|
(single-member-test (member :int32_t)
|
||||||
"object.member_ = member_;")
|
"object.member_ = member_;")
|
||||||
(single-member-test (member :char)
|
(single-member-test (member :char)
|
||||||
"object.member_ = member_;")))))
|
"object.member_ = member_;")))
|
||||||
|
(subtest "class copying"
|
||||||
|
(undefine-cpp-types)
|
||||||
|
(lcp:define-class non-copyable-class-1 ()
|
||||||
|
((counter "int32_t *")))
|
||||||
|
(lcp:define-class cloneable-class ()
|
||||||
|
((uid :int32_t))
|
||||||
|
(:clone))
|
||||||
|
(lcp:define-class copyable-class-1 ()
|
||||||
|
((counter "int32_t *" :clone :copy)))
|
||||||
|
(lcp:define-class copyable-class-2 ()
|
||||||
|
((member :int32_t)))
|
||||||
|
(single-member-test (member "NonCopyableClass1")
|
||||||
|
lcp.clone:clone-error)
|
||||||
|
(single-member-test (member "CloneableClass")
|
||||||
|
"object.member_ = member_.Clone();")
|
||||||
|
(single-member-test (member "CopyableClass1")
|
||||||
|
"object.member_ = member_;")
|
||||||
|
(single-member-test (member "CopyableClass2")
|
||||||
|
"object.member_ = member_;")
|
||||||
|
(single-member-test (member "UnknownClass")
|
||||||
|
"object.member_ = member_;"))))
|
||||||
|
@ -332,7 +332,14 @@ class AstStorage {
|
|||||||
cpp<#
|
cpp<#
|
||||||
|
|
||||||
(lcp:define-class tree ()
|
(lcp:define-class tree ()
|
||||||
((uid :int32_t :scope :public))
|
((uid :int32_t :scope :public
|
||||||
|
:clone (lambda (source dest)
|
||||||
|
#>cpp
|
||||||
|
${dest} = ${source};
|
||||||
|
// TODO(mtomic): This is a hack. Adopting existing UIDs breaks everything
|
||||||
|
// because `AstStorage` keeps a counter for generating when `Create` is called.
|
||||||
|
storage->max_existing_uid_ = std::max(storage->max_existing_uid_, ${source});
|
||||||
|
cpp<#)))
|
||||||
(:abstractp t)
|
(:abstractp t)
|
||||||
(:public
|
(:public
|
||||||
#>cpp
|
#>cpp
|
||||||
|
@ -18,18 +18,9 @@ namespace {
|
|||||||
|
|
||||||
std::pair<std::unique_ptr<LogicalOperator>, AstStorage> Clone(
|
std::pair<std::unique_ptr<LogicalOperator>, AstStorage> Clone(
|
||||||
const LogicalOperator &original_plan) {
|
const LogicalOperator &original_plan) {
|
||||||
// TODO: Add a proper Clone method to LogicalOperator
|
AstStorage storage;
|
||||||
::capnp::MallocMessageBuilder message;
|
std::unique_ptr<LogicalOperator> root_copy = original_plan.Clone(&storage);
|
||||||
{
|
return std::make_pair(std::move(root_copy), std::move(storage));
|
||||||
auto builder = message.initRoot<query::plan::capnp::LogicalOperator>();
|
|
||||||
LogicalOperator::SaveHelper helper;
|
|
||||||
Save(original_plan, &builder, &helper);
|
|
||||||
}
|
|
||||||
auto reader = message.getRoot<query::plan::capnp::LogicalOperator>();
|
|
||||||
std::unique_ptr<LogicalOperator> plan_copy;
|
|
||||||
LogicalOperator::LoadHelper helper;
|
|
||||||
Load(&plan_copy, reader, &helper);
|
|
||||||
return std::make_pair(std::move(plan_copy), std::move(helper.ast_storage));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t AddWorkerPlan(DistributedPlan &distributed_plan,
|
int64_t AddWorkerPlan(DistributedPlan &distributed_plan,
|
||||||
|
@ -84,7 +84,8 @@ time on data transfer. It gives no guarantees on result order.")
|
|||||||
input_ = input;
|
input_ = input;
|
||||||
}
|
}
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(defun slk-load-pull-remote (member)
|
(defun slk-load-pull-remote (member)
|
||||||
#>cpp
|
#>cpp
|
||||||
@ -119,7 +120,16 @@ time on data transfer. It gives no guarantees on result order.")
|
|||||||
:slk-save #'slk-save-operator-pointer
|
:slk-save #'slk-save-operator-pointer
|
||||||
:slk-load #'slk-load-pull-remote
|
:slk-load #'slk-load-pull-remote
|
||||||
:capnp-save #'save-operator-pointer
|
:capnp-save #'save-operator-pointer
|
||||||
:capnp-load #'load-pull-remote)
|
:capnp-load #'load-pull-remote
|
||||||
|
:clone (lambda (source dest)
|
||||||
|
#>cpp
|
||||||
|
if (${source}) {
|
||||||
|
std::shared_ptr<LogicalOperator> tmp = ${source}->Clone(storage);
|
||||||
|
${dest} = std::static_pointer_cast<PullRemote>(tmp);
|
||||||
|
} else {
|
||||||
|
${dest} = nullptr;
|
||||||
|
}
|
||||||
|
cpp<#))
|
||||||
(advance-command :bool :initval "false" :scope :public))
|
(advance-command :bool :initval "false" :scope :public))
|
||||||
(:documentation
|
(:documentation
|
||||||
"Operator used to synchronize stages of plan execution between the master and
|
"Operator used to synchronize stages of plan execution between the master and
|
||||||
@ -164,7 +174,8 @@ Logic of the synchronize operator is:
|
|||||||
input_ = input;
|
input_ = input;
|
||||||
}
|
}
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class pull-remote-order-by (logical-operator)
|
(lcp:define-class pull-remote-order-by (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -209,7 +220,8 @@ by having only one result from each worker.")
|
|||||||
input_ = input;
|
input_ = input;
|
||||||
}
|
}
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class distributed-expand (logical-operator)
|
(lcp:define-class distributed-expand (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -242,7 +254,8 @@ by having only one result from each worker.")
|
|||||||
input_ = input;
|
input_ = input;
|
||||||
}
|
}
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class distributed-expand-bfs (logical-operator)
|
(lcp:define-class distributed-expand-bfs (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -312,7 +325,8 @@ by having only one result from each worker.")
|
|||||||
input_ = input;
|
input_ = input;
|
||||||
}
|
}
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class distributed-create-node (logical-operator)
|
(lcp:define-class distributed-create-node (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -348,7 +362,8 @@ by having only one result from each worker.")
|
|||||||
input_ = input;
|
input_ = input;
|
||||||
}
|
}
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class distributed-create-expand (logical-operator)
|
(lcp:define-class distributed-create-expand (logical-operator)
|
||||||
((node-info "NodeCreationInfo" :scope :public
|
((node-info "NodeCreationInfo" :scope :public
|
||||||
@ -395,7 +410,8 @@ by having only one result from each worker.")
|
|||||||
input_ = input;
|
input_ = input;
|
||||||
}
|
}
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:pop-namespace) ;; plan
|
(lcp:pop-namespace) ;; plan
|
||||||
(lcp:pop-namespace) ;; query
|
(lcp:pop-namespace) ;; query
|
||||||
|
@ -229,7 +229,9 @@ can serve as inputs to others and thus a sequence of operations is formed.")
|
|||||||
:load-args '((helper "query::plan::LogicalOperator::SlkLoadHelper *")))
|
:load-args '((helper "query::plan::LogicalOperator::SlkLoadHelper *")))
|
||||||
(:capnp :base t
|
(:capnp :base t
|
||||||
:save-args '((helper "LogicalOperator::SaveHelper *"))
|
:save-args '((helper "LogicalOperator::SaveHelper *"))
|
||||||
:load-args '((helper "LogicalOperator::LoadHelper *")))))
|
:load-args '((helper "LogicalOperator::LoadHelper *"))))
|
||||||
|
(:clone :args '((storage "AstStorage *"))
|
||||||
|
:base t))
|
||||||
|
|
||||||
(defun slk-save-ast-pointer (member)
|
(defun slk-save-ast-pointer (member)
|
||||||
#>cpp
|
#>cpp
|
||||||
@ -371,7 +373,8 @@ and false on every following Pull.")
|
|||||||
bool did_pull_{false};
|
bool did_pull_{false};
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(defun slk-save-properties (member)
|
(defun slk-save-properties (member)
|
||||||
#>cpp
|
#>cpp
|
||||||
@ -431,7 +434,8 @@ and false on every following Pull.")
|
|||||||
(:serialize (:slk :save-args '((helper "query::plan::LogicalOperator::SaveHelper *"))
|
(:serialize (:slk :save-args '((helper "query::plan::LogicalOperator::SaveHelper *"))
|
||||||
:load-args '((helper "query::plan::LogicalOperator::SlkLoadHelper *")))
|
:load-args '((helper "query::plan::LogicalOperator::SlkLoadHelper *")))
|
||||||
(:capnp :save-args '((helper "LogicalOperator::SaveHelper *"))
|
(:capnp :save-args '((helper "LogicalOperator::SaveHelper *"))
|
||||||
:load-args '((helper "LogicalOperator::LoadHelper *")))))
|
:load-args '((helper "LogicalOperator::LoadHelper *"))))
|
||||||
|
(:clone :args '((storage "AstStorage *"))))
|
||||||
|
|
||||||
(lcp:define-class create-node (logical-operator)
|
(lcp:define-class create-node (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -494,7 +498,8 @@ a preceeding `MATCH`), or multiple nodes (`MATCH ... CREATE` or
|
|||||||
const std::unique_ptr<Cursor> input_cursor_;
|
const std::unique_ptr<Cursor> input_cursor_;
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-struct edge-creation-info ()
|
(lcp:define-struct edge-creation-info ()
|
||||||
((symbol "Symbol")
|
((symbol "Symbol")
|
||||||
@ -516,7 +521,8 @@ a preceeding `MATCH`), or multiple nodes (`MATCH ... CREATE` or
|
|||||||
(:serialize (:slk :save-args '((helper "query::plan::LogicalOperator::SaveHelper *"))
|
(:serialize (:slk :save-args '((helper "query::plan::LogicalOperator::SaveHelper *"))
|
||||||
:load-args '((helper "query::plan::LogicalOperator::SlkLoadHelper *")))
|
:load-args '((helper "query::plan::LogicalOperator::SlkLoadHelper *")))
|
||||||
(:capnp :save-args '((helper "LogicalOperator::SaveHelper *"))
|
(:capnp :save-args '((helper "LogicalOperator::SaveHelper *"))
|
||||||
:load-args '((helper "LogicalOperator::LoadHelper *")))))
|
:load-args '((helper "LogicalOperator::LoadHelper *"))))
|
||||||
|
(:clone :args '((storage "AstStorage *"))))
|
||||||
|
|
||||||
(lcp:define-class create-expand (logical-operator)
|
(lcp:define-class create-expand (logical-operator)
|
||||||
((node-info "NodeCreationInfo" :scope :public
|
((node-info "NodeCreationInfo" :scope :public
|
||||||
@ -621,7 +627,8 @@ chained in cases when longer paths need creating.
|
|||||||
ExpressionEvaluator &evaluator);
|
ExpressionEvaluator &evaluator);
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class scan-all (logical-operator)
|
(lcp:define-class scan-all (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -675,7 +682,8 @@ with a constructor argument.
|
|||||||
input_ = input;
|
input_ = input;
|
||||||
}
|
}
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class scan-all-by-label (scan-all)
|
(lcp:define-class scan-all-by-label (scan-all)
|
||||||
((label "storage::Label" :scope :public))
|
((label "storage::Label" :scope :public))
|
||||||
@ -696,7 +704,8 @@ given label.
|
|||||||
std::unique_ptr<Cursor> MakeCursor(
|
std::unique_ptr<Cursor> MakeCursor(
|
||||||
database::GraphDbAccessor &db) const override;
|
database::GraphDbAccessor &db) const override;
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(defun slk-save-optional-bound (member)
|
(defun slk-save-optional-bound (member)
|
||||||
#>cpp
|
#>cpp
|
||||||
@ -774,20 +783,35 @@ given label.
|
|||||||
load-bound)
|
load-bound)
|
||||||
reader member capnp-name)))
|
reader member capnp-name)))
|
||||||
|
|
||||||
|
(defun clone-optional-bound (source dest)
|
||||||
|
#>cpp
|
||||||
|
if (${source}) {
|
||||||
|
${dest}.emplace(utils::Bound<Expression *>(
|
||||||
|
${source}->value()->Clone(storage),
|
||||||
|
${source}->type()));
|
||||||
|
} else {
|
||||||
|
${dest} = std::experimental::nullopt;
|
||||||
|
}
|
||||||
|
cpp<#)
|
||||||
|
|
||||||
(lcp:define-class scan-all-by-label-property-range (scan-all)
|
(lcp:define-class scan-all-by-label-property-range (scan-all)
|
||||||
((label "storage::Label" :scope :public)
|
((label "storage::Label" :scope :public)
|
||||||
(property "storage::Property" :scope :public)
|
(property "storage::Property" :scope :public)
|
||||||
(property-name "std::string" :scope :public)
|
(property-name "std::string" :scope :public)
|
||||||
(lower-bound "std::experimental::optional<Bound>" :scope :public
|
(lower-bound "std::experimental::optional<Bound>" :scope :public
|
||||||
:capnp-type "Utils.Optional(Utils.Bound(Ast.Tree))"
|
|
||||||
:slk-save #'slk-save-optional-bound
|
:slk-save #'slk-save-optional-bound
|
||||||
:slk-load #'slk-load-optional-bound
|
:slk-load #'slk-load-optional-bound
|
||||||
:capnp-save #'save-optional-bound :capnp-load #'load-optional-bound)
|
:capnp-save #'save-optional-bound
|
||||||
|
:capnp-load #'load-optional-bound
|
||||||
|
:capnp-type "Utils.Optional(Utils.Bound(Ast.Tree))"
|
||||||
|
:clone #'clone-optional-bound)
|
||||||
(upper-bound "std::experimental::optional<Bound>" :scope :public
|
(upper-bound "std::experimental::optional<Bound>" :scope :public
|
||||||
:slk-save #'slk-save-optional-bound
|
:slk-save #'slk-save-optional-bound
|
||||||
:slk-load #'slk-load-optional-bound
|
:slk-load #'slk-load-optional-bound
|
||||||
:capnp-save #'save-optional-bound :capnp-load #'load-optional-bound
|
:capnp-save #'save-optional-bound
|
||||||
:capnp-type "Utils.Optional(Utils.Bound(Ast.Tree))"))
|
:capnp-load #'load-optional-bound
|
||||||
|
:capnp-type "Utils.Optional(Utils.Bound(Ast.Tree))"
|
||||||
|
:clone #'clone-optional-bound))
|
||||||
(:documentation
|
(:documentation
|
||||||
"Behaves like @c ScanAll, but produces only vertices with given label and
|
"Behaves like @c ScanAll, but produces only vertices with given label and
|
||||||
property value which is inside a range (inclusive or exlusive).
|
property value which is inside a range (inclusive or exlusive).
|
||||||
@ -826,7 +850,8 @@ property value which is inside a range (inclusive or exlusive).
|
|||||||
std::unique_ptr<Cursor> MakeCursor(
|
std::unique_ptr<Cursor> MakeCursor(
|
||||||
database::GraphDbAccessor &db) const override;
|
database::GraphDbAccessor &db) const override;
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class scan-all-by-label-property-value (scan-all)
|
(lcp:define-class scan-all-by-label-property-value (scan-all)
|
||||||
((label "storage::Label" :scope :public)
|
((label "storage::Label" :scope :public)
|
||||||
@ -868,7 +893,8 @@ property value.
|
|||||||
std::unique_ptr<Cursor> MakeCursor(
|
std::unique_ptr<Cursor> MakeCursor(
|
||||||
database::GraphDbAccessor &db) const override;
|
database::GraphDbAccessor &db) const override;
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-struct expand-common ()
|
(lcp:define-struct expand-common ()
|
||||||
(
|
(
|
||||||
@ -989,7 +1015,8 @@ pulled.")
|
|||||||
bool InitEdges(Frame &, ExecutionContext &);
|
bool InitEdges(Frame &, ExecutionContext &);
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-struct expansion-lambda ()
|
(lcp:define-struct expansion-lambda ()
|
||||||
((inner-edge-symbol "Symbol" :documentation "Currently expanded edge symbol.")
|
((inner-edge-symbol "Symbol" :documentation "Currently expanded edge symbol.")
|
||||||
@ -1028,7 +1055,8 @@ pulled.")
|
|||||||
(:capnp
|
(:capnp
|
||||||
:save-args '((saved-ast-uids "std::vector<int32_t> *"))
|
:save-args '((saved-ast-uids "std::vector<int32_t> *"))
|
||||||
:load-args '((ast-storage "AstStorage *")
|
:load-args '((ast-storage "AstStorage *")
|
||||||
(loaded-ast-uids "std::vector<int32_t> *")))))
|
(loaded-ast-uids "std::vector<int32_t> *"))))
|
||||||
|
(:clone :args '((storage "AstStorage *"))))
|
||||||
|
|
||||||
(lcp:define-class expand-variable (logical-operator)
|
(lcp:define-class expand-variable (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -1189,7 +1217,8 @@ pulled.")
|
|||||||
friend class ExpandVariableCursor;
|
friend class ExpandVariableCursor;
|
||||||
friend class ExpandWeightedShortestPathCursor;
|
friend class ExpandWeightedShortestPathCursor;
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class construct-named-path (logical-operator)
|
(lcp:define-class construct-named-path (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -1223,7 +1252,8 @@ pulled.")
|
|||||||
input_ = input;
|
input_ = input;
|
||||||
}
|
}
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class filter (logical-operator)
|
(lcp:define-class filter (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -1273,7 +1303,8 @@ a boolean value.")
|
|||||||
const std::unique_ptr<Cursor> input_cursor_;
|
const std::unique_ptr<Cursor> input_cursor_;
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class produce (logical-operator)
|
(lcp:define-class produce (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -1329,7 +1360,8 @@ RETURN clause) the Produce's pull succeeds exactly once.")
|
|||||||
const std::unique_ptr<Cursor> input_cursor_;
|
const std::unique_ptr<Cursor> input_cursor_;
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class delete (logical-operator)
|
(lcp:define-class delete (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -1382,7 +1414,8 @@ Has a flag for using DETACH DELETE when deleting vertices.")
|
|||||||
const std::unique_ptr<Cursor> input_cursor_;
|
const std::unique_ptr<Cursor> input_cursor_;
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class set-property (logical-operator)
|
(lcp:define-class set-property (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -1438,7 +1471,8 @@ can be stored (a TypedValue that can be converted to PropertyValue).")
|
|||||||
const std::unique_ptr<Cursor> input_cursor_;
|
const std::unique_ptr<Cursor> input_cursor_;
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class set-properties (logical-operator)
|
(lcp:define-class set-properties (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -1511,7 +1545,8 @@ that the old properties are discarded and replaced with new ones.")
|
|||||||
void Set(TRecordAccessor &record, const TypedValue &rhs) const;
|
void Set(TRecordAccessor &record, const TypedValue &rhs) const;
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class set-labels (logical-operator)
|
(lcp:define-class set-labels (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -1558,7 +1593,8 @@ It does NOT remove labels that are already set on that Vertex.")
|
|||||||
const std::unique_ptr<Cursor> input_cursor_;
|
const std::unique_ptr<Cursor> input_cursor_;
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class remove-property (logical-operator)
|
(lcp:define-class remove-property (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -1606,7 +1642,8 @@ It does NOT remove labels that are already set on that Vertex.")
|
|||||||
const std::unique_ptr<Cursor> input_cursor_;
|
const std::unique_ptr<Cursor> input_cursor_;
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class remove-labels (logical-operator)
|
(lcp:define-class remove-labels (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -1653,7 +1690,8 @@ If a label does not exist on a Vertex, nothing happens.")
|
|||||||
const std::unique_ptr<Cursor> input_cursor_;
|
const std::unique_ptr<Cursor> input_cursor_;
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class edge-uniqueness-filter (logical-operator)
|
(lcp:define-class edge-uniqueness-filter (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -1712,7 +1750,8 @@ edge lists).")
|
|||||||
const std::unique_ptr<Cursor> input_cursor_;
|
const std::unique_ptr<Cursor> input_cursor_;
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class accumulate (logical-operator)
|
(lcp:define-class accumulate (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -1786,7 +1825,8 @@ has been cached will be reconstructed before Pull returns.
|
|||||||
bool pulled_all_input_{false};
|
bool pulled_all_input_{false};
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
#>cpp
|
#>cpp
|
||||||
/**
|
/**
|
||||||
@ -1881,7 +1921,8 @@ elements are in an undefined state after aggregation.")
|
|||||||
:load-args '((helper "query::plan::LogicalOperator::SlkLoadHelper *")))
|
:load-args '((helper "query::plan::LogicalOperator::SlkLoadHelper *")))
|
||||||
(:capnp
|
(:capnp
|
||||||
:save-args '((helper "LogicalOperator::SaveHelper *"))
|
:save-args '((helper "LogicalOperator::SaveHelper *"))
|
||||||
:load-args '((helper "LogicalOperator::LoadHelper *")))))
|
:load-args '((helper "LogicalOperator::LoadHelper *"))))
|
||||||
|
(:clone :args '((storage "AstStorage *"))))
|
||||||
#>cpp
|
#>cpp
|
||||||
Aggregate() = default;
|
Aggregate() = default;
|
||||||
Aggregate(const std::shared_ptr<LogicalOperator> &input,
|
Aggregate(const std::shared_ptr<LogicalOperator> &input,
|
||||||
@ -1981,7 +2022,8 @@ elements are in an undefined state after aggregation.")
|
|||||||
void EnsureOkForAvgSum(const TypedValue &value) const;
|
void EnsureOkForAvgSum(const TypedValue &value) const;
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class skip (logical-operator)
|
(lcp:define-class skip (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -2041,7 +2083,8 @@ operator's implementation does not expect this.")
|
|||||||
int skipped_{0};
|
int skipped_{0};
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class limit (logical-operator)
|
(lcp:define-class limit (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -2104,7 +2147,8 @@ input should be performed).")
|
|||||||
int pulled_{0};
|
int pulled_{0};
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class order-by (logical-operator)
|
(lcp:define-class order-by (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -2176,7 +2220,8 @@ are valid for usage after the OrderBy operator.")
|
|||||||
decltype(cache_.begin()) cache_it_ = cache_.begin();
|
decltype(cache_.begin()) cache_it_ = cache_.begin();
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class merge (logical-operator)
|
(lcp:define-class merge (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -2249,7 +2294,8 @@ documentation.")
|
|||||||
bool pull_input_{true};
|
bool pull_input_{true};
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class optional (logical-operator)
|
(lcp:define-class optional (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -2311,7 +2357,8 @@ and returns true, once.")
|
|||||||
bool pull_input_{true};
|
bool pull_input_{true};
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class unwind (logical-operator)
|
(lcp:define-class unwind (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -2368,7 +2415,8 @@ Input is optional (unwind can be the first clause in a query).")
|
|||||||
std::vector<TypedValue>::iterator input_value_it_ = input_value_.end();
|
std::vector<TypedValue>::iterator input_value_it_ = input_value_.end();
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class distinct (logical-operator)
|
(lcp:define-class distinct (logical-operator)
|
||||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -2427,7 +2475,8 @@ This implementation maintains input ordering.")
|
|||||||
seen_rows_;
|
seen_rows_;
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class union (logical-operator)
|
(lcp:define-class union (logical-operator)
|
||||||
((left-op "std::shared_ptr<LogicalOperator>" :scope :public
|
((left-op "std::shared_ptr<LogicalOperator>" :scope :public
|
||||||
@ -2488,7 +2537,8 @@ of symbols used by each of the inputs.")
|
|||||||
const std::unique_ptr<Cursor> left_cursor_, right_cursor_;
|
const std::unique_ptr<Cursor> left_cursor_, right_cursor_;
|
||||||
};
|
};
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
;; TODO: We should probably output this operator in regular planner, not just
|
;; TODO: We should probably output this operator in regular planner, not just
|
||||||
;; distributed planner.
|
;; distributed planner.
|
||||||
@ -2533,12 +2583,13 @@ of symbols used by each of the inputs.")
|
|||||||
std::shared_ptr<LogicalOperator> input() const override;
|
std::shared_ptr<LogicalOperator> input() const override;
|
||||||
void set_input(std::shared_ptr<LogicalOperator>) override;
|
void set_input(std::shared_ptr<LogicalOperator>) override;
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:define-class output-table (logical-operator)
|
(lcp:define-class output-table (logical-operator)
|
||||||
((output-symbols "std::vector<Symbol>" :scope :public :dont-save t)
|
((output-symbols "std::vector<Symbol>" :scope :public :dont-save t)
|
||||||
(callback "std::function<std::vector<std::vector<TypedValue>>(Frame *, ExecutionContext *)>"
|
(callback "std::function<std::vector<std::vector<TypedValue>>(Frame *, ExecutionContext *)>"
|
||||||
:scope :public :dont-save t))
|
:scope :public :dont-save t :clone :copy))
|
||||||
(:documentation "An operator that outputs a table, producing a single row on each pull")
|
(:documentation "An operator that outputs a table, producing a single row on each pull")
|
||||||
(:public
|
(:public
|
||||||
#>cpp
|
#>cpp
|
||||||
@ -2567,7 +2618,8 @@ of symbols used by each of the inputs.")
|
|||||||
std::shared_ptr<LogicalOperator> input() const override;
|
std::shared_ptr<LogicalOperator> input() const override;
|
||||||
void set_input(std::shared_ptr<LogicalOperator> input) override;
|
void set_input(std::shared_ptr<LogicalOperator> input) override;
|
||||||
cpp<#)
|
cpp<#)
|
||||||
(:serialize (:slk) (:capnp)))
|
(:serialize (:slk) (:capnp))
|
||||||
|
(:clone))
|
||||||
|
|
||||||
(lcp:pop-namespace) ;; plan
|
(lcp:pop-namespace) ;; plan
|
||||||
(lcp:pop-namespace) ;; query
|
(lcp:pop-namespace) ;; query
|
||||||
|
@ -127,6 +127,11 @@ class Yield : public query::plan::LogicalOperator {
|
|||||||
LOG(FATAL) << "Please go away, visitor!";
|
LOG(FATAL) << "Please go away, visitor!";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<LogicalOperator> Clone(
|
||||||
|
query::AstStorage *storage) const override {
|
||||||
|
LOG(FATAL) << "Don't clone Yield operator!";
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<query::plan::LogicalOperator> input_;
|
std::shared_ptr<query::plan::LogicalOperator> input_;
|
||||||
std::vector<query::Symbol> modified_symbols_;
|
std::vector<query::Symbol> modified_symbols_;
|
||||||
std::vector<std::vector<query::TypedValue>> values_;
|
std::vector<std::vector<query::TypedValue>> values_;
|
||||||
|
Loading…
Reference in New Issue
Block a user