File indexing completed on 2024-10-13 12:38:24
0001 /* This file is part of the KDE project 0002 Copyright (C) 2005-2016 Jarosław Staniek <staniek@kde.org> 0003 0004 This library is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This library is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this library; see the file COPYING.LIB. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 * Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include "KDbPreparedStatement.h" 0021 #include "KDbPreparedStatementInterface.h" 0022 #include "KDbSqlResult.h" 0023 #include "KDbTableSchema.h" 0024 #include "kdb_debug.h" 0025 0026 KDbPreparedStatement::Data::Data() 0027 : Data(InvalidStatement, nullptr, nullptr, QStringList()) 0028 { 0029 } 0030 0031 KDbPreparedStatement::Data::Data(Type _type, KDbPreparedStatementInterface* _iface, 0032 KDbFieldList* _fields, 0033 const QStringList& _whereFieldNames) 0034 : type(_type), fields(_fields), whereFieldNames(_whereFieldNames) 0035 , fieldsForParameters(nullptr), whereFields(nullptr), dirty(true), iface(_iface) 0036 , lastInsertRecordId(std::numeric_limits<quint64>::max()) 0037 { 0038 } 0039 0040 KDbPreparedStatement::Data::~Data() 0041 { 0042 delete iface; 0043 delete whereFields; 0044 } 0045 0046 KDbPreparedStatement::KDbPreparedStatement() 0047 : d( new Data() ) 0048 { 0049 } 0050 0051 KDbPreparedStatement::KDbPreparedStatement(KDbPreparedStatementInterface* iface, 0052 Type type, KDbFieldList* fields, 0053 const QStringList& whereFieldNames) 0054 : d( new Data(type, iface, fields, whereFieldNames) ) 0055 { 0056 } 0057 0058 KDbPreparedStatement::~KDbPreparedStatement() 0059 { 0060 } 0061 0062 bool KDbPreparedStatement::execute(const KDbPreparedStatementParameters& parameters) 0063 { 0064 if (d->dirty) { 0065 KDbEscapedString s; 0066 if (!generateStatementString(&s)) { // sets d->fieldsForParameters too 0067 m_result.setCode(ERR_OTHER); 0068 return false; 0069 } 0070 //! @todo error message? 0071 if (s.isEmpty()) { 0072 m_result.setCode(ERR_OTHER); 0073 return false; 0074 } 0075 if (!d->iface->prepare(s)) { 0076 m_result.setCode(ERR_OTHER); 0077 return false; 0078 } 0079 d->dirty = false; 0080 } 0081 QSharedPointer<KDbSqlResult> result 0082 = d->iface->execute(d->type, *d->fieldsForParameters, d->fields, parameters); 0083 if (!result) { 0084 return false; 0085 } 0086 d->lastInsertRecordId = result->lastInsertRecordId(); 0087 return true; 0088 } 0089 0090 bool KDbPreparedStatement::generateStatementString(KDbEscapedString * s) 0091 { 0092 s->reserve(1024); 0093 switch (d->type) { 0094 case SelectStatement: 0095 return generateSelectStatementString(s); 0096 case InsertStatement: 0097 return generateInsertStatementString(s); 0098 default:; 0099 } 0100 kdbCritical() << "Unsupported type" << d->type; 0101 return false; 0102 } 0103 0104 bool KDbPreparedStatement::generateSelectStatementString(KDbEscapedString * s) 0105 { 0106 //! @todo only tables and trivial queries supported for select... 0107 *s = "SELECT "; 0108 bool first = true; 0109 foreach(KDbField *f, *d->fields->fields()) { 0110 if (first) 0111 first = false; 0112 else 0113 s->append(", "); 0114 s->append(f->name()); 0115 } 0116 // create WHERE 0117 first = true; 0118 delete d->whereFields; 0119 d->whereFields = new KDbField::List(); 0120 foreach(const QString& whereItem, d->whereFieldNames) { 0121 if (first) { 0122 s->append(" WHERE "); 0123 first = false; 0124 } 0125 else 0126 s->append(" AND "); 0127 KDbField *f = d->fields->field(whereItem); 0128 if (!f) { 0129 kdbWarning() << "field" << whereItem << "not found, aborting"; 0130 s->clear(); 0131 return false; 0132 } 0133 d->whereFields->append(f); 0134 s->append(whereItem.toUtf8() + "=?"); 0135 } 0136 d->fieldsForParameters = d->whereFields; 0137 return true; 0138 } 0139 0140 bool KDbPreparedStatement::generateInsertStatementString(KDbEscapedString * s) 0141 { 0142 //! @todo only tables supported for insert; what about views? 0143 KDbTableSchema *table = d->fields->isEmpty() ? nullptr : d->fields->field(0)->table(); 0144 if (!table) 0145 return false; //err 0146 0147 KDbEscapedString namesList; 0148 bool first = true; 0149 //we are using a selection of fields only 0150 const bool allTableFieldsUsed = dynamic_cast<KDbTableSchema*>(d->fields); 0151 foreach(const KDbField* f, *d->fields->fields()) { 0152 if (first) { 0153 s->append("?"); 0154 if (!allTableFieldsUsed) 0155 namesList = KDbEscapedString(f->name()); 0156 first = false; 0157 } else { 0158 s->append(",?"); 0159 if (!allTableFieldsUsed) { 0160 namesList.append(", "); 0161 namesList.append(f->name()); 0162 } 0163 } 0164 } 0165 s->append(")"); 0166 s->prepend(KDbEscapedString("INSERT INTO ") + table->name() 0167 + (allTableFieldsUsed ? KDbEscapedString() : (KDbEscapedString(" (") + namesList + ')')) 0168 + " VALUES ("); 0169 d->fieldsForParameters = d->fields->fields(); 0170 return true; 0171 } 0172 0173 bool KDbPreparedStatement::isValid() const 0174 { 0175 return d->type != InvalidStatement; 0176 } 0177 0178 KDbPreparedStatement::Type KDbPreparedStatement::type() const 0179 { 0180 return d->type; 0181 } 0182 0183 void KDbPreparedStatement::setType(KDbPreparedStatement::Type type) 0184 { 0185 d->type = type; 0186 d->dirty = true; 0187 } 0188 0189 const KDbFieldList* KDbPreparedStatement::fields() const 0190 { 0191 return d->fields; 0192 } 0193 0194 void KDbPreparedStatement::setFields(KDbFieldList* fields) 0195 { 0196 if (fields) { 0197 d->fields = fields; 0198 d->dirty = true; 0199 } 0200 } 0201 0202 QStringList KDbPreparedStatement::whereFieldNames() const 0203 { 0204 return d->whereFieldNames; 0205 } 0206 0207 void KDbPreparedStatement::setWhereFieldNames(const QStringList& whereFieldNames) 0208 { 0209 d->whereFieldNames = whereFieldNames; 0210 d->dirty = true; 0211 } 0212 0213 quint64 KDbPreparedStatement::lastInsertRecordId() const 0214 { 0215 return d->lastInsertRecordId; 0216 } 0217 0218 /*bool KDbPreparedStatement::insert() 0219 { 0220 const bool res = m_conn->drv_prepareStatement(this); 0221 const bool res = m_conn->drv_insertRecord(this); 0222 clearArguments(); 0223 return res; 0224 } 0225 0226 bool KDbPreparedStatement::select() 0227 { 0228 const bool res = m_conn->drv_bindArgumentForPreparedStatement(this, m_args.count()-1); 0229 }*/