QGIS API Documentation  3.25.0-Master (dec16ba68b)
qgssqliteexpressioncompiler.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgssqliteexpressioncompiler.cpp
3  -----------------------------------
4  begin : November 2015
5  copyright : (C) 2015 Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
17 
20 #include "qgsexpressionfunction.h"
21 #include "qgsexpressionnodeimpl.h"
22 #include "qgsexpression.h"
23 #include "qgssqliteutils.h"
24 
25 QgsSQLiteExpressionCompiler::QgsSQLiteExpressionCompiler( const QgsFields &fields, bool ignoreStaticNodes )
26  : QgsSqlExpressionCompiler( fields, QgsSqlExpressionCompiler::LikeIsCaseInsensitive | QgsSqlExpressionCompiler::IntegerDivisionResultsInInteger, ignoreStaticNodes )
27 {
28 }
29 
30 QgsSqlExpressionCompiler::Result QgsSQLiteExpressionCompiler::compileNode( const QgsExpressionNode *node, QString &result )
31 {
32  const QgsSqlExpressionCompiler::Result staticRes = replaceNodeByStaticCachedValueIfPossible( node, result );
33  if ( staticRes != Fail )
34  return staticRes;
35 
36  switch ( node->nodeType() )
37  {
39  {
40  const QgsExpressionNodeBinaryOperator *op = static_cast<const QgsExpressionNodeBinaryOperator *>( node );
41  switch ( op->op() )
42  {
45  return Fail; //not supported by SQLite
46 
49  {
50  QString opL, opR;
51 
52  if ( compileNode( op->opLeft(), opL ) != Complete ||
53  compileNode( op->opRight(), opR ) != Complete )
54  return Fail;
55 
56  result = QStringLiteral( "lower(%1) %2 lower(%3) ESCAPE '\\'" )
57  .arg( opL )
58  .arg( op->op() == QgsExpressionNodeBinaryOperator::boILike ? QStringLiteral( "LIKE" ) : QStringLiteral( "NOT LIKE" ) )
59  .arg( opR );
60 
61  return Complete;
62  }
63 
64  default:
65  //fallback to default handling
66  return QgsSqlExpressionCompiler::compileNode( node, result );
67  }
68  }
69 
71  {
72  const QgsExpressionNodeFunction *n = static_cast<const QgsExpressionNodeFunction *>( node );
74 
75  if ( fd->name() == QLatin1String( "make_datetime" ) || fd->name() == QLatin1String( "make_date" ) || fd->name() == QLatin1String( "make_time" ) )
76  {
77  const auto constList = n->args()->list();
78  for ( const QgsExpressionNode *ln : constList )
79  {
80  if ( ln->nodeType() != QgsExpressionNode::ntLiteral )
81  return Fail;
82  }
83  }
84 
85  return QgsSqlExpressionCompiler::compileNode( node, result );
86  }
87 
88  default:
89  break;
90  }
91 
92  return QgsSqlExpressionCompiler::compileNode( node, result );
93 }
94 
95 QString QgsSQLiteExpressionCompiler::quotedIdentifier( const QString &identifier )
96 {
97  return QgsSqliteUtils::quotedIdentifier( identifier );
98 }
99 
100 QString QgsSQLiteExpressionCompiler::quotedValue( const QVariant &value, bool &ok )
101 {
102  ok = true;
103  return QgsSqliteUtils::quotedValue( value );
104 }
105 
106 QString QgsSQLiteExpressionCompiler::sqlFunctionFromFunctionName( const QString &fnName ) const
107 {
108  static const QMap<QString, QString> FN_NAMES
109  {
110  { "abs", "abs" },
111  { "char", "char" },
112  { "coalesce", "coalesce" },
113  { "lower", "lower" },
114  { "round", "round" },
115  { "trim", "trim" },
116  { "upper", "upper" },
117  { "make_datetime", "" },
118  { "make_date", "" },
119  { "make_time", "" },
120  };
121 
122  return FN_NAMES.value( fnName, QString() );
123 }
124 
125 QStringList QgsSQLiteExpressionCompiler::sqlArgumentsFromFunctionName( const QString &fnName, const QStringList &fnArgs ) const
126 {
127  QStringList args( fnArgs );
128  if ( fnName == QLatin1String( "make_datetime" ) )
129  {
130  args = QStringList( QStringLiteral( "'%1-%2-%3T%4:%5:%6Z'" ).arg( args[0].rightJustified( 4, '0' ) )
131  .arg( args[1].rightJustified( 2, '0' ) )
132  .arg( args[2].rightJustified( 2, '0' ) )
133  .arg( args[3].rightJustified( 2, '0' ) )
134  .arg( args[4].rightJustified( 2, '0' ) )
135  .arg( args[5].rightJustified( 2, '0' ) ) );
136  }
137  else if ( fnName == QLatin1String( "make_date" ) )
138  {
139  args = QStringList( QStringLiteral( "'%1-%2-%3'" ).arg( args[0].rightJustified( 4, '0' ) )
140  .arg( args[1].rightJustified( 2, '0' ) )
141  .arg( args[2].rightJustified( 2, '0' ) ) );
142  }
143  else if ( fnName == QLatin1String( "make_time" ) )
144  {
145  args = QStringList( QStringLiteral( "'%1:%2:%3'" ).arg( args[0].rightJustified( 2, '0' ) )
146  .arg( args[1].rightJustified( 2, '0' ) )
147  .arg( args[2].rightJustified( 2, '0' ) ) );
148  }
149  return args;
150 }
151 
152 QString QgsSQLiteExpressionCompiler::castToReal( const QString &value ) const
153 {
154  return QStringLiteral( "CAST((%1) AS REAL)" ).arg( value );
155 }
156 
157 QString QgsSQLiteExpressionCompiler::castToInt( const QString &value ) const
158 {
159  return QStringLiteral( "CAST((%1) AS INTEGER)" ).arg( value );
160 }
161 
162 QString QgsSQLiteExpressionCompiler::castToText( const QString &value ) const
163 {
164  return QStringLiteral( "CAST((%1) AS TEXT)" ).arg( value );
165 }
166 
A abstract base class for defining QgsExpression functions.
QString name() const
The name of the function.
A binary expression operator, which operates on two values.
QgsExpressionNodeBinaryOperator::BinaryOperator op() const
Returns the binary operator.
QgsExpressionNode * opRight() const
Returns the node to the right of the operator.
QgsExpressionNode * opLeft() const
Returns the node to the left of the operator.
An expression node for expression functions.
int fnIndex() const
Returns the index of the node's function.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
Abstract base class for all nodes that can appear in an expression.
virtual QgsExpressionNode::NodeType nodeType() const =0
Gets the type of this node.
static const QList< QgsExpressionFunction * > & Functions()
Container of fields for a vector layer.
Definition: qgsfields.h:45
Generic expression compiler for translation to provider specific SQL WHERE clauses.
virtual Result compileNode(const QgsExpressionNode *node, QString &str)
Compiles an expression node and returns the result of the compilation.
Result
Possible results from expression compilation.
static QString quotedIdentifier(const QString &identifier)
Returns a properly quoted version of identifier.
static QString quotedValue(const QVariant &value)
Returns a properly quoted and escaped version of value for use in SQL strings.