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-11-21 22:18:42 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             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "gdal_unit_test.h"
      14             : 
      15             : #include "ogr_core.h"
      16             : #include "ogr_geometry.h"
      17             : #include "ogr_swq.h"
      18             : 
      19             : #include "gtest_include.h"
      20             : 
      21             : namespace
      22             : {
      23             : 
      24             : struct test_ogr_swq : public ::testing::Test
      25             : {
      26             : };
      27             : 
      28           4 : TEST_F(test_ogr_swq, basic)
      29             : {
      30             :     std::vector<swq_expr_node> nodes = {
      31             :         swq_expr_node(),
      32             :         swq_expr_node(1),
      33             :         swq_expr_node(2),
      34             :         swq_expr_node(1.5),
      35             :         swq_expr_node(2.5),
      36             :         swq_expr_node(static_cast<GIntBig>(4000) * 1000 * 1000),
      37             :         swq_expr_node(static_cast<GIntBig>(4000) * 1000 * 1000 + 1),
      38             :         swq_expr_node(static_cast<const char *>(nullptr)),
      39             :         swq_expr_node("a"),
      40             :         swq_expr_node("b"),
      41             :         swq_expr_node(SWQ_OR),
      42             :         swq_expr_node(SWQ_NOT),
      43             :         swq_expr_node(static_cast<OGRGeometry *>(nullptr)),
      44           1 :         swq_expr_node(std::make_unique<OGRPoint>(1, 2).get()),
      45           2 :         swq_expr_node(std::make_unique<OGRPoint>(1, 3).get()),
      46          21 :     };
      47             :     {
      48           2 :         auto node = swq_expr_node(SWQ_NOT);
      49           1 :         node.PushSubExpression(new swq_expr_node(1));
      50           1 :         nodes.emplace_back(node);
      51             :     }
      52             :     {
      53           2 :         auto node = swq_expr_node(SWQ_NOT);
      54           1 :         node.PushSubExpression(new swq_expr_node(2));
      55           1 :         nodes.emplace_back(node);
      56             :     }
      57             :     {
      58           2 :         auto node = swq_expr_node();
      59           1 :         node.eNodeType = SNT_COLUMN;
      60           1 :         node.field_index = 0;
      61           1 :         node.table_index = 0;
      62           1 :         nodes.emplace_back(node);
      63             :     }
      64             :     {
      65           2 :         auto node = swq_expr_node();
      66           1 :         node.eNodeType = SNT_COLUMN;
      67           1 :         node.field_index = 0;
      68           1 :         node.table_index = 0;
      69           1 :         node.table_name = CPLStrdup("foo");
      70           1 :         nodes.emplace_back(node);
      71             :     }
      72             :     {
      73           2 :         auto node = swq_expr_node();
      74           1 :         node.eNodeType = SNT_COLUMN;
      75           1 :         node.field_index = 0;
      76           1 :         node.table_index = 0;
      77           1 :         node.table_name = CPLStrdup("bar");
      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 = 1;
      84           1 :         node.table_index = 0;
      85           1 :         nodes.emplace_back(node);
      86             :     }
      87             :     {
      88           2 :         auto node = swq_expr_node();
      89           1 :         node.eNodeType = SNT_COLUMN;
      90           1 :         node.field_index = 0;
      91           1 :         node.table_index = 1;
      92           1 :         nodes.emplace_back(node);
      93             :     }
      94             : 
      95          23 :     for (const auto &node1 : nodes)
      96             :     {
      97         506 :         for (const auto &node2 : nodes)
      98             :         {
      99         484 :             if (&node1 == &node2)
     100             :             {
     101          22 :                 EXPECT_TRUE(node1 == node1);
     102          22 :                 EXPECT_TRUE(node1 == swq_expr_node(node1));
     103             :             }
     104             :             else
     105             :             {
     106         462 :                 EXPECT_FALSE(node1 == node2);
     107         462 :                 EXPECT_FALSE(node2 == node1);
     108             : 
     109             :                 {
     110         924 :                     swq_expr_node copy(node1);
     111         462 :                     copy = node2;
     112         462 :                     EXPECT_TRUE(copy == node2);
     113             :                 }
     114             :                 {
     115         924 :                     swq_expr_node copy1(node1);
     116         924 :                     swq_expr_node copy2(node2);
     117         462 :                     copy1 = std::move(copy2);
     118         462 :                     EXPECT_TRUE(copy1 == node2);
     119             :                 }
     120             :             }
     121             :         }
     122             :     }
     123           1 : }
     124             : 
     125             : class PushNotOperationDownToStackFixture
     126             :     : public test_ogr_swq,
     127             :       public ::testing::WithParamInterface<
     128             :           std::tuple<const char *, const char *>>
     129             : {
     130             :   public:
     131           1 :     static std::vector<std::tuple<const char *, const char *>> GetTupleValues()
     132             :     {
     133             :         return {
     134             :             std::make_tuple("NOT(1 = 2)", "1 <> 2"),
     135             :             std::make_tuple("NOT(1 <> 2)", "1 = 2"),
     136             :             std::make_tuple("NOT(1 >= 2)", "1 < 2"),
     137             :             std::make_tuple("NOT(1 > 2)", "1 <= 2"),
     138             :             std::make_tuple("NOT(1 <= 2)", "1 > 2"),
     139             :             std::make_tuple("NOT(1 < 2)", "1 >= 2"),
     140             :             std::make_tuple("NOT(NOT(1))", "1"),
     141             :             std::make_tuple("NOT(1 AND 2)", "(NOT 1) OR (NOT 2)"),
     142             :             std::make_tuple("NOT(1 OR 2)", "(NOT 1) AND (NOT 2)"),
     143             :             std::make_tuple("3 AND NOT(1 OR 2)", "3 AND ((NOT 1) AND (NOT 2))"),
     144             :             std::make_tuple("NOT(NOT(1 = 2) OR 2)", "(1 = 2) AND (NOT 2)"),
     145             :             std::make_tuple("1", "1"),
     146           1 :         };
     147             :     }
     148             : };
     149             : 
     150          25 : TEST_P(PushNotOperationDownToStackFixture, test)
     151             : {
     152          12 :     const char *pszInput = std::get<0>(GetParam());
     153          12 :     const char *pszExpected = std::get<1>(GetParam());
     154             : 
     155          12 :     swq_expr_node *poNode = nullptr;
     156          12 :     swq_expr_compile(pszInput, 0, nullptr, nullptr, true, nullptr, &poNode);
     157          12 :     ASSERT_TRUE(poNode);
     158          12 :     poNode->PushNotOperationDownToStack();
     159          12 :     char *pszStr = poNode->Unparse(nullptr, '"');
     160          24 :     std::string osStr = pszStr ? pszStr : "";
     161          12 :     CPLFree(pszStr);
     162          12 :     EXPECT_STREQ(osStr.c_str(), pszExpected);
     163          12 :     delete poNode;
     164             : }
     165             : 
     166          26 : INSTANTIATE_TEST_SUITE_P(
     167             :     test_ogr_swq, PushNotOperationDownToStackFixture,
     168             :     ::testing::ValuesIn(PushNotOperationDownToStackFixture::GetTupleValues()),
     169             :     [](const ::testing::TestParamInfo<
     170             :         PushNotOperationDownToStackFixture::ParamType> &l_info)
     171             :     {
     172             :         CPLString osStr = std::get<0>(l_info.param);
     173             :         osStr.replaceAll(' ', '_');
     174             :         osStr.replaceAll('(', '_');
     175             :         osStr.replaceAll(')', '_');
     176             :         osStr.replaceAll("<>", "NE");
     177             :         osStr.replaceAll(">=", "GE");
     178             :         osStr.replaceAll(">", "GT");
     179             :         osStr.replaceAll("<=", "LE");
     180             :         osStr.replaceAll("<", "LT");
     181             :         osStr.replaceAll('=', "EQ");
     182             :         osStr.replaceAll("__", '_');
     183             :         if (osStr.back() == '_')
     184             :             osStr.pop_back();
     185             :         return osStr;
     186             :     });
     187             : 
     188           4 : TEST_F(test_ogr_swq, select_unparse)
     189             : {
     190             :     {
     191           2 :         swq_select select;
     192           1 :         const char *pszSQL = "SELECT a FROM FOO";
     193           1 :         EXPECT_EQ(select.preparse(pszSQL), CE_None);
     194           1 :         char *ret = select.Unparse();
     195           1 :         EXPECT_STREQ(ret, pszSQL);
     196           1 :         CPLFree(ret);
     197             :     }
     198             :     {
     199           2 :         swq_select select;
     200           1 :         const char *pszSQL =
     201             :             "SELECT DISTINCT a, \"a b\" AS renamed, AVG(x.a) AS avg, MIN(a), "
     202             :             "MAX(\"a b\"), SUM(a), AVG(a), COUNT(a), COUNT(DISTINCT a), "
     203             :             "STDDEV_POP(a), STDDEV_SAMP(a) "
     204             :             "FROM 'foo'.\"FOO BAR\" AS x "
     205             :             "JOIN 'bar'.BAR AS y ON FOO.x = BAR.y "
     206             :             "WHERE 1 ORDER BY a, \"a b\" DESC "
     207             :             "LIMIT 1 OFFSET 2";
     208           1 :         EXPECT_EQ(select.preparse(pszSQL), CE_None);
     209           1 :         char *ret = select.Unparse();
     210           1 :         EXPECT_STREQ(ret, pszSQL);
     211           1 :         CPLFree(ret);
     212             :     }
     213           1 : }
     214             : 
     215             : }  // namespace

Generated by: LCOV version 1.14