1 /******************************************************************************
2  *
3  * Component: OGR SQL Engine
4  * Purpose: Implementation of the swq_op_registrar class used to
5  *          represent operations possible in an SQL expression.
6  * Author: Frank Warmerdam <warmerdam@pobox.com>
7  *
8  ******************************************************************************
9  * Copyright (C) 2010 Frank Warmerdam <warmerdam@pobox.com>
10  * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.com>
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a
13  * copy of this software and associated documentation files (the "Software"),
14  * to deal in the Software without restriction, including without limitation
15  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16  * and/or sell copies of the Software, and to permit persons to whom the
17  * Software is furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included
20  * in all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28  * DEALINGS IN THE SOFTWARE.
29  ****************************************************************************/
30 
31 #include "cpl_port.h"
32 #include "ogr_swq.h"
33 
34 #include <cstddef>
35 
36 #include "cpl_conv.h"
37 #include "cpl_error.h"
38 
39 CPL_CVSID("$Id: swq_op_registrar.cpp ffd62ee1bdeed41a9301102c35b3c0eb30a36dc2 2019-11-28 16:56:51 +0100 Even Rouault $")
40 
41 //! @cond Doxygen_Suppress
42 static swq_field_type SWQColumnFuncChecker(
43     swq_expr_node *poNode, int bAllowMismatchTypeOnFieldComparison );
44 
45 static const swq_operation swq_apsOperations[] =
46 {
47     { "OR", SWQ_OR, SWQGeneralEvaluator, SWQGeneralChecker },
48     { "AND", SWQ_AND, SWQGeneralEvaluator, SWQGeneralChecker },
49     { "NOT", SWQ_NOT , SWQGeneralEvaluator, SWQGeneralChecker },
50     { "=", SWQ_EQ , SWQGeneralEvaluator, SWQGeneralChecker },
51     { "<>", SWQ_NE , SWQGeneralEvaluator, SWQGeneralChecker },
52     { ">=", SWQ_GE , SWQGeneralEvaluator, SWQGeneralChecker },
53     { "<=", SWQ_LE , SWQGeneralEvaluator, SWQGeneralChecker },
54     { "<", SWQ_LT , SWQGeneralEvaluator, SWQGeneralChecker },
55     { ">", SWQ_GT , SWQGeneralEvaluator, SWQGeneralChecker },
56     { "LIKE", SWQ_LIKE , SWQGeneralEvaluator, SWQGeneralChecker },
57     { "ILIKE", SWQ_ILIKE , SWQGeneralEvaluator, SWQGeneralChecker },
58     { "IS NULL", SWQ_ISNULL , SWQGeneralEvaluator, SWQGeneralChecker },
59     { "IN", SWQ_IN , SWQGeneralEvaluator, SWQGeneralChecker },
60     { "BETWEEN", SWQ_BETWEEN , SWQGeneralEvaluator, SWQGeneralChecker },
61     { "+", SWQ_ADD , SWQGeneralEvaluator, SWQGeneralChecker },
62     { "-", SWQ_SUBTRACT , SWQGeneralEvaluator, SWQGeneralChecker },
63     { "*", SWQ_MULTIPLY , SWQGeneralEvaluator, SWQGeneralChecker },
64     { "/", SWQ_DIVIDE , SWQGeneralEvaluator, SWQGeneralChecker },
65     { "%", SWQ_MODULUS , SWQGeneralEvaluator, SWQGeneralChecker },
66     { "CONCAT", SWQ_CONCAT , SWQGeneralEvaluator, SWQGeneralChecker },
67     { "SUBSTR", SWQ_SUBSTR , SWQGeneralEvaluator, SWQGeneralChecker },
68     { "HSTORE_GET_VALUE", SWQ_HSTORE_GET_VALUE , SWQGeneralEvaluator,
69         SWQGeneralChecker },
70 
71     { "AVG", SWQ_AVG, SWQGeneralEvaluator, SWQColumnFuncChecker },
72     { "MIN", SWQ_MIN, SWQGeneralEvaluator, SWQColumnFuncChecker },
73     { "MAX", SWQ_MAX, SWQGeneralEvaluator, SWQColumnFuncChecker },
74     { "COUNT", SWQ_COUNT, SWQGeneralEvaluator, SWQColumnFuncChecker },
75     { "SUM", SWQ_SUM, SWQGeneralEvaluator, SWQColumnFuncChecker },
76 
77     { "CAST", SWQ_CAST, SWQCastEvaluator, SWQCastChecker }
78 };
79 
80 /************************************************************************/
81 /*                            GetOperator()                             */
82 /************************************************************************/
83 
GetOperator(const char * pszName)84 const swq_operation *swq_op_registrar::GetOperator( const char *pszName )
85 
86 {
87     for( const auto& op: swq_apsOperations )
88     {
89         if( EQUAL(pszName, op.pszName) )
90             return &op;
91     }
92 
93     return nullptr;
94 }
95 
96 /************************************************************************/
97 /*                            GetOperator()                             */
98 /************************************************************************/
99 
GetOperator(swq_op eOperator)100 const swq_operation *swq_op_registrar::GetOperator( swq_op eOperator )
101 
102 {
103     for( const auto& op: swq_apsOperations )
104     {
105         if( eOperator == op.eOperation )
106             return &op;
107     }
108 
109     return nullptr;
110 }
111 
112 /************************************************************************/
113 /*                        SWQColumnFuncChecker()                        */
114 /*                                                                      */
115 /*      Column summary functions are not legal in any context except    */
116 /*      as a root operator on column definitions.  They are removed     */
117 /*      from this tree before checking so we just need to issue an      */
118 /*      error if they are used in any other context.                    */
119 /************************************************************************/
120 
SWQColumnFuncChecker(swq_expr_node * poNode,int)121 static swq_field_type SWQColumnFuncChecker(
122     swq_expr_node *poNode, int /* bAllowMismatchTypeOnFieldComparison */ )
123 {
124     const swq_operation *poOp =
125         swq_op_registrar::GetOperator(static_cast<swq_op>(poNode->nOperation));
126     CPLError( CE_Failure, CPLE_AppDefined,
127               "Column Summary Function '%s' found in an inappropriate context.",
128               poOp != nullptr ? poOp->pszName : "" );
129     return SWQ_ERROR;
130 }
131 //! @endcond
132