Changeset View
Changeset View
Standalone View
Standalone View
src/drivers/sqlite/SqlitePreparedStatement.cpp
Show All 29 Lines | |||||
30 | } | 30 | } | ||
31 | 31 | | |||
32 | SqlitePreparedStatement::~SqlitePreparedStatement() | 32 | SqlitePreparedStatement::~SqlitePreparedStatement() | ||
33 | { | 33 | { | ||
34 | } | 34 | } | ||
35 | 35 | | |||
36 | bool SqlitePreparedStatement::prepare(const KDbEscapedString& sql) | 36 | bool SqlitePreparedStatement::prepare(const KDbEscapedString& sql) | ||
37 | { | 37 | { | ||
38 | m_sqlResult.reset(static_cast<SqliteSqlResult*>(connection->executeSQL(sql))); | 38 | m_sqlResult = connection->prepareSql(sql); | ||
39 | m_result = connection->result(); | 39 | m_result = connection->result(); | ||
40 | return m_sqlResult && !m_result.isError(); | 40 | return m_sqlResult && !m_result.isError(); | ||
41 | } | 41 | } | ||
42 | 42 | | |||
43 | bool SqlitePreparedStatement::bindValue(KDbField *field, const QVariant& value, int par) | 43 | bool SqlitePreparedStatement::bindValue(KDbField *field, const QVariant& value, int par) | ||
44 | { | 44 | { | ||
45 | if (value.isNull()) { | 45 | if (value.isNull()) { | ||
46 | //no value to bind or the value is null: bind NULL | 46 | //no value to bind or the value is null: bind NULL | ||
47 | int res = sqlite3_bind_null(m_sqlResult->prepared_st, par); | 47 | int res = sqlite3_bind_null(sqlResult()->prepared_st, par); | ||
48 | if (res != SQLITE_OK) { | 48 | if (res != SQLITE_OK) { | ||
49 | m_result.setServerErrorCode(res); | 49 | m_result.setServerErrorCode(res); | ||
50 | storeResult(&m_result); | 50 | storeResult(&m_result); | ||
51 | return false; | 51 | return false; | ||
52 | } | 52 | } | ||
53 | return true; | 53 | return true; | ||
54 | } | 54 | } | ||
55 | if (field->isTextType()) { | 55 | if (field->isTextType()) { | ||
56 | //! @todo optimize: make a static copy so SQLITE_STATIC can be used | 56 | //! @todo optimize: make a static copy so SQLITE_STATIC can be used | ||
57 | const QByteArray utf8String(value.toString().toUtf8()); | 57 | const QByteArray utf8String(value.toString().toUtf8()); | ||
58 | int res = sqlite3_bind_text(m_sqlResult->prepared_st, par, | 58 | int res = sqlite3_bind_text(sqlResult()->prepared_st, par, | ||
59 | utf8String.constData(), utf8String.length(), SQLITE_TRANSIENT /*??*/); | 59 | utf8String.constData(), utf8String.length(), SQLITE_TRANSIENT /*??*/); | ||
60 | if (res != SQLITE_OK) { | 60 | if (res != SQLITE_OK) { | ||
61 | m_result.setServerErrorCode(res); | 61 | m_result.setServerErrorCode(res); | ||
62 | storeResult(&m_result); | 62 | storeResult(&m_result); | ||
63 | return false; | 63 | return false; | ||
64 | } | 64 | } | ||
65 | return true; | 65 | return true; | ||
66 | } | 66 | } | ||
67 | 67 | | |||
68 | switch (field->type()) { | 68 | switch (field->type()) { | ||
69 | case KDbField::Byte: | 69 | case KDbField::Byte: | ||
70 | case KDbField::ShortInteger: | 70 | case KDbField::ShortInteger: | ||
71 | case KDbField::Integer: { | 71 | case KDbField::Integer: { | ||
72 | //! @todo what about unsigned > INT_MAX ? | 72 | //! @todo what about unsigned > INT_MAX ? | ||
73 | bool ok; | 73 | bool ok; | ||
74 | const int intValue = value.toInt(&ok); | 74 | const int intValue = value.toInt(&ok); | ||
75 | if (ok) { | 75 | if (ok) { | ||
76 | int res = sqlite3_bind_int(m_sqlResult->prepared_st, par, intValue); | 76 | int res = sqlite3_bind_int(sqlResult()->prepared_st, par, intValue); | ||
77 | if (res != SQLITE_OK) { | 77 | if (res != SQLITE_OK) { | ||
78 | m_result.setServerErrorCode(res); | 78 | m_result.setServerErrorCode(res); | ||
79 | storeResult(&m_result); | 79 | storeResult(&m_result); | ||
80 | return false; | 80 | return false; | ||
81 | } | 81 | } | ||
82 | } else { | 82 | } else { | ||
83 | int res = sqlite3_bind_null(m_sqlResult->prepared_st, par); | 83 | int res = sqlite3_bind_null(sqlResult()->prepared_st, par); | ||
84 | if (res != SQLITE_OK) { | 84 | if (res != SQLITE_OK) { | ||
85 | m_result.setServerErrorCode(res); | 85 | m_result.setServerErrorCode(res); | ||
86 | storeResult(&m_result); | 86 | storeResult(&m_result); | ||
87 | return false; | 87 | return false; | ||
88 | } | 88 | } | ||
89 | } | 89 | } | ||
90 | break; | 90 | break; | ||
91 | } | 91 | } | ||
92 | case KDbField::Float: | 92 | case KDbField::Float: | ||
93 | case KDbField::Double: { | 93 | case KDbField::Double: { | ||
94 | int res = sqlite3_bind_double(m_sqlResult->prepared_st, par, value.toDouble()); | 94 | int res = sqlite3_bind_double(sqlResult()->prepared_st, par, value.toDouble()); | ||
95 | if (res != SQLITE_OK) { | 95 | if (res != SQLITE_OK) { | ||
96 | m_result.setServerErrorCode(res); | 96 | m_result.setServerErrorCode(res); | ||
97 | storeResult(&m_result); | 97 | storeResult(&m_result); | ||
98 | return false; | 98 | return false; | ||
99 | } | 99 | } | ||
100 | break; | 100 | break; | ||
101 | } | 101 | } | ||
102 | case KDbField::BigInteger: { | 102 | case KDbField::BigInteger: { | ||
103 | //! @todo what about unsigned > LLONG_MAX ? | 103 | //! @todo what about unsigned > LLONG_MAX ? | ||
104 | bool ok; | 104 | bool ok; | ||
105 | const qint64 int64Value = value.toLongLong(&ok); | 105 | const qint64 int64Value = value.toLongLong(&ok); | ||
106 | if (ok) { | 106 | if (ok) { | ||
107 | int res = sqlite3_bind_int64(m_sqlResult->prepared_st, par, int64Value); | 107 | int res = sqlite3_bind_int64(sqlResult()->prepared_st, par, int64Value); | ||
108 | if (res != SQLITE_OK) { | 108 | if (res != SQLITE_OK) { | ||
109 | m_result.setServerErrorCode(res); | 109 | m_result.setServerErrorCode(res); | ||
110 | storeResult(&m_result); | 110 | storeResult(&m_result); | ||
111 | return false; | 111 | return false; | ||
112 | } | 112 | } | ||
113 | } else { | 113 | } else { | ||
114 | int res = sqlite3_bind_null(m_sqlResult->prepared_st, par); | 114 | int res = sqlite3_bind_null(sqlResult()->prepared_st, par); | ||
115 | if (res != SQLITE_OK) { | 115 | if (res != SQLITE_OK) { | ||
116 | m_result.setServerErrorCode(res); | 116 | m_result.setServerErrorCode(res); | ||
117 | storeResult(&m_result); | 117 | storeResult(&m_result); | ||
118 | return false; | 118 | return false; | ||
119 | } | 119 | } | ||
120 | } | 120 | } | ||
121 | break; | 121 | break; | ||
122 | } | 122 | } | ||
123 | case KDbField::Boolean: { | 123 | case KDbField::Boolean: { | ||
124 | int res = sqlite3_bind_text(m_sqlResult->prepared_st, par, value.toBool() ? "1" : "0", | 124 | int res = sqlite3_bind_text(sqlResult()->prepared_st, par, value.toBool() ? "1" : "0", | ||
125 | 1, SQLITE_TRANSIENT /*??*/); | 125 | 1, SQLITE_TRANSIENT /*??*/); | ||
126 | if (res != SQLITE_OK) { | 126 | if (res != SQLITE_OK) { | ||
127 | m_result.setServerErrorCode(res); | 127 | m_result.setServerErrorCode(res); | ||
128 | storeResult(&m_result); | 128 | storeResult(&m_result); | ||
129 | return false; | 129 | return false; | ||
130 | } | 130 | } | ||
131 | break; | 131 | break; | ||
132 | } | 132 | } | ||
133 | case KDbField::Time: { | 133 | case KDbField::Time: { | ||
134 | int res = sqlite3_bind_text(m_sqlResult->prepared_st, par, | 134 | int res = sqlite3_bind_text(sqlResult()->prepared_st, par, | ||
135 | qPrintable(value.toTime().toString(Qt::ISODate)), | 135 | qPrintable(value.toTime().toString(Qt::ISODate)), | ||
136 | QLatin1String("HH:MM:SS").size(), SQLITE_TRANSIENT /*??*/); | 136 | QLatin1String("HH:MM:SS").size(), SQLITE_TRANSIENT /*??*/); | ||
137 | if (res != SQLITE_OK) { | 137 | if (res != SQLITE_OK) { | ||
138 | m_result.setServerErrorCode(res); | 138 | m_result.setServerErrorCode(res); | ||
139 | storeResult(&m_result); | 139 | storeResult(&m_result); | ||
140 | return false; | 140 | return false; | ||
141 | } | 141 | } | ||
142 | break; | 142 | break; | ||
143 | } | 143 | } | ||
144 | case KDbField::Date: { | 144 | case KDbField::Date: { | ||
145 | int res = sqlite3_bind_text(m_sqlResult->prepared_st, par, | 145 | int res = sqlite3_bind_text(sqlResult()->prepared_st, par, | ||
146 | qPrintable(value.toDate().toString(Qt::ISODate)), | 146 | qPrintable(value.toDate().toString(Qt::ISODate)), | ||
147 | QLatin1String("YYYY-MM-DD").size(), SQLITE_TRANSIENT /*??*/); | 147 | QLatin1String("YYYY-MM-DD").size(), SQLITE_TRANSIENT /*??*/); | ||
148 | if (res != SQLITE_OK) { | 148 | if (res != SQLITE_OK) { | ||
149 | m_result.setServerErrorCode(res); | 149 | m_result.setServerErrorCode(res); | ||
150 | storeResult(&m_result); | 150 | storeResult(&m_result); | ||
151 | return false; | 151 | return false; | ||
152 | } | 152 | } | ||
153 | break; | 153 | break; | ||
154 | } | 154 | } | ||
155 | case KDbField::DateTime: { | 155 | case KDbField::DateTime: { | ||
156 | int res = sqlite3_bind_text(m_sqlResult->prepared_st, par, | 156 | int res = sqlite3_bind_text(sqlResult()->prepared_st, par, | ||
157 | qPrintable(value.toDateTime().toString(Qt::ISODate)), | 157 | qPrintable(value.toDateTime().toString(Qt::ISODate)), | ||
158 | QLatin1String("YYYY-MM-DDTHH:MM:SS").size(), SQLITE_TRANSIENT /*??*/); | 158 | QLatin1String("YYYY-MM-DDTHH:MM:SS").size(), SQLITE_TRANSIENT /*??*/); | ||
159 | if (res != SQLITE_OK) { | 159 | if (res != SQLITE_OK) { | ||
160 | m_result.setServerErrorCode(res); | 160 | m_result.setServerErrorCode(res); | ||
161 | storeResult(&m_result); | 161 | storeResult(&m_result); | ||
162 | return false; | 162 | return false; | ||
163 | } | 163 | } | ||
164 | break; | 164 | break; | ||
165 | } | 165 | } | ||
166 | case KDbField::BLOB: { | 166 | case KDbField::BLOB: { | ||
167 | const QByteArray byteArray(value.toByteArray()); | 167 | const QByteArray byteArray(value.toByteArray()); | ||
168 | int res = sqlite3_bind_blob(m_sqlResult->prepared_st, par, | 168 | int res = sqlite3_bind_blob(sqlResult()->prepared_st, par, | ||
169 | byteArray.constData(), byteArray.size(), SQLITE_TRANSIENT /*??*/); | 169 | byteArray.constData(), byteArray.size(), SQLITE_TRANSIENT /*??*/); | ||
170 | if (res != SQLITE_OK) { | 170 | if (res != SQLITE_OK) { | ||
171 | m_result.setServerErrorCode(res); | 171 | m_result.setServerErrorCode(res); | ||
172 | storeResult(&m_result); | 172 | storeResult(&m_result); | ||
173 | return false; | 173 | return false; | ||
174 | } | 174 | } | ||
175 | break; | 175 | break; | ||
176 | } | 176 | } | ||
177 | default: { | 177 | default: { | ||
178 | sqliteWarning() << "unsupported field type:" | 178 | sqliteWarning() << "unsupported field type:" | ||
179 | << field->type() << "- NULL value bound to column #" << par; | 179 | << field->type() << "- NULL value bound to column #" << par; | ||
180 | int res = sqlite3_bind_null(m_sqlResult->prepared_st, par); | 180 | int res = sqlite3_bind_null(sqlResult()->prepared_st, par); | ||
181 | if (res != SQLITE_OK) { | 181 | if (res != SQLITE_OK) { | ||
182 | m_result.setServerErrorCode(res); | 182 | m_result.setServerErrorCode(res); | ||
183 | storeResult(&m_result); | 183 | storeResult(&m_result); | ||
184 | return false; | 184 | return false; | ||
185 | } | 185 | } | ||
186 | } | 186 | } | ||
187 | } //switch | 187 | } //switch | ||
188 | return true; | 188 | return true; | ||
189 | } | 189 | } | ||
190 | 190 | | |||
191 | KDbSqlResult* SqlitePreparedStatement::execute( | 191 | QSharedPointer<KDbSqlResult> SqlitePreparedStatement::execute( | ||
192 | KDbPreparedStatement::Type type, | 192 | KDbPreparedStatement::Type type, | ||
193 | const KDbField::List& selectFieldList, | 193 | const KDbField::List& selectFieldList, | ||
194 | KDbFieldList* insertFieldList, | 194 | KDbFieldList* insertFieldList, | ||
195 | const KDbPreparedStatementParameters& parameters, bool *resultOwned) | 195 | const KDbPreparedStatementParameters& parameters) | ||
196 | { | 196 | { | ||
197 | Q_UNUSED(insertFieldList); | 197 | Q_UNUSED(insertFieldList); | ||
198 | Q_UNUSED(resultOwned); | 198 | if (!sqlResult()->prepared_st) { | ||
199 | if (!m_sqlResult->prepared_st) { | 199 | return QSharedPointer<KDbSqlResult>(); | ||
200 | return nullptr; | | |||
201 | } | 200 | } | ||
202 | 201 | | |||
203 | int par = 1; // par.index counted from 1 | 202 | int par = 1; // par.index counted from 1 | ||
204 | KDbField::ListIterator itFields(selectFieldList.constBegin()); | 203 | KDbField::ListIterator itFields(selectFieldList.constBegin()); | ||
205 | for (QList<QVariant>::ConstIterator it = parameters.constBegin(); | 204 | for (QList<QVariant>::ConstIterator it = parameters.constBegin(); | ||
206 | itFields != selectFieldList.constEnd(); | 205 | itFields != selectFieldList.constEnd(); | ||
207 | it += (it == parameters.constEnd() ? 0 : 1), ++itFields, par++) | 206 | it += (it == parameters.constEnd() ? 0 : 1), ++itFields, par++) | ||
208 | { | 207 | { | ||
209 | if (!bindValue(*itFields, it == parameters.constEnd() ? QVariant() : *it, par)) | 208 | if (!bindValue(*itFields, it == parameters.constEnd() ? QVariant() : *it, par)) | ||
210 | return nullptr; | 209 | return QSharedPointer<KDbSqlResult>(); | ||
211 | } | 210 | } | ||
212 | 211 | | |||
213 | //real execution | 212 | //real execution | ||
214 | const int res = sqlite3_step(m_sqlResult->prepared_st); | 213 | const int res = sqlite3_step(sqlResult()->prepared_st); | ||
215 | if (type == KDbPreparedStatement::InsertStatement) { | 214 | if (type == KDbPreparedStatement::InsertStatement) { | ||
216 | const bool ok = res == SQLITE_DONE; | 215 | const bool ok = res == SQLITE_DONE; | ||
217 | if (ok) { | 216 | if (ok) { | ||
218 | m_result = KDbResult(); | 217 | m_result = KDbResult(); | ||
219 | } else { | 218 | } else { | ||
220 | m_result.setServerErrorCode(res); | 219 | m_result.setServerErrorCode(res); | ||
221 | storeResult(&m_result); | 220 | storeResult(&m_result); | ||
222 | sqliteWarning() << m_result << QString::fromLatin1(sqlite3_sql(m_sqlResult->prepared_st)); | 221 | sqliteWarning() << m_result << QString::fromLatin1(sqlite3_sql(sqlResult()->prepared_st)); | ||
223 | } | 222 | } | ||
224 | (void)sqlite3_reset(m_sqlResult->prepared_st); | 223 | (void)sqlite3_reset(sqlResult()->prepared_st); | ||
225 | return m_sqlResult.data(); | 224 | return m_sqlResult; | ||
226 | } | 225 | } | ||
227 | else if (type == KDbPreparedStatement::SelectStatement) { | 226 | else if (type == KDbPreparedStatement::SelectStatement) { | ||
228 | //! @todo fetch result | 227 | //! @todo fetch result | ||
229 | const bool ok = res == SQLITE_ROW; | 228 | const bool ok = res == SQLITE_ROW; | ||
230 | storeResult(&m_result); | 229 | storeResult(&m_result); | ||
231 | if (ok) { | 230 | if (ok) { | ||
232 | m_result = KDbResult(); | 231 | m_result = KDbResult(); | ||
233 | } else { | 232 | } else { | ||
234 | m_result.setServerErrorCode(res); | 233 | m_result.setServerErrorCode(res); | ||
235 | storeResult(&m_result); | 234 | storeResult(&m_result); | ||
236 | sqliteWarning() << m_result << QString::fromLatin1(sqlite3_sql(m_sqlResult->prepared_st)); | 235 | sqliteWarning() << m_result << QString::fromLatin1(sqlite3_sql(sqlResult()->prepared_st)); | ||
237 | } | 236 | } | ||
238 | (void)sqlite3_reset(m_sqlResult->prepared_st); | 237 | (void)sqlite3_reset(sqlResult()->prepared_st); | ||
239 | return m_sqlResult.data(); | 238 | return m_sqlResult; | ||
240 | } | 239 | } | ||
241 | return nullptr; | 240 | return QSharedPointer<KDbSqlResult>(); | ||
242 | } | 241 | } |