LCOV - code coverage report
Current view: top level - core - qgssqlstatement.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 0 399 0.0 %
Date: 2021-04-10 08:29:14 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :                               qgssqlstatement.cpp
       3                 :            :                              -------------------
       4                 :            :     begin                : April 2016
       5                 :            :     copyright            : (C) 2011 by Martin Dobias
       6                 :            :     copyright            : (C) 2016 by Even Rouault
       7                 :            :     email                : even.rouault at spatialys.com
       8                 :            :  ***************************************************************************
       9                 :            :  *                                                                         *
      10                 :            :  *   This program is free software; you can redistribute it and/or modify  *
      11                 :            :  *   it under the terms of the GNU General Public License as published by  *
      12                 :            :  *   the Free Software Foundation; either version 2 of the License, or     *
      13                 :            :  *   (at your option) any later version.                                   *
      14                 :            :  *                                                                         *
      15                 :            :  ***************************************************************************/
      16                 :            : 
      17                 :            : #include "qgssqlstatement.h"
      18                 :            : #include "qgis.h"
      19                 :            : 
      20                 :            : #include <cmath>
      21                 :            : #include <limits>
      22                 :            : 
      23                 :            : 
      24                 :            : // from parser
      25                 :            : extern QgsSQLStatement::Node *parse( const QString &str, QString &parserErrorMsg, bool allowFragments );
      26                 :            : 
      27                 :            : ///////////////////////////////////////////////
      28                 :            : // operators
      29                 :            : 
      30                 :            : const char *QgsSQLStatement::BINARY_OPERATOR_TEXT[] =
      31                 :            : {
      32                 :            :   // this must correspond (number and order of element) to the declaration of the enum BinaryOperator
      33                 :            :   "OR", "AND",
      34                 :            :   "=", "<>", "<=", ">=", "<", ">", "LIKE", "NOT LIKE", "ILIKE", "NOT ILIKE", "IS", "IS NOT",
      35                 :            :   "+", "-", "*", "/", "//", "%", "^",
      36                 :            :   "||"
      37                 :            : };
      38                 :            : 
      39                 :            : const char *QgsSQLStatement::UNARY_OPERATOR_TEXT[] =
      40                 :            : {
      41                 :            :   // this must correspond (number and order of element) to the declaration of the enum UnaryOperator
      42                 :            :   "NOT", "-"
      43                 :            : };
      44                 :            : 
      45                 :            : const char *QgsSQLStatement::JOIN_TYPE_TEXT[] =
      46                 :            : {
      47                 :            :   // this must correspond (number and order of element) to the declaration of the enum JoinType
      48                 :            :   "", "LEFT", "LEFT OUTER", "RIGHT", "RIGHT OUTER", "CROSS", "INNER", "FULL"
      49                 :            : };
      50                 :            : 
      51                 :            : //////
      52                 :            : 
      53                 :          0 : QString QgsSQLStatement::statement() const
      54                 :            : {
      55                 :          0 :   if ( !mStatement.isNull() )
      56                 :          0 :     return mStatement;
      57                 :            :   else
      58                 :          0 :     return dump();
      59                 :          0 : }
      60                 :            : 
      61                 :          0 : QString QgsSQLStatement::dump() const
      62                 :            : {
      63                 :          0 :   if ( !mRootNode )
      64                 :          0 :     return tr( "(no root)" );
      65                 :            : 
      66                 :          0 :   return mRootNode->dump();
      67                 :          0 : }
      68                 :            : 
      69                 :          0 : QString QgsSQLStatement::quotedIdentifier( QString name )
      70                 :            : {
      71                 :          0 :   return QStringLiteral( "\"%1\"" ).arg( name.replace( '\"', QLatin1String( "\"\"" ) ) );
      72                 :          0 : }
      73                 :            : 
      74                 :          0 : QString QgsSQLStatement::quotedIdentifierIfNeeded( const QString &name )
      75                 :            : {
      76                 :            :   // This might not be complete, but it must be at least what we recognize
      77                 :            :   static const char *const RESERVED_KEYWORDS[] =
      78                 :            :   {
      79                 :            :     "AND", "OR", "NOT", "LIKE", "IN", "IS", "BETWEEN", "NULL", "SELECT", "ALL", "DISTINCT", "CAST", "AS",
      80                 :            :     "FROM", "JOIN", "ON", "USING", "WHERE", "ORDER", "BY", "ASC", "DESC",
      81                 :            :     "LEFT", "RIGHT", "INNER", "OUTER", "CROSS", "FULL", "NATURAL", "UNION",
      82                 :            :     "OFFSET", "LIMIT", "GROUP", "HAVING"
      83                 :            :   };
      84                 :            : 
      85                 :          0 :   for ( size_t i = 0; i < sizeof( RESERVED_KEYWORDS ) / sizeof( RESERVED_KEYWORDS[0] ); ++i )
      86                 :            :   {
      87                 :          0 :     if ( name.compare( QString( RESERVED_KEYWORDS[i] ), Qt::CaseInsensitive ) == 0 )
      88                 :            :     {
      89                 :          0 :       return quotedIdentifier( name );
      90                 :            :     }
      91                 :          0 :   }
      92                 :          0 :   static const QRegExp IDENTIFIER_RE( "^[A-Za-z_\x80-\xff][A-Za-z0-9_\x80-\xff]*$" );
      93                 :          0 :   return IDENTIFIER_RE.exactMatch( name ) ? name : quotedIdentifier( name );
      94                 :          0 : }
      95                 :            : 
      96                 :          0 : QString QgsSQLStatement::stripQuotedIdentifier( QString text )
      97                 :            : {
      98                 :          0 :   if ( text.length() >= 2 && text[0] == '"' && text[text.length() - 1] == '"' )
      99                 :            :   {
     100                 :            :     // strip double quotes on start,end
     101                 :          0 :     text = text.mid( 1, text.length() - 2 );
     102                 :            : 
     103                 :            :     // make single "double quotes" from double "double quotes"
     104                 :          0 :     text.replace( QLatin1String( "\"\"" ), QLatin1String( "\"" ) );
     105                 :          0 :   }
     106                 :          0 :   return text;
     107                 :            : }
     108                 :            : 
     109                 :          0 : QString QgsSQLStatement::stripMsQuotedIdentifier( QString text )
     110                 :            : {
     111                 :          0 :   if ( text.length() >= 2 && text[0] == '[' && text[text.length() - 1] == ']' )
     112                 :            :   {
     113                 :            :     // strip square brackets on start,end
     114                 :          0 :     text = text.mid( 1, text.length() - 2 );
     115                 :          0 :   }
     116                 :          0 :   return text;
     117                 :            : }
     118                 :            : 
     119                 :          0 : QString QgsSQLStatement::quotedString( QString text )
     120                 :            : {
     121                 :          0 :   text.replace( '\'', QLatin1String( "''" ) );
     122                 :          0 :   text.replace( '\\', QLatin1String( "\\\\" ) );
     123                 :          0 :   text.replace( '\n', QLatin1String( "\\n" ) );
     124                 :          0 :   text.replace( '\t', QLatin1String( "\\t" ) );
     125                 :          0 :   return QStringLiteral( "'%1'" ).arg( text );
     126                 :          0 : }
     127                 :            : 
     128                 :          0 : QgsSQLStatement::QgsSQLStatement( const QString &expr )
     129                 :          0 :   : QgsSQLStatement( expr, false )
     130                 :            : {
     131                 :          0 : }
     132                 :            : 
     133                 :          0 : QgsSQLStatement::QgsSQLStatement( const QString &expr, bool allowFragments )
     134                 :          0 :   : mAllowFragments( allowFragments )
     135                 :          0 : {
     136                 :          0 :   mRootNode = ::parse( expr, mParserErrorString, mAllowFragments );
     137                 :          0 :   mStatement = expr;
     138                 :          0 : }
     139                 :            : 
     140                 :          0 : QgsSQLStatement::QgsSQLStatement( const QgsSQLStatement &other )
     141                 :          0 : {
     142                 :          0 :   mRootNode = ::parse( other.mStatement, mParserErrorString, other.mAllowFragments );
     143                 :          0 :   mStatement = other.mStatement;
     144                 :          0 : }
     145                 :            : 
     146                 :          0 : QgsSQLStatement &QgsSQLStatement::operator=( const QgsSQLStatement &other )
     147                 :            : {
     148                 :          0 :   if ( &other != this )
     149                 :            :   {
     150                 :          0 :     delete mRootNode;
     151                 :          0 :     mParserErrorString.clear();
     152                 :          0 :     mRootNode = ::parse( other.mStatement, mParserErrorString, other.mAllowFragments );
     153                 :          0 :     mStatement = other.mStatement;
     154                 :          0 :   }
     155                 :          0 :   return *this;
     156                 :            : }
     157                 :            : 
     158                 :          0 : QgsSQLStatement::~QgsSQLStatement()
     159                 :          0 : {
     160                 :          0 :   delete mRootNode;
     161                 :          0 : }
     162                 :            : 
     163                 :          0 : bool QgsSQLStatement::hasParserError() const { return !mParserErrorString.isNull() || ( !mRootNode && !mAllowFragments ); }
     164                 :            : 
     165                 :          0 : QString QgsSQLStatement::parserErrorString() const { return mParserErrorString; }
     166                 :            : 
     167                 :          0 : void QgsSQLStatement::acceptVisitor( QgsSQLStatement::Visitor &v ) const
     168                 :            : {
     169                 :          0 :   if ( mRootNode )
     170                 :          0 :     mRootNode->accept( v );
     171                 :          0 : }
     172                 :            : 
     173                 :          0 : const QgsSQLStatement::Node *QgsSQLStatement::rootNode() const
     174                 :            : {
     175                 :          0 :   return mRootNode;
     176                 :            : }
     177                 :            : 
     178                 :          0 : void QgsSQLStatement::RecursiveVisitor::visit( const QgsSQLStatement::NodeSelect &n )
     179                 :            : {
     180                 :          0 :   const auto constTables = n.tables();
     181                 :          0 :   for ( QgsSQLStatement::NodeTableDef *table : constTables )
     182                 :            :   {
     183                 :          0 :     table->accept( *this );
     184                 :            :   }
     185                 :          0 :   const auto constColumns = n.columns();
     186                 :          0 :   for ( QgsSQLStatement::NodeSelectedColumn *column : constColumns )
     187                 :            :   {
     188                 :          0 :     column->accept( *this );
     189                 :            :   }
     190                 :          0 :   const auto constJoins = n.joins();
     191                 :          0 :   for ( QgsSQLStatement::NodeJoin *join : constJoins )
     192                 :            :   {
     193                 :          0 :     join->accept( *this );
     194                 :            :   }
     195                 :          0 :   QgsSQLStatement::Node *where = n.where();
     196                 :          0 :   if ( where )
     197                 :          0 :     where->accept( *this );
     198                 :          0 :   const auto constOrderBy = n.orderBy();
     199                 :          0 :   for ( QgsSQLStatement::NodeColumnSorted *column : constOrderBy )
     200                 :            :   {
     201                 :          0 :     column->accept( *this );
     202                 :            :   }
     203                 :          0 : }
     204                 :            : 
     205                 :          0 : void QgsSQLStatement::RecursiveVisitor::visit( const QgsSQLStatement::NodeJoin &n )
     206                 :            : {
     207                 :          0 :   n.tableDef()->accept( *this );
     208                 :          0 :   QgsSQLStatement::Node *expr = n.onExpr();
     209                 :          0 :   if ( expr )
     210                 :          0 :     expr->accept( *this );
     211                 :          0 : }
     212                 :            : 
     213                 :            : /**
     214                 :            :  * \ingroup core
     215                 :            :  * \brief Internal use.
     216                 :            :  * \note not available in Python bindings
     217                 :            :  */
     218                 :          0 : class QgsSQLStatementCollectTableNames: public QgsSQLStatement::RecursiveVisitor
     219                 :            : {
     220                 :            :   public:
     221                 :            :     typedef QPair<QString, QString> TableColumnPair;
     222                 :            : 
     223                 :            :     /**
     224                 :            :      * Constructor for QgsSQLStatementCollectTableNames.
     225                 :            :      */
     226                 :          0 :     QgsSQLStatementCollectTableNames() = default;
     227                 :            : 
     228                 :            :     void visit( const QgsSQLStatement::NodeColumnRef &n ) override;
     229                 :            :     void visit( const QgsSQLStatement::NodeTableDef &n ) override;
     230                 :            : 
     231                 :            :     QSet<QString> tableNamesDeclared;
     232                 :            :     QSet<TableColumnPair> tableNamesReferenced;
     233                 :            : };
     234                 :            : 
     235                 :          0 : void QgsSQLStatementCollectTableNames::visit( const QgsSQLStatement::NodeColumnRef &n )
     236                 :            : {
     237                 :          0 :   if ( !n.tableName().isEmpty() )
     238                 :          0 :     tableNamesReferenced.insert( TableColumnPair( n.tableName(), n.name() ) );
     239                 :          0 :   QgsSQLStatement::RecursiveVisitor::visit( n );
     240                 :          0 : }
     241                 :            : 
     242                 :          0 : void QgsSQLStatementCollectTableNames::visit( const QgsSQLStatement::NodeTableDef &n )
     243                 :            : {
     244                 :          0 :   tableNamesDeclared.insert( n.alias().isEmpty() ? n.name() : n.alias() );
     245                 :          0 :   QgsSQLStatement::RecursiveVisitor::visit( n );
     246                 :          0 : }
     247                 :            : 
     248                 :          0 : bool QgsSQLStatement::doBasicValidationChecks( QString &errorMsgOut ) const
     249                 :            : {
     250                 :          0 :   errorMsgOut.clear();
     251                 :          0 :   if ( !mRootNode )
     252                 :            :   {
     253                 :          0 :     errorMsgOut = tr( "No root node" );
     254                 :          0 :     return false;
     255                 :            :   }
     256                 :          0 :   QgsSQLStatementCollectTableNames v;
     257                 :          0 :   mRootNode->accept( v );
     258                 :            : 
     259                 :          0 :   for ( const QgsSQLStatementCollectTableNames::TableColumnPair &pair : std::as_const( v.tableNamesReferenced ) )
     260                 :            :   {
     261                 :          0 :     if ( !v.tableNamesDeclared.contains( pair.first ) )
     262                 :            :     {
     263                 :          0 :       if ( !errorMsgOut.isEmpty() )
     264                 :          0 :         errorMsgOut += QLatin1Char( ' ' );
     265                 :          0 :       errorMsgOut += tr( "Table %1 is referenced by column %2, but not selected in FROM / JOIN." ).arg( pair.first, pair.second );
     266                 :          0 :     }
     267                 :            :   }
     268                 :            : 
     269                 :          0 :   return errorMsgOut.isEmpty();
     270                 :          0 : }
     271                 :            : 
     272                 :            : ///////////////////////////////////////////////
     273                 :            : // nodes
     274                 :            : 
     275                 :          0 : void QgsSQLStatement::NodeList::accept( QgsSQLStatement::Visitor &v ) const
     276                 :            : {
     277                 :          0 :   for ( QgsSQLStatement::Node *node : mList )
     278                 :            :   {
     279                 :          0 :     node->accept( v );
     280                 :            :   }
     281                 :          0 : }
     282                 :            : 
     283                 :          0 : QgsSQLStatement::NodeList *QgsSQLStatement::NodeList::clone() const
     284                 :            : {
     285                 :          0 :   NodeList *nl = new NodeList;
     286                 :          0 :   const auto constMList = mList;
     287                 :          0 :   for ( Node *node : constMList )
     288                 :            :   {
     289                 :          0 :     nl->mList.append( node->clone() );
     290                 :            :   }
     291                 :            : 
     292                 :          0 :   return nl;
     293                 :          0 : }
     294                 :            : 
     295                 :          0 : QString QgsSQLStatement::NodeList::dump() const
     296                 :            : {
     297                 :          0 :   QString msg;
     298                 :          0 :   bool first = true;
     299                 :          0 :   const auto constMList = mList;
     300                 :          0 :   for ( Node *n : constMList )
     301                 :            :   {
     302                 :          0 :     if ( !first ) msg += QLatin1String( ", " );
     303                 :          0 :     else first = false;
     304                 :          0 :     msg += n->dump();
     305                 :            :   }
     306                 :          0 :   return msg;
     307                 :          0 : }
     308                 :            : 
     309                 :            : 
     310                 :            : //
     311                 :            : 
     312                 :          0 : QString QgsSQLStatement::NodeUnaryOperator::dump() const
     313                 :            : {
     314                 :          0 :   return QStringLiteral( "%1 %2" ).arg( UNARY_OPERATOR_TEXT[mOp], mOperand->dump() );
     315                 :          0 : }
     316                 :            : 
     317                 :          0 : QgsSQLStatement::Node *QgsSQLStatement::NodeUnaryOperator::clone() const
     318                 :            : {
     319                 :          0 :   return new NodeUnaryOperator( mOp, mOperand->clone() );
     320                 :          0 : }
     321                 :            : 
     322                 :            : //
     323                 :            : 
     324                 :          0 : int QgsSQLStatement::NodeBinaryOperator::precedence() const
     325                 :            : {
     326                 :            :   // see left/right in qgsexpressionparser.yy
     327                 :          0 :   switch ( mOp )
     328                 :            :   {
     329                 :            :     case boOr:
     330                 :          0 :       return 1;
     331                 :            : 
     332                 :            :     case boAnd:
     333                 :          0 :       return 2;
     334                 :            : 
     335                 :            :     case boEQ:
     336                 :            :     case boNE:
     337                 :            :     case boLE:
     338                 :            :     case boGE:
     339                 :            :     case boLT:
     340                 :            :     case boGT:
     341                 :            :     case boLike:
     342                 :            :     case boILike:
     343                 :            :     case boNotLike:
     344                 :            :     case boNotILike:
     345                 :            :     case boIs:
     346                 :            :     case boIsNot:
     347                 :          0 :       return 3;
     348                 :            : 
     349                 :            :     case boPlus:
     350                 :            :     case boMinus:
     351                 :          0 :       return 4;
     352                 :            : 
     353                 :            :     case boMul:
     354                 :            :     case boDiv:
     355                 :            :     case boIntDiv:
     356                 :            :     case boMod:
     357                 :          0 :       return 5;
     358                 :            : 
     359                 :            :     case boPow:
     360                 :          0 :       return 6;
     361                 :            : 
     362                 :            :     case boConcat:
     363                 :          0 :       return 7;
     364                 :            :   }
     365                 :            :   Q_ASSERT( false && "unexpected binary operator" );
     366                 :          0 :   return -1;
     367                 :          0 : }
     368                 :            : 
     369                 :          0 : bool QgsSQLStatement::NodeBinaryOperator::leftAssociative() const
     370                 :            : {
     371                 :            :   // see left/right in qgsexpressionparser.yy
     372                 :          0 :   switch ( mOp )
     373                 :            :   {
     374                 :            :     case boOr:
     375                 :            :     case boAnd:
     376                 :            :     case boEQ:
     377                 :            :     case boNE:
     378                 :            :     case boLE:
     379                 :            :     case boGE:
     380                 :            :     case boLT:
     381                 :            :     case boGT:
     382                 :            :     case boLike:
     383                 :            :     case boILike:
     384                 :            :     case boNotLike:
     385                 :            :     case boNotILike:
     386                 :            :     case boIs:
     387                 :            :     case boIsNot:
     388                 :            :     case boPlus:
     389                 :            :     case boMinus:
     390                 :            :     case boMul:
     391                 :            :     case boDiv:
     392                 :            :     case boIntDiv:
     393                 :            :     case boMod:
     394                 :            :     case boConcat:
     395                 :          0 :       return true;
     396                 :            : 
     397                 :            :     case boPow:
     398                 :          0 :       return false;
     399                 :            :   }
     400                 :            :   Q_ASSERT( false && "unexpected binary operator" );
     401                 :          0 :   return false;
     402                 :          0 : }
     403                 :            : 
     404                 :          0 : QString QgsSQLStatement::NodeBinaryOperator::dump() const
     405                 :            : {
     406                 :          0 :   QgsSQLStatement::NodeBinaryOperator *lOp = dynamic_cast<QgsSQLStatement::NodeBinaryOperator *>( mOpLeft );
     407                 :          0 :   QgsSQLStatement::NodeBinaryOperator *rOp = dynamic_cast<QgsSQLStatement::NodeBinaryOperator *>( mOpRight );
     408                 :          0 :   QgsSQLStatement::NodeUnaryOperator *ruOp = dynamic_cast<QgsSQLStatement::NodeUnaryOperator *>( mOpRight );
     409                 :            : 
     410                 :          0 :   QString rdump( mOpRight->dump() );
     411                 :            : 
     412                 :            :   // avoid dumping "IS (NOT ...)" as "IS NOT ..."
     413                 :          0 :   if ( mOp == boIs && ruOp && ruOp->op() == uoNot )
     414                 :            :   {
     415                 :          0 :     rdump.prepend( '(' ).append( ')' );
     416                 :          0 :   }
     417                 :            : 
     418                 :          0 :   QString fmt;
     419                 :          0 :   if ( leftAssociative() )
     420                 :            :   {
     421                 :          0 :     fmt += lOp && ( lOp->precedence() < precedence() ) ? "(%1)" : "%1";
     422                 :          0 :     fmt += QLatin1String( " %2 " );
     423                 :          0 :     fmt += rOp && ( rOp->precedence() <= precedence() ) ? "(%3)" : "%3";
     424                 :          0 :   }
     425                 :            :   else
     426                 :            :   {
     427                 :          0 :     fmt += lOp && ( lOp->precedence() <= precedence() ) ? "(%1)" : "%1";
     428                 :          0 :     fmt += QLatin1String( " %2 " );
     429                 :          0 :     fmt += rOp && ( rOp->precedence() < precedence() ) ? "(%3)" : "%3";
     430                 :            :   }
     431                 :            : 
     432                 :          0 :   return fmt.arg( mOpLeft->dump(), BINARY_OPERATOR_TEXT[mOp], rdump );
     433                 :          0 : }
     434                 :            : 
     435                 :          0 : QgsSQLStatement::Node *QgsSQLStatement::NodeBinaryOperator::clone() const
     436                 :            : {
     437                 :          0 :   return new NodeBinaryOperator( mOp, mOpLeft->clone(), mOpRight->clone() );
     438                 :          0 : }
     439                 :            : 
     440                 :            : //
     441                 :            : 
     442                 :          0 : QString QgsSQLStatement::NodeInOperator::dump() const
     443                 :            : {
     444                 :          0 :   return QStringLiteral( "%1 %2IN (%3)" ).arg( mNode->dump(), mNotIn ? "NOT " : "", mList->dump() );
     445                 :          0 : }
     446                 :            : 
     447                 :          0 : QgsSQLStatement::Node *QgsSQLStatement::NodeInOperator::clone() const
     448                 :            : {
     449                 :          0 :   return new NodeInOperator( mNode->clone(), mList->clone(), mNotIn );
     450                 :          0 : }
     451                 :            : 
     452                 :            : //
     453                 :            : 
     454                 :          0 : QString QgsSQLStatement::NodeBetweenOperator::dump() const
     455                 :            : {
     456                 :          0 :   return QStringLiteral( "%1 %2BETWEEN %3 AND %4" ).arg( mNode->dump(), mNotBetween ? "NOT " : "", mMinVal->dump(), mMaxVal->dump() );
     457                 :          0 : }
     458                 :            : 
     459                 :          0 : QgsSQLStatement::Node *QgsSQLStatement::NodeBetweenOperator::clone() const
     460                 :            : {
     461                 :          0 :   return new NodeBetweenOperator( mNode->clone(), mMinVal->clone(), mMaxVal->clone(), mNotBetween );
     462                 :          0 : }
     463                 :            : 
     464                 :            : //
     465                 :            : 
     466                 :          0 : QString QgsSQLStatement::NodeFunction::dump() const
     467                 :            : {
     468                 :          0 :   return QStringLiteral( "%1(%2)" ).arg( mName, mArgs ? mArgs->dump() : QString() ); // function
     469                 :          0 : }
     470                 :            : 
     471                 :          0 : QgsSQLStatement::Node *QgsSQLStatement::NodeFunction::clone() const
     472                 :            : {
     473                 :          0 :   return new NodeFunction( mName, mArgs ? mArgs->clone() : nullptr );
     474                 :          0 : }
     475                 :            : 
     476                 :            : //
     477                 :            : 
     478                 :          0 : QString QgsSQLStatement::NodeLiteral::dump() const
     479                 :            : {
     480                 :          0 :   if ( mValue.isNull() )
     481                 :          0 :     return QStringLiteral( "NULL" );
     482                 :            : 
     483                 :          0 :   switch ( mValue.type() )
     484                 :            :   {
     485                 :            :     case QVariant::Int:
     486                 :          0 :       return QString::number( mValue.toInt() );
     487                 :            :     case QVariant::LongLong:
     488                 :          0 :       return QString::number( mValue.toLongLong() );
     489                 :            :     case QVariant::Double:
     490                 :          0 :       return QString::number( mValue.toDouble() );
     491                 :            :     case QVariant::String:
     492                 :          0 :       return quotedString( mValue.toString() );
     493                 :            :     case QVariant::Bool:
     494                 :          0 :       return mValue.toBool() ? "TRUE" : "FALSE";
     495                 :            :     default:
     496                 :          0 :       return tr( "[unsupported type: %1; value: %2]" ).arg( mValue.typeName(), mValue.toString() );
     497                 :            :   }
     498                 :          0 : }
     499                 :            : 
     500                 :          0 : QgsSQLStatement::Node *QgsSQLStatement::NodeLiteral::clone() const
     501                 :            : {
     502                 :          0 :   return new NodeLiteral( mValue );
     503                 :          0 : }
     504                 :            : 
     505                 :            : //
     506                 :            : 
     507                 :          0 : QString QgsSQLStatement::NodeColumnRef::dump() const
     508                 :            : {
     509                 :          0 :   QString ret;
     510                 :          0 :   if ( mDistinct )
     511                 :          0 :     ret += QLatin1String( "DISTINCT " );
     512                 :          0 :   if ( !mTableName.isEmpty() )
     513                 :            :   {
     514                 :          0 :     ret += quotedIdentifierIfNeeded( mTableName );
     515                 :          0 :     ret += '.';
     516                 :          0 :   }
     517                 :          0 :   ret += ( mStar ) ? mName : quotedIdentifierIfNeeded( mName );
     518                 :          0 :   return ret;
     519                 :          0 : }
     520                 :            : 
     521                 :          0 : QgsSQLStatement::Node *QgsSQLStatement::NodeColumnRef::clone() const
     522                 :            : {
     523                 :          0 :   return cloneThis();
     524                 :            : }
     525                 :            : 
     526                 :          0 : QgsSQLStatement::NodeColumnRef *QgsSQLStatement::NodeColumnRef::cloneThis() const
     527                 :            : {
     528                 :          0 :   NodeColumnRef *newColumnRef = new NodeColumnRef( mTableName, mName, mStar );
     529                 :          0 :   newColumnRef->setDistinct( mDistinct );
     530                 :          0 :   return newColumnRef;
     531                 :          0 : }
     532                 :            : 
     533                 :            : //
     534                 :            : 
     535                 :          0 : QString QgsSQLStatement::NodeSelectedColumn::dump() const
     536                 :            : {
     537                 :          0 :   QString ret;
     538                 :          0 :   ret += mColumnNode->dump();
     539                 :          0 :   if ( !mAlias.isEmpty() )
     540                 :            :   {
     541                 :          0 :     ret += QLatin1String( " AS " );
     542                 :          0 :     ret += quotedIdentifierIfNeeded( mAlias );
     543                 :          0 :   }
     544                 :          0 :   return ret;
     545                 :          0 : }
     546                 :            : 
     547                 :          0 : QgsSQLStatement::NodeSelectedColumn *QgsSQLStatement::NodeSelectedColumn::cloneThis() const
     548                 :            : {
     549                 :          0 :   NodeSelectedColumn *newObj = new NodeSelectedColumn( mColumnNode->clone() );
     550                 :          0 :   newObj->setAlias( mAlias );
     551                 :          0 :   return newObj;
     552                 :          0 : }
     553                 :            : 
     554                 :          0 : QgsSQLStatement::Node *QgsSQLStatement::NodeSelectedColumn::clone() const
     555                 :            : {
     556                 :          0 :   return cloneThis();
     557                 :            : }
     558                 :            : //
     559                 :            : 
     560                 :          0 : QString QgsSQLStatement::NodeTableDef::dump() const
     561                 :            : {
     562                 :          0 :   QString ret;
     563                 :          0 :   ret = quotedIdentifierIfNeeded( mName );
     564                 :          0 :   if ( !mAlias.isEmpty() )
     565                 :            :   {
     566                 :          0 :     ret += QLatin1String( " AS " );
     567                 :          0 :     ret += quotedIdentifierIfNeeded( mAlias );
     568                 :          0 :   }
     569                 :          0 :   return ret;
     570                 :          0 : }
     571                 :            : 
     572                 :          0 : QgsSQLStatement::NodeTableDef *QgsSQLStatement::NodeTableDef::cloneThis() const
     573                 :            : {
     574                 :          0 :   return new NodeTableDef( mName, mAlias );
     575                 :          0 : }
     576                 :            : 
     577                 :          0 : QgsSQLStatement::Node *QgsSQLStatement::NodeTableDef::clone() const
     578                 :            : {
     579                 :          0 :   return cloneThis();
     580                 :            : }
     581                 :            : 
     582                 :            : //
     583                 :            : 
     584                 :          0 : QgsSQLStatement::NodeSelect::~NodeSelect()
     585                 :          0 : {
     586                 :          0 :   qDeleteAll( mTableList );
     587                 :          0 :   qDeleteAll( mColumns );
     588                 :          0 :   qDeleteAll( mJoins );
     589                 :          0 :   delete mWhere;
     590                 :          0 :   qDeleteAll( mOrderBy );
     591                 :          0 : }
     592                 :            : 
     593                 :          0 : QString QgsSQLStatement::NodeSelect::dump() const
     594                 :            : {
     595                 :          0 :   QString ret = QStringLiteral( "SELECT " );
     596                 :          0 :   if ( mDistinct )
     597                 :          0 :     ret += QLatin1String( "DISTINCT " );
     598                 :          0 :   bool bFirstColumn = true;
     599                 :          0 :   const auto constMColumns = mColumns;
     600                 :          0 :   for ( QgsSQLStatement::NodeSelectedColumn *column : constMColumns )
     601                 :            :   {
     602                 :          0 :     if ( !bFirstColumn )
     603                 :          0 :       ret += QLatin1String( ", " );
     604                 :          0 :     bFirstColumn = false;
     605                 :          0 :     ret += column->dump();
     606                 :            :   }
     607                 :          0 :   ret += QLatin1String( " FROM " );
     608                 :          0 :   bool bFirstTable = true;
     609                 :          0 :   const auto constMTableList = mTableList;
     610                 :          0 :   for ( QgsSQLStatement::NodeTableDef *table : constMTableList )
     611                 :            :   {
     612                 :          0 :     if ( !bFirstTable )
     613                 :          0 :       ret += QLatin1String( ", " );
     614                 :          0 :     bFirstTable = false;
     615                 :          0 :     ret += table->dump();
     616                 :            :   }
     617                 :          0 :   const auto constMJoins = mJoins;
     618                 :          0 :   for ( QgsSQLStatement::NodeJoin *join : constMJoins )
     619                 :            :   {
     620                 :          0 :     ret += ' ';
     621                 :          0 :     ret += join->dump();
     622                 :            :   }
     623                 :          0 :   if ( mWhere )
     624                 :            :   {
     625                 :          0 :     ret += QLatin1String( " WHERE " );
     626                 :          0 :     ret += mWhere->dump();
     627                 :          0 :   }
     628                 :          0 :   if ( !mOrderBy.isEmpty() )
     629                 :            :   {
     630                 :          0 :     ret += QLatin1String( " ORDER BY " );
     631                 :          0 :     bool bFirst = true;
     632                 :          0 :     const auto constMOrderBy = mOrderBy;
     633                 :          0 :     for ( QgsSQLStatement::NodeColumnSorted *orderBy : constMOrderBy )
     634                 :            :     {
     635                 :          0 :       if ( !bFirst )
     636                 :          0 :         ret += QLatin1String( ", " );
     637                 :          0 :       bFirst = false;
     638                 :          0 :       ret += orderBy->dump();
     639                 :            :     }
     640                 :          0 :   }
     641                 :          0 :   return ret;
     642                 :          0 : }
     643                 :            : 
     644                 :          0 : QgsSQLStatement::Node *QgsSQLStatement::NodeSelect::clone() const
     645                 :            : {
     646                 :          0 :   QList<QgsSQLStatement::NodeSelectedColumn *> newColumnList;
     647                 :          0 :   const auto constMColumns = mColumns;
     648                 :          0 :   for ( QgsSQLStatement::NodeSelectedColumn *column : constMColumns )
     649                 :            :   {
     650                 :          0 :     newColumnList.push_back( column->cloneThis() );
     651                 :            :   }
     652                 :          0 :   QList<QgsSQLStatement::NodeTableDef *> newTableList;
     653                 :          0 :   const auto constMTableList = mTableList;
     654                 :          0 :   for ( QgsSQLStatement::NodeTableDef *table : constMTableList )
     655                 :            :   {
     656                 :          0 :     newTableList.push_back( table->cloneThis() );
     657                 :            :   }
     658                 :          0 :   QgsSQLStatement::NodeSelect *newSelect = new NodeSelect( newTableList, newColumnList, mDistinct );
     659                 :          0 :   const auto constMJoins = mJoins;
     660                 :          0 :   for ( QgsSQLStatement::NodeJoin *join : constMJoins )
     661                 :            :   {
     662                 :          0 :     newSelect->appendJoin( join->cloneThis() );
     663                 :            :   }
     664                 :          0 :   if ( mWhere )
     665                 :            :   {
     666                 :          0 :     newSelect->setWhere( mWhere->clone() );
     667                 :          0 :   }
     668                 :          0 :   QList<QgsSQLStatement::NodeColumnSorted *> newOrderByList;
     669                 :          0 :   const auto constMOrderBy = mOrderBy;
     670                 :          0 :   for ( QgsSQLStatement::NodeColumnSorted *columnSorted : constMOrderBy )
     671                 :            :   {
     672                 :          0 :     newOrderByList.push_back( columnSorted->cloneThis() );
     673                 :            :   }
     674                 :          0 :   newSelect->setOrderBy( newOrderByList );
     675                 :          0 :   return newSelect;
     676                 :          0 : }
     677                 :            : 
     678                 :            : //
     679                 :            : 
     680                 :          0 : QString QgsSQLStatement::NodeJoin::dump() const
     681                 :            : {
     682                 :          0 :   QString ret;
     683                 :          0 :   if ( mType != jtDefault )
     684                 :            :   {
     685                 :          0 :     ret += JOIN_TYPE_TEXT[mType];
     686                 :          0 :     ret += QLatin1Char( ' ' );
     687                 :          0 :   }
     688                 :          0 :   ret += QLatin1String( "JOIN " );
     689                 :          0 :   ret += mTableDef->dump();
     690                 :          0 :   if ( mOnExpr )
     691                 :            :   {
     692                 :          0 :     ret += QLatin1String( " ON " );
     693                 :          0 :     ret += mOnExpr->dump();
     694                 :          0 :   }
     695                 :            :   else
     696                 :            :   {
     697                 :          0 :     ret += QLatin1String( " USING (" );
     698                 :          0 :     bool first = true;
     699                 :          0 :     const auto constMUsingColumns = mUsingColumns;
     700                 :          0 :     for ( QString column : constMUsingColumns )
     701                 :            :     {
     702                 :          0 :       if ( !first )
     703                 :          0 :         ret += QLatin1String( ", " );
     704                 :          0 :       first = false;
     705                 :          0 :       ret += quotedIdentifierIfNeeded( column );
     706                 :          0 :     }
     707                 :          0 :     ret += QLatin1Char( ')' );
     708                 :          0 :   }
     709                 :          0 :   return ret;
     710                 :          0 : }
     711                 :            : 
     712                 :          0 : QgsSQLStatement::Node *QgsSQLStatement::NodeJoin::clone() const
     713                 :            : {
     714                 :          0 :   return cloneThis();
     715                 :            : }
     716                 :            : 
     717                 :          0 : QgsSQLStatement::NodeJoin *QgsSQLStatement::NodeJoin::cloneThis() const
     718                 :            : {
     719                 :          0 :   if ( mOnExpr )
     720                 :          0 :     return new NodeJoin( mTableDef->cloneThis(), mOnExpr->clone(), mType );
     721                 :            :   else
     722                 :          0 :     return new NodeJoin( mTableDef->cloneThis(), mUsingColumns, mType );
     723                 :          0 : }
     724                 :            : 
     725                 :            : //
     726                 :            : 
     727                 :          0 : QString QgsSQLStatement::NodeColumnSorted::dump() const
     728                 :            : {
     729                 :          0 :   QString ret;
     730                 :          0 :   ret = mColumn->dump();
     731                 :          0 :   if ( !mAsc )
     732                 :          0 :     ret += QLatin1String( " DESC" );
     733                 :          0 :   return ret;
     734                 :          0 : }
     735                 :            : 
     736                 :          0 : QgsSQLStatement::Node *QgsSQLStatement::NodeColumnSorted::clone() const
     737                 :            : {
     738                 :          0 :   return cloneThis();
     739                 :            : }
     740                 :            : 
     741                 :          0 : QgsSQLStatement::NodeColumnSorted *QgsSQLStatement::NodeColumnSorted::cloneThis() const
     742                 :            : {
     743                 :          0 :   return new NodeColumnSorted( mColumn->cloneThis(), mAsc );
     744                 :          0 : }
     745                 :            : 
     746                 :            : //
     747                 :            : 
     748                 :          0 : QString QgsSQLStatement::NodeCast::dump() const
     749                 :            : {
     750                 :          0 :   QString ret( QStringLiteral( "CAST(" ) );
     751                 :          0 :   ret += mNode->dump();
     752                 :          0 :   ret += QLatin1String( " AS " );
     753                 :          0 :   ret += mType;
     754                 :          0 :   ret += ')';
     755                 :          0 :   return ret;
     756                 :          0 : }
     757                 :            : 
     758                 :          0 : QgsSQLStatement::Node *QgsSQLStatement::NodeCast::clone() const
     759                 :            : {
     760                 :          0 :   return new NodeCast( mNode->clone(), mType );
     761                 :          0 : }
     762                 :            : 
     763                 :            : //
     764                 :            : // QgsSQLStatementFragment
     765                 :            : //
     766                 :            : 
     767                 :          0 : QgsSQLStatementFragment::QgsSQLStatementFragment( const QString &fragment )
     768                 :          0 :   : QgsSQLStatement( fragment, true )
     769                 :          0 : {
     770                 :            : 
     771                 :          0 : }

Generated by: LCOV version 1.14