Branch data Line data Source code
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 : :
16 : : ///@cond PRIVATE
17 : :
18 : : #include "qgssqliteexpressioncompiler.h"
19 : : #include "qgssqlexpressioncompiler.h"
20 : : #include "qgsexpressionfunction.h"
21 : : #include "qgsexpressionnodeimpl.h"
22 : : #include "qgsexpression.h"
23 : : #include "qgssqliteutils.h"
24 : :
25 : 0 : QgsSQLiteExpressionCompiler::QgsSQLiteExpressionCompiler( const QgsFields &fields, bool ignoreStaticNodes )
26 : 0 : : QgsSqlExpressionCompiler( fields, QgsSqlExpressionCompiler::LikeIsCaseInsensitive | QgsSqlExpressionCompiler::IntegerDivisionResultsInInteger, ignoreStaticNodes )
27 : 0 : {
28 : 0 : }
29 : :
30 : 0 : QgsSqlExpressionCompiler::Result QgsSQLiteExpressionCompiler::compileNode( const QgsExpressionNode *node, QString &result )
31 : : {
32 : 0 : QgsSqlExpressionCompiler::Result staticRes = replaceNodeByStaticCachedValueIfPossible( node, result );
33 : 0 : if ( staticRes != Fail )
34 : 0 : return staticRes;
35 : :
36 : 0 : switch ( node->nodeType() )
37 : : {
38 : : case QgsExpressionNode::ntBinaryOperator:
39 : : {
40 : 0 : const QgsExpressionNodeBinaryOperator *op = static_cast<const QgsExpressionNodeBinaryOperator *>( node );
41 : 0 : switch ( op->op() )
42 : : {
43 : : case QgsExpressionNodeBinaryOperator::boPow:
44 : : case QgsExpressionNodeBinaryOperator::boRegexp:
45 : 0 : return Fail; //not supported by SQLite
46 : :
47 : : case QgsExpressionNodeBinaryOperator::boILike:
48 : : case QgsExpressionNodeBinaryOperator::boNotILike:
49 : : {
50 : 0 : QString opL, opR;
51 : :
52 : 0 : if ( compileNode( op->opLeft(), opL ) != Complete ||
53 : 0 : compileNode( op->opRight(), opR ) != Complete )
54 : 0 : return Fail;
55 : :
56 : 0 : result = QStringLiteral( "lower(%1) %2 lower(%3) ESCAPE '\\'" )
57 : 0 : .arg( opL )
58 : 0 : .arg( op->op() == QgsExpressionNodeBinaryOperator::boILike ? QStringLiteral( "LIKE" ) : QStringLiteral( "NOT LIKE" ) )
59 : 0 : .arg( opR );
60 : :
61 : 0 : return Complete;
62 : 0 : }
63 : :
64 : : default:
65 : : //fallback to default handling
66 : 0 : return QgsSqlExpressionCompiler::compileNode( node, result );
67 : : }
68 : : }
69 : :
70 : : case QgsExpressionNode::ntFunction:
71 : : {
72 : 0 : const QgsExpressionNodeFunction *n = static_cast<const QgsExpressionNodeFunction *>( node );
73 : 0 : QgsExpressionFunction *fd = QgsExpression::Functions()[n->fnIndex()];
74 : :
75 : 0 : if ( fd->name() == QLatin1String( "make_datetime" ) || fd->name() == QLatin1String( "make_date" ) || fd->name() == QLatin1String( "make_time" ) )
76 : : {
77 : 0 : const auto constList = n->args()->list();
78 : 0 : for ( const QgsExpressionNode *ln : constList )
79 : : {
80 : 0 : if ( ln->nodeType() != QgsExpressionNode::ntLiteral )
81 : 0 : return Fail;
82 : : }
83 : 0 : }
84 : :
85 : 0 : return QgsSqlExpressionCompiler::compileNode( node, result );
86 : : }
87 : :
88 : : default:
89 : 0 : break;
90 : : }
91 : :
92 : 0 : return QgsSqlExpressionCompiler::compileNode( node, result );
93 : 0 : }
94 : :
95 : 0 : QString QgsSQLiteExpressionCompiler::quotedIdentifier( const QString &identifier )
96 : : {
97 : 0 : return QgsSqliteUtils::quotedIdentifier( identifier );
98 : : }
99 : :
100 : 0 : QString QgsSQLiteExpressionCompiler::quotedValue( const QVariant &value, bool &ok )
101 : : {
102 : 0 : ok = true;
103 : 0 : return QgsSqliteUtils::quotedValue( value );
104 : : }
105 : :
106 : 0 : QString QgsSQLiteExpressionCompiler::sqlFunctionFromFunctionName( const QString &fnName ) const
107 : : {
108 : 0 : static const QMap<QString, QString> FN_NAMES
109 : 0 : {
110 : 0 : { "abs", "abs" },
111 : 0 : { "char", "char" },
112 : 0 : { "coalesce", "coalesce" },
113 : 0 : { "lower", "lower" },
114 : 0 : { "round", "round" },
115 : 0 : { "trim", "trim" },
116 : 0 : { "upper", "upper" },
117 : 0 : { "make_datetime", "" },
118 : 0 : { "make_date", "" },
119 : 0 : { "make_time", "" },
120 : : };
121 : :
122 : 0 : return FN_NAMES.value( fnName, QString() );
123 : 0 : }
124 : :
125 : 0 : QStringList QgsSQLiteExpressionCompiler::sqlArgumentsFromFunctionName( const QString &fnName, const QStringList &fnArgs ) const
126 : : {
127 : 0 : QStringList args( fnArgs );
128 : 0 : if ( fnName == QLatin1String( "make_datetime" ) )
129 : : {
130 : 0 : args = QStringList( QStringLiteral( "'%1-%2-%3T%4:%5:%6Z'" ).arg( args[0].rightJustified( 4, '0' ) )
131 : 0 : .arg( args[1].rightJustified( 2, '0' ) )
132 : 0 : .arg( args[2].rightJustified( 2, '0' ) )
133 : 0 : .arg( args[3].rightJustified( 2, '0' ) )
134 : 0 : .arg( args[4].rightJustified( 2, '0' ) )
135 : 0 : .arg( args[5].rightJustified( 2, '0' ) ) );
136 : 0 : }
137 : 0 : else if ( fnName == QLatin1String( "make_date" ) )
138 : : {
139 : 0 : args = QStringList( QStringLiteral( "'%1-%2-%3'" ).arg( args[0].rightJustified( 4, '0' ) )
140 : 0 : .arg( args[1].rightJustified( 2, '0' ) )
141 : 0 : .arg( args[2].rightJustified( 2, '0' ) ) );
142 : 0 : }
143 : 0 : else if ( fnName == QLatin1String( "make_time" ) )
144 : : {
145 : 0 : args = QStringList( QStringLiteral( "'%1:%2:%3'" ).arg( args[0].rightJustified( 2, '0' ) )
146 : 0 : .arg( args[1].rightJustified( 2, '0' ) )
147 : 0 : .arg( args[2].rightJustified( 2, '0' ) ) );
148 : 0 : }
149 : 0 : return args;
150 : 0 : }
151 : :
152 : 0 : QString QgsSQLiteExpressionCompiler::castToReal( const QString &value ) const
153 : : {
154 : 0 : return QStringLiteral( "CAST((%1) AS REAL)" ).arg( value );
155 : 0 : }
156 : :
157 : 0 : QString QgsSQLiteExpressionCompiler::castToInt( const QString &value ) const
158 : : {
159 : 0 : return QStringLiteral( "CAST((%1) AS INTEGER)" ).arg( value );
160 : 0 : }
161 : :
162 : 0 : QString QgsSQLiteExpressionCompiler::castToText( const QString &value ) const
163 : : {
164 : 0 : return QStringLiteral( "CAST((%1) AS TEXT)" ).arg( value );
165 : 0 : }
166 : :
167 : : ///@endcond
|