// Copyright 2022 Memgraph Ltd. // // Use of this software is governed by the Business Source License // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // License, and you may not use this file except in compliance with the Business Source License. // // As of the Change Date specified in that file, in accordance with // the Business Source License, use of this software will be governed // by the Apache License, Version 2.0, included in the file // licenses/APL.txt. #include #include #include #include "query/frontend/ast/ast.hpp" #include "query/frontend/ast/pretty_print.hpp" #include "query_common.hpp" #include "utils/string.hpp" using namespace memgraph::query; using memgraph::query::test_common::ToString; using testing::ElementsAre; using testing::UnorderedElementsAre; namespace { struct ExpressionPrettyPrinterTest : public ::testing::Test { memgraph::storage::Storage db; memgraph::storage::Storage::Accessor storage_dba{db.Access()}; memgraph::query::DbAccessor dba{&storage_dba}; AstStorage storage; }; TEST_F(ExpressionPrettyPrinterTest, Literals) { // 1 EXPECT_EQ(ToString(LITERAL(1)), "1"); // "hello" EXPECT_EQ(ToString(LITERAL("hello")), "\"hello\""); // null EXPECT_EQ(ToString(LITERAL(TypedValue())), "null"); // true EXPECT_EQ(ToString(LITERAL(true)), "true"); // false EXPECT_EQ(ToString(LITERAL(false)), "false"); // [1 null "hello"] std::vector values{memgraph::storage::PropertyValue(1), memgraph::storage::PropertyValue(), memgraph::storage::PropertyValue("hello")}; EXPECT_EQ(ToString(LITERAL(memgraph::storage::PropertyValue(values))), "[1, null, \"hello\"]"); // {hello: 1, there: 2} std::map map{{"hello", memgraph::storage::PropertyValue(1)}, {"there", memgraph::storage::PropertyValue(2)}}; EXPECT_EQ(ToString(LITERAL(memgraph::storage::PropertyValue(map))), "{\"hello\": 1, \"there\": 2}"); std::vector tt_vec{ memgraph::storage::PropertyValue(memgraph::storage::TemporalData(memgraph::storage::TemporalType::Duration, 1)), memgraph::storage::PropertyValue(memgraph::storage::TemporalData(memgraph::storage::TemporalType::Duration, -2)), memgraph::storage::PropertyValue(memgraph::storage::TemporalData(memgraph::storage::TemporalType::LocalTime, 2)), memgraph::storage::PropertyValue( memgraph::storage::TemporalData(memgraph::storage::TemporalType::LocalDateTime, 3)), memgraph::storage::PropertyValue(memgraph::storage::TemporalData(memgraph::storage::TemporalType::Date, 4))}; EXPECT_EQ(ToString(LITERAL(memgraph::storage::PropertyValue(tt_vec))), "[DURATION(\"P0DT0H0M0.000001S\"), DURATION(\"P0DT0H0M-0.000002S\"), LOCALTIME(\"00:00:00.000002\"), " "LOCALDATETIME(\"1970-01-01T00:00:00.000003\"), DATE(\"1970-01-01\")]"); } TEST_F(ExpressionPrettyPrinterTest, Identifiers) { // x EXPECT_EQ(ToString(IDENT("x")), "(Identifier \"x\")"); // hello_there EXPECT_EQ(ToString(IDENT("hello_there")), "(Identifier \"hello_there\")"); } TEST_F(ExpressionPrettyPrinterTest, Reducing) { // all(x in list where x.prop = 42) auto prop = dba.NameToProperty("prop"); EXPECT_EQ(ToString(ALL("x", LITERAL(std::vector{}), WHERE(EQ(PROPERTY_LOOKUP("x", prop), LITERAL(42))))), "(All (Identifier \"x\") [] (== (PropertyLookup " "(Identifier \"x\") \"prop\") 42))"); // reduce(accumulator = initial_value, variable IN list | expression) EXPECT_EQ(ToString(REDUCE("accumulator", IDENT("initial_value"), "variable", IDENT("list"), IDENT("expression"))), "(Reduce (Identifier \"accumulator\") (Identifier \"initial_value\") " "(Identifier \"variable\") (Identifier \"list\") (Identifier " "\"expression\"))"); } TEST_F(ExpressionPrettyPrinterTest, UnaryOperators) { // not(false) EXPECT_EQ(ToString(NOT(LITERAL(false))), "(Not false)"); // +1 EXPECT_EQ(ToString(UPLUS(LITERAL(1))), "(+ 1)"); // -1 EXPECT_EQ(ToString(UMINUS(LITERAL(1))), "(- 1)"); // null IS NULL EXPECT_EQ(ToString(IS_NULL(LITERAL(TypedValue()))), "(IsNull null)"); } TEST_F(ExpressionPrettyPrinterTest, BinaryOperators) { // and(null, 5) EXPECT_EQ(ToString(AND(LITERAL(TypedValue()), LITERAL(5))), "(And null 5)"); // or(5, {hello: "there"}["hello"]) EXPECT_EQ( ToString(OR(LITERAL(5), PROPERTY_LOOKUP(MAP(std::make_pair(storage.GetPropertyIx("hello"), LITERAL("there"))), "hello"))), "(Or 5 (PropertyLookup {\"hello\": \"there\"} \"hello\"))"); // and(coalesce(null, 1), {hello: "there"}) EXPECT_EQ(ToString(AND(COALESCE(LITERAL(TypedValue()), LITERAL(1)), MAP(std::make_pair(storage.GetPropertyIx("hello"), LITERAL("there"))))), "(And (Coalesce [null, 1]) {\"hello\": \"there\"})"); } TEST_F(ExpressionPrettyPrinterTest, Coalesce) { // coalesce() EXPECT_EQ(ToString(COALESCE()), "(Coalesce [])"); // coalesce(null, null) EXPECT_EQ(ToString(COALESCE(LITERAL(TypedValue()), LITERAL(TypedValue()))), "(Coalesce [null, null])"); // coalesce(null, 2, 3) EXPECT_EQ(ToString(COALESCE(LITERAL(TypedValue()), LITERAL(2), LITERAL(3))), "(Coalesce [null, 2, 3])"); // coalesce(null, 2, assert(false), 3) EXPECT_EQ(ToString(COALESCE(LITERAL(TypedValue()), LITERAL(2), FN("ASSERT", LITERAL(false)), LITERAL(3))), "(Coalesce [null, 2, (Function \"ASSERT\" [false]), 3])"); // coalesce(null, assert(false)) EXPECT_EQ(ToString(COALESCE(LITERAL(TypedValue()), FN("ASSERT", LITERAL(false)))), "(Coalesce [null, (Function \"ASSERT\" [false])])"); // coalesce([null, null]) EXPECT_EQ(ToString(COALESCE(LITERAL(TypedValue(std::vector{TypedValue(), TypedValue()})))), "(Coalesce [[null, null]])"); } TEST_F(ExpressionPrettyPrinterTest, ParameterLookup) { // and($hello, $there) EXPECT_EQ(ToString(AND(PARAMETER_LOOKUP(1), PARAMETER_LOOKUP(2))), "(And (ParameterLookup 1) (ParameterLookup 2))"); } TEST_F(ExpressionPrettyPrinterTest, PropertyLookup) { // {hello: "there"}["hello"] EXPECT_EQ(ToString(PROPERTY_LOOKUP(MAP(std::make_pair(storage.GetPropertyIx("hello"), LITERAL("there"))), "hello")), "(PropertyLookup {\"hello\": \"there\"} \"hello\")"); } TEST_F(ExpressionPrettyPrinterTest, NamedExpression) { // n AS 1 EXPECT_EQ(ToString(NEXPR("n", LITERAL(1))), "(NamedExpression \"n\" 1)"); } } // namespace