LCOV - code coverage report
Current view: top level - autotest/cpp - test_ogr_swq.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 81 81 100.0 %
Date: 2024-05-14 13:00:50 Functions: 15 15 100.0 %

          Line data    Source code
       1             : ///////////////////////////////////////////////////////////////////////////////
       2             : //
       3             : // Project:  C++ Test Suite for GDAL/OGR
       4             : // Purpose:  Test SWQ (SQL WHERE Query) features.
       5             : // Author:   Even Rouault <even.rouault at spatialys.com>
       6             : //
       7             : ///////////////////////////////////////////////////////////////////////////////
       8             : // Copyright (c) 2023, Even Rouault <even.rouault at spatialys.com>
       9             : /*
      10             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  ****************************************************************************/
      28             : 
      29             : #include "gdal_unit_test.h"
      30             : 
      31             : #include "ogr_core.h"
      32             : #include "ogr_geometry.h"
      33             : #include "ogr_swq.h"
      34             : 
      35             : #include "gtest_include.h"
      36             : 
      37             : namespace
      38             : {
      39             : 
      40             : struct test_ogr_swq : public ::testing::Test
      41             : {
      42             : };
      43             : 
      44           4 : TEST_F(test_ogr_swq, basic)
      45             : {
      46             :     std::vector<swq_expr_node> nodes = {
      47             :         swq_expr_node(),
      48             :         swq_expr_node(1),
      49             :         swq_expr_node(2),
      50             :         swq_expr_node(1.5),
      51             :         swq_expr_node(2.5),
      52             :         swq_expr_node(static_cast<GIntBig>(4000) * 1000 * 1000),
      53             :         swq_expr_node(static_cast<GIntBig>(4000) * 1000 * 1000 + 1),
      54             :         swq_expr_node(static_cast<const char *>(nullptr)),
      55             :         swq_expr_node("a"),
      56             :         swq_expr_node("b"),
      57             :         swq_expr_node(SWQ_OR),
      58             :         swq_expr_node(SWQ_NOT),
      59             :         swq_expr_node(static_cast<OGRGeometry *>(nullptr)),
      60           1 :         swq_expr_node(std::make_unique<OGRPoint>(1, 2).get()),
      61           2 :         swq_expr_node(std::make_unique<OGRPoint>(1, 3).get()),
      62          21 :     };
      63             :     {
      64           2 :         auto node = swq_expr_node(SWQ_NOT);
      65           1 :         node.PushSubExpression(new swq_expr_node(1));
      66           1 :         nodes.emplace_back(node);
      67             :     }
      68             :     {
      69           2 :         auto node = swq_expr_node(SWQ_NOT);
      70           1 :         node.PushSubExpression(new swq_expr_node(2));
      71           1 :         nodes.emplace_back(node);
      72             :     }
      73             :     {
      74           2 :         auto node = swq_expr_node();
      75           1 :         node.eNodeType = SNT_COLUMN;
      76           1 :         node.field_index = 0;
      77           1 :         node.table_index = 0;
      78           1 :         nodes.emplace_back(node);
      79             :     }
      80             :     {
      81           2 :         auto node = swq_expr_node();
      82           1 :         node.eNodeType = SNT_COLUMN;
      83           1 :         node.field_index = 0;
      84           1 :         node.table_index = 0;
      85           1 :         node.table_name = CPLStrdup("foo");
      86           1 :         nodes.emplace_back(node);
      87             :     }
      88             :     {
      89           2 :         auto node = swq_expr_node();
      90           1 :         node.eNodeType = SNT_COLUMN;
      91           1 :         node.field_index = 0;
      92           1 :         node.table_index = 0;
      93           1 :         node.table_name = CPLStrdup("bar");
      94           1 :         nodes.emplace_back(node);
      95             :     }
      96             :     {
      97           2 :         auto node = swq_expr_node();
      98           1 :         node.eNodeType = SNT_COLUMN;
      99           1 :         node.field_index = 1;
     100           1 :         node.table_index = 0;
     101           1 :         nodes.emplace_back(node);
     102             :     }
     103             :     {
     104           2 :         auto node = swq_expr_node();
     105           1 :         node.eNodeType = SNT_COLUMN;
     106           1 :         node.field_index = 0;
     107           1 :         node.table_index = 1;
     108           1 :         nodes.emplace_back(node);
     109             :     }
     110             : 
     111          23 :     for (const auto &node1 : nodes)
     112             :     {
     113         506 :         for (const auto &node2 : nodes)
     114             :         {
     115         484 :             if (&node1 == &node2)
     116             :             {
     117          22 :                 EXPECT_TRUE(node1 == node1);
     118          22 :                 EXPECT_TRUE(node1 == swq_expr_node(node1));
     119             :             }
     120             :             else
     121             :             {
     122         462 :                 EXPECT_FALSE(node1 == node2);
     123         462 :                 EXPECT_FALSE(node2 == node1);
     124             : 
     125             :                 {
     126         924 :                     swq_expr_node copy(node1);
     127         462 :                     copy = node2;
     128         462 :                     EXPECT_TRUE(copy == node2);
     129             :                 }
     130             :                 {
     131         924 :                     swq_expr_node copy1(node1);
     132         924 :                     swq_expr_node copy2(node2);
     133         462 :                     copy1 = std::move(copy2);
     134         462 :                     EXPECT_TRUE(copy1 == node2);
     135             :                 }
     136             :             }
     137             :         }
     138             :     }
     139           1 : }
     140             : 
     141             : class PushNotOperationDownToStackFixture
     142             :     : public test_ogr_swq,
     143             :       public ::testing::WithParamInterface<
     144             :           std::tuple<const char *, const char *>>
     145             : {
     146             :   public:
     147           1 :     static std::vector<std::tuple<const char *, const char *>> GetTupleValues()
     148             :     {
     149             :         return {
     150             :             std::make_tuple("NOT(1 = 2)", "1 <> 2"),
     151             :             std::make_tuple("NOT(1 <> 2)", "1 = 2"),
     152             :             std::make_tuple("NOT(1 >= 2)", "1 < 2"),
     153             :             std::make_tuple("NOT(1 > 2)", "1 <= 2"),
     154             :             std::make_tuple("NOT(1 <= 2)", "1 > 2"),
     155             :             std::make_tuple("NOT(1 < 2)", "1 >= 2"),
     156             :             std::make_tuple("NOT(NOT(1))", "1"),
     157             :             std::make_tuple("NOT(1 AND 2)", "(NOT (1)) OR (NOT (2))"),
     158             :             std::make_tuple("NOT(1 OR 2)", "(NOT (1)) AND (NOT (2))"),
     159             :             std::make_tuple("3 AND NOT(1 OR 2)",
     160             :                             "3 AND ((NOT (1)) AND (NOT (2)))"),
     161             :             std::make_tuple("NOT(NOT(1 = 2) OR 2)", "(1 = 2) AND (NOT (2))"),
     162             :             std::make_tuple("1", "1"),
     163           1 :         };
     164             :     }
     165             : };
     166             : 
     167          25 : TEST_P(PushNotOperationDownToStackFixture, test)
     168             : {
     169          12 :     const char *pszInput = std::get<0>(GetParam());
     170          12 :     const char *pszExpected = std::get<1>(GetParam());
     171             : 
     172          12 :     swq_expr_node *poNode = nullptr;
     173          12 :     swq_expr_compile(pszInput, 0, nullptr, nullptr, true, nullptr, &poNode);
     174          12 :     ASSERT_TRUE(poNode);
     175          12 :     poNode->PushNotOperationDownToStack();
     176          12 :     char *pszStr = poNode->Unparse(nullptr, '"');
     177          24 :     std::string osStr = pszStr ? pszStr : "";
     178          12 :     CPLFree(pszStr);
     179          12 :     EXPECT_STREQ(osStr.c_str(), pszExpected);
     180          12 :     delete poNode;
     181             : }
     182             : 
     183          26 : INSTANTIATE_TEST_SUITE_P(
     184             :     test_ogr_swq, PushNotOperationDownToStackFixture,
     185             :     ::testing::ValuesIn(PushNotOperationDownToStackFixture::GetTupleValues()),
     186             :     [](const ::testing::TestParamInfo<
     187             :         PushNotOperationDownToStackFixture::ParamType> &l_info)
     188             :     {
     189             :         CPLString osStr = std::get<0>(l_info.param);
     190             :         osStr.replaceAll(' ', '_');
     191             :         osStr.replaceAll('(', '_');
     192             :         osStr.replaceAll(')', '_');
     193             :         osStr.replaceAll("<>", "NE");
     194             :         osStr.replaceAll(">=", "GE");
     195             :         osStr.replaceAll(">", "GT");
     196             :         osStr.replaceAll("<=", "LE");
     197             :         osStr.replaceAll("<", "LT");
     198             :         osStr.replaceAll('=', "EQ");
     199             :         osStr.replaceAll("__", '_');
     200             :         if (osStr.back() == '_')
     201             :             osStr.pop_back();
     202             :         return osStr;
     203             :     });
     204             : 
     205           4 : TEST_F(test_ogr_swq, select_unparse)
     206             : {
     207             :     {
     208           2 :         swq_select select;
     209           1 :         const char *pszSQL = "SELECT a FROM FOO";
     210           1 :         EXPECT_EQ(select.preparse(pszSQL), CE_None);
     211           1 :         char *ret = select.Unparse();
     212           1 :         EXPECT_STREQ(ret, pszSQL);
     213           1 :         CPLFree(ret);
     214             :     }
     215             :     {
     216           2 :         swq_select select;
     217           1 :         const char *pszSQL =
     218             :             "SELECT DISTINCT a, \"a b\" AS renamed, AVG(x.a) AS avg, MIN(a), "
     219             :             "MAX(\"a b\"), SUM(a), AVG(a), COUNT(a), COUNT(DISTINCT a) "
     220             :             "FROM 'foo'.\"FOO BAR\" AS x "
     221             :             "JOIN 'bar'.BAR AS y ON FOO.x = BAR.y "
     222             :             "WHERE 1 ORDER BY a, \"a b\" DESC "
     223             :             "LIMIT 1 OFFSET 2";
     224           1 :         EXPECT_EQ(select.preparse(pszSQL), CE_None);
     225           1 :         char *ret = select.Unparse();
     226           1 :         EXPECT_STREQ(ret, pszSQL);
     227           1 :         CPLFree(ret);
     228             :     }
     229           1 : }
     230             : 
     231             : }  // namespace

Generated by: LCOV version 1.14