File indexing completed on 2024-12-08 04:17:08

0001 /* This file is part of the KDE project
0002    Copyright (C) 2003 Lucijan Busch <lucijan@kde.org>
0003    Copyright (C) 2004-2018 Jarosław Staniek <staniek@kde.org>
0004 
0005    This library is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU Library General Public
0007    License as published by the Free Software Foundation; either
0008    version 2 of the License, or (at your option) any later version.
0009 
0010    This library is distributed in the hope that it will be useful,
0011    but WITHOUT ANY WARRANTY; without even the implied warranty of
0012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013    Library General Public License for more details.
0014 
0015    You should have received a copy of the GNU Library General Public License
0016    along with this library; see the file COPYING.LIB.  If not, write to
0017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019 */
0020 
0021 #include "KDbParser.h"
0022 #include "KDbParser_p.h"
0023 #include "generated/sqlparser.h"
0024 
0025 #include "KDbConnection.h"
0026 #include "KDbTableSchema.h"
0027 
0028 #include <vector>
0029 
0030 bool parseData();
0031 
0032 //! Cache
0033 class ParserStatic
0034 {
0035 public:
0036     ParserStatic()
0037      : statementTypeStrings({
0038             QLatin1String("None"),
0039             QLatin1String("Select"),
0040             QLatin1String("CreateTable"),
0041             QLatin1String("AlterTable"),
0042             QLatin1String("Insert"),
0043             QLatin1String("Update"),
0044             QLatin1String("Delete")})
0045     {
0046     }
0047     const std::vector<QString> statementTypeStrings;
0048 private:
0049     Q_DISABLE_COPY(ParserStatic)
0050 };
0051 
0052 Q_GLOBAL_STATIC(ParserStatic, KDb_parserStatic)
0053 
0054 KDbParser::KDbParser(KDbConnection *connection)
0055         : d(new KDbParserPrivate)
0056 {
0057     d->connection = connection;
0058 }
0059 
0060 KDbParser::~KDbParser()
0061 {
0062     delete d;
0063 }
0064 
0065 KDbParser::StatementType KDbParser::statementType() const
0066 {
0067     return d->statementType;
0068 }
0069 
0070 QString KDbParser::statementTypeString() const
0071 {
0072     Q_ASSERT(size_t(d->statementType) < sizeof(KDb_parserStatic->statementTypeStrings));
0073     return KDb_parserStatic->statementTypeStrings[d->statementType];
0074 }
0075 
0076 KDbTableSchema *KDbParser::table()
0077 {
0078     KDbTableSchema *t = d->table;
0079     d->table = nullptr;
0080     return t;
0081 }
0082 
0083 KDbQuerySchema *KDbParser::query()
0084 {
0085     KDbQuerySchema *s = d->query;
0086     d->query = nullptr;
0087     return s;
0088 }
0089 
0090 KDbConnection *KDbParser::connection()
0091 {
0092     return d->connection;
0093 }
0094 
0095 const KDbConnection *KDbParser::connection() const
0096 {
0097     return d->connection;
0098 }
0099 
0100 KDbParserError KDbParser::error() const
0101 {
0102     return d->error;
0103 }
0104 
0105 KDbEscapedString KDbParser::statement() const
0106 {
0107     return d->sql;
0108 }
0109 
0110 void KDbParser::init()
0111 {
0112     if (d->initialized)
0113         return;
0114     // nothing to do
0115     d->initialized = true;
0116 }
0117 
0118 bool KDbParser::parse(const KDbEscapedString &sql, KDbQuerySchema *query)
0119 {
0120     init();
0121     reset();
0122     d->sql = sql;
0123     d->query = query;
0124 
0125     KDbParser *oldParser = globalParser;
0126     KDbField *oldField = globalField;
0127     globalParser = this;
0128     globalField = nullptr;
0129     bool res = parseData();
0130     globalParser = oldParser;
0131     globalField = oldField;
0132     if (query) { // if existing query was supplied to parse() nullptr should be returned by query()
0133         d->query = nullptr;
0134     }
0135     return res;
0136 }
0137 
0138 void KDbParser::reset()
0139 {
0140     d->reset();
0141 }
0142 
0143 //-------------------------------------
0144 
0145 class Q_DECL_HIDDEN KDbParserError::Private
0146 {
0147 public:
0148     Private() {}
0149     Private(const Private &other) {
0150         copy(other);
0151     }
0152 #define KDbParserErrorPrivateArgs(o) std::tie(o.type, o.message, o.token, o.position)
0153     void copy(const Private &other) {
0154         KDbParserErrorPrivateArgs((*this)) = KDbParserErrorPrivateArgs(other);
0155     }
0156     bool operator==(const Private &other) const {
0157         return KDbParserErrorPrivateArgs((*this)) == KDbParserErrorPrivateArgs(other);
0158     }
0159     QString type;
0160     QString message;
0161     QByteArray token;
0162     int position = -1;
0163 };
0164 
0165 KDbParserError::KDbParserError()
0166     : d(new Private)
0167 {
0168 }
0169 
0170 KDbParserError::KDbParserError(const QString &type, const QString &message, const QByteArray &token,
0171                                int position)
0172     : d(new Private)
0173 {
0174     d->type = type;
0175     d->message = message;
0176     d->token = token;
0177     d->position = position;
0178 }
0179 
0180 KDbParserError::KDbParserError(const KDbParserError &other)
0181     : d(new Private(*other.d))
0182 {
0183     *d = *other.d;
0184 }
0185 
0186 KDbParserError::~KDbParserError()
0187 {
0188     delete d;
0189 }
0190 
0191 KDbParserError& KDbParserError::operator=(const KDbParserError &other)
0192 {
0193     if (this != &other) {
0194         d->copy(*other.d);
0195     }
0196     return *this;
0197 }
0198 
0199 bool KDbParserError::operator==(const KDbParserError &other) const
0200 {
0201     return *d == *other.d;
0202 }
0203 
0204 QString KDbParserError::type() const
0205 {
0206     return d->type;
0207 }
0208 
0209 QString KDbParserError::message() const
0210 {
0211     return d->message;
0212 }
0213 
0214 int KDbParserError::position() const
0215 {
0216     return d->position;
0217 }
0218 
0219 QDebug operator<<(QDebug dbg, const KDbParserError& error)
0220 {
0221     QDebugStateSaver saver(dbg);
0222     if (error.type().isEmpty() && error.message().isEmpty()) {
0223         dbg.space() << "KDb:KDbParserError: None";
0224     } else {
0225         dbg.space() << "KDb:KDbParserError: type=" << error.type() << "message=" << error.message()
0226                     << "pos=" << error.position() << ")";
0227     }
0228     return dbg.maybeSpace();
0229 }