KDb

KDbPreparedStatement.cpp
1 /* This file is part of the KDE project
2  Copyright (C) 2005-2016 JarosÅ‚aw Staniek <[email protected]>
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 
26 KDbPreparedStatement::Data::Data()
27  : Data(InvalidStatement, nullptr, nullptr, QStringList())
28 {
29 }
30 
31 KDbPreparedStatement::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 
40 KDbPreparedStatement::Data::~Data()
41 {
42  delete iface;
43  delete whereFields;
44 }
45 
47  : d( new Data() )
48 {
49 }
50 
52  Type type, KDbFieldList* fields,
53  const QStringList& whereFieldNames)
54  : d( new Data(type, iface, fields, whereFieldNames) )
55 {
56 }
57 
58 KDbPreparedStatement::~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 
90 bool 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 
104 bool 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 
140 bool 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 
173 bool KDbPreparedStatement::isValid() const
174 {
175  return d->type != InvalidStatement;
176 }
177 
178 KDbPreparedStatement::Type KDbPreparedStatement::type() const
179 {
180  return d->type;
181 }
182 
183 void KDbPreparedStatement::setType(KDbPreparedStatement::Type type)
184 {
185  d->type = type;
186  d->dirty = true;
187 }
188 
189 const 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 
202 QStringList KDbPreparedStatement::whereFieldNames() const
203 {
204  return d->whereFieldNames;
205 }
206 
207 void 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 
226 bool KDbPreparedStatement::select()
227 {
228  const bool res = m_conn->drv_bindArgumentForPreparedStatement(this, m_args.count()-1);
229 }*/
@ InsertStatement
INSERT statement will be prepared end executed.
@ SelectStatement
SELECT statement will be prepared end executed.
Specialized string for escaping.
QString name
@ InvalidStatement
Used only in invalid statements.
KDbPreparedStatement()
Creates an invalid prepared statement.
QByteArray toUtf8() const const
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
Type
Defines type of the prepared statement.
Prepared statement interface for backend-dependent implementations.
void setFields(KDbFieldList *fields)
Sets fields for the statement. Does nothing if fields is nullptr.
Meta-data for a field.
Definition: KDbField.h:71
QString name() const
Definition: KDbField.cpp:256
bool execute(const KDbPreparedStatementParameters &parameters)
KDbUtils::AutodeletedList< KDbField * > List
list of fields
Definition: KDbField.h:77
KDbField::List * whereFields
temporary, used for select statements, based on whereFieldNames
quint64 lastInsertRecordId() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Thu Oct 6 2022 04:04:38 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.