KDb

KDbPreparedStatement.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2005-2016 Jarosław Staniek <staniek@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18*/
19
20#include "KDbPreparedStatement.h"
21#include "KDbPreparedStatementInterface.h"
22#include "KDbSqlResult.h"
23#include "KDbTableSchema.h"
24#include "kdb_debug.h"
25
26KDbPreparedStatement::Data::Data()
27 : Data(InvalidStatement, nullptr, nullptr, QStringList())
28{
29}
30
31KDbPreparedStatement::Data::Data(Type _type, KDbPreparedStatementInterface* _iface,
32 KDbFieldList* _fields,
33 const QStringList& _whereFieldNames)
34 : type(_type), fields(_fields), whereFieldNames(_whereFieldNames)
35 , fieldsForParameters(nullptr), whereFields(nullptr), dirty(true), iface(_iface)
36 , lastInsertRecordId(std::numeric_limits<quint64>::max())
37{
38}
39
40KDbPreparedStatement::Data::~Data()
41{
42 delete iface;
43 delete whereFields;
44}
45
50
52 Type type, KDbFieldList* fields,
53 const QStringList& whereFieldNames)
54 : d( new Data(type, iface, fields, whereFieldNames) )
55{
56}
57
58KDbPreparedStatement::~KDbPreparedStatement()
59{
60}
61
63{
64 if (d->dirty) {
66 if (!generateStatementString(&s)) { // sets d->fieldsForParameters too
67 m_result.setCode(ERR_OTHER);
68 return false;
69 }
70//! @todo error message?
71 if (s.isEmpty()) {
72 m_result.setCode(ERR_OTHER);
73 return false;
74 }
75 if (!d->iface->prepare(s)) {
76 m_result.setCode(ERR_OTHER);
77 return false;
78 }
79 d->dirty = false;
80 }
82 = d->iface->execute(d->type, *d->fieldsForParameters, d->fields, parameters);
83 if (!result) {
84 return false;
85 }
86 d->lastInsertRecordId = result->lastInsertRecordId();
87 return true;
88}
89
90bool KDbPreparedStatement::generateStatementString(KDbEscapedString * s)
91{
92 s->reserve(1024);
93 switch (d->type) {
94 case SelectStatement:
95 return generateSelectStatementString(s);
96 case InsertStatement:
97 return generateInsertStatementString(s);
98 default:;
99 }
100 kdbCritical() << "Unsupported type" << d->type;
101 return false;
102}
103
104bool KDbPreparedStatement::generateSelectStatementString(KDbEscapedString * s)
105{
106//! @todo only tables and trivial queries supported for select...
107 *s = "SELECT ";
108 bool first = true;
109 foreach(KDbField *f, *d->fields->fields()) {
110 if (first)
111 first = false;
112 else
113 s->append(", ");
114 s->append(f->name());
115 }
116 // create WHERE
117 first = true;
118 delete d->whereFields;
119 d->whereFields = new KDbField::List();
120 foreach(const QString& whereItem, d->whereFieldNames) {
121 if (first) {
122 s->append(" WHERE ");
123 first = false;
124 }
125 else
126 s->append(" AND ");
127 KDbField *f = d->fields->field(whereItem);
128 if (!f) {
129 kdbWarning() << "field" << whereItem << "not found, aborting";
130 s->clear();
131 return false;
132 }
133 d->whereFields->append(f);
134 s->append(whereItem.toUtf8() + "=?");
135 }
136 d->fieldsForParameters = d->whereFields;
137 return true;
138}
139
140bool KDbPreparedStatement::generateInsertStatementString(KDbEscapedString * s)
141{
142 //! @todo only tables supported for insert; what about views?
143 KDbTableSchema *table = d->fields->isEmpty() ? nullptr : d->fields->field(0)->table();
144 if (!table)
145 return false; //err
146
147 KDbEscapedString namesList;
148 bool first = true;
149 //we are using a selection of fields only
150 const bool allTableFieldsUsed = dynamic_cast<KDbTableSchema*>(d->fields);
151 foreach(const KDbField* f, *d->fields->fields()) {
152 if (first) {
153 s->append("?");
154 if (!allTableFieldsUsed)
155 namesList = KDbEscapedString(f->name());
156 first = false;
157 } else {
158 s->append(",?");
159 if (!allTableFieldsUsed) {
160 namesList.append(", ");
161 namesList.append(f->name());
162 }
163 }
164 }
165 s->append(")");
166 s->prepend(KDbEscapedString("INSERT INTO ") + table->name()
167 + (allTableFieldsUsed ? KDbEscapedString() : (KDbEscapedString(" (") + namesList + ')'))
168 + " VALUES (");
169 d->fieldsForParameters = d->fields->fields();
170 return true;
171}
172
173bool KDbPreparedStatement::isValid() const
174{
175 return d->type != InvalidStatement;
176}
177
178KDbPreparedStatement::Type KDbPreparedStatement::type() const
179{
180 return d->type;
181}
182
183void KDbPreparedStatement::setType(KDbPreparedStatement::Type type)
184{
185 d->type = type;
186 d->dirty = true;
187}
188
189const KDbFieldList* KDbPreparedStatement::fields() const
190{
191 return d->fields;
192}
193
195{
196 if (fields) {
197 d->fields = fields;
198 d->dirty = true;
199 }
200}
201
202QStringList KDbPreparedStatement::whereFieldNames() const
203{
204 return d->whereFieldNames;
205}
206
207void KDbPreparedStatement::setWhereFieldNames(const QStringList& whereFieldNames)
208{
209 d->whereFieldNames = whereFieldNames;
210 d->dirty = true;
211}
212
214{
215 return d->lastInsertRecordId;
216}
217
218/*bool KDbPreparedStatement::insert()
219{
220 const bool res = m_conn->drv_prepareStatement(this);
221 const bool res = m_conn->drv_insertRecord(this);
222 clearArguments();
223 return res;
224}
225
226bool KDbPreparedStatement::select()
227{
228 const bool res = m_conn->drv_bindArgumentForPreparedStatement(this, m_args.count()-1);
229}*/
Specialized string for escaping.
Meta-data for a field.
Definition KDbField.h:72
QString name() const
Definition KDbField.cpp:256
KDbUtils::AutodeletedList< KDbField * > List
list of fields
Definition KDbField.h:77
Prepared statement interface for backend-dependent implementations.
KDbField::List * whereFields
temporary, used for select statements, based on whereFieldNames
void setFields(KDbFieldList *fields)
Sets fields for the statement. Does nothing if fields is nullptr.
KDbPreparedStatement()
Creates an invalid prepared statement.
bool execute(const KDbPreparedStatementParameters &parameters)
Type
Defines type of the prepared statement.
@ InsertStatement
INSERT statement will be prepared end executed.
@ InvalidStatement
Used only in invalid statements.
@ SelectStatement
SELECT statement will be prepared end executed.
Type type(const QSqlDatabase &db)
QByteArray toUtf8() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:20:59 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.