File indexing completed on 2024-04-28 15:58:54
0001 /* This file is part of the KDE project 0002 Copyright (C) 2005-2012 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 "SqlitePreparedStatement.h" 0021 #include "KDbPreparedStatement.h" 0022 #include "sqlite_debug.h" 0023 0024 SqlitePreparedStatement::SqlitePreparedStatement(SqliteConnectionInternal* conn) 0025 : KDbPreparedStatementInterface() 0026 , SqliteConnectionInternal(conn->connection) 0027 { 0028 data_owned = false; 0029 data = conn->data; //copy 0030 } 0031 0032 SqlitePreparedStatement::~SqlitePreparedStatement() 0033 { 0034 } 0035 0036 bool SqlitePreparedStatement::prepare(const KDbEscapedString& sql) 0037 { 0038 m_sqlResult = connection->prepareSql(sql); 0039 m_result = connection->result(); 0040 return m_sqlResult && !m_result.isError(); 0041 } 0042 0043 bool SqlitePreparedStatement::bindValue(KDbField *field, const QVariant& value, int par) 0044 { 0045 if (value.isNull()) { 0046 //no value to bind or the value is null: bind NULL 0047 int res = sqlite3_bind_null(sqlResult()->prepared_st, par); 0048 if (res != SQLITE_OK) { 0049 m_result.setServerErrorCode(res); 0050 storeResult(&m_result); 0051 return false; 0052 } 0053 return true; 0054 } 0055 if (field->isTextType()) { 0056 //! @todo optimize: make a static copy so SQLITE_STATIC can be used 0057 const QByteArray utf8String(value.toString().toUtf8()); 0058 int res = sqlite3_bind_text(sqlResult()->prepared_st, par, 0059 utf8String.constData(), utf8String.length(), SQLITE_TRANSIENT /*??*/); 0060 if (res != SQLITE_OK) { 0061 m_result.setServerErrorCode(res); 0062 storeResult(&m_result); 0063 return false; 0064 } 0065 return true; 0066 } 0067 0068 switch (field->type()) { 0069 case KDbField::Byte: 0070 case KDbField::ShortInteger: 0071 case KDbField::Integer: { 0072 //! @todo what about unsigned > INT_MAX ? 0073 bool ok; 0074 const int intValue = value.toInt(&ok); 0075 if (ok) { 0076 int res = sqlite3_bind_int(sqlResult()->prepared_st, par, intValue); 0077 if (res != SQLITE_OK) { 0078 m_result.setServerErrorCode(res); 0079 storeResult(&m_result); 0080 return false; 0081 } 0082 } else { 0083 int res = sqlite3_bind_null(sqlResult()->prepared_st, par); 0084 if (res != SQLITE_OK) { 0085 m_result.setServerErrorCode(res); 0086 storeResult(&m_result); 0087 return false; 0088 } 0089 } 0090 break; 0091 } 0092 case KDbField::Float: 0093 case KDbField::Double: { 0094 int res = sqlite3_bind_double(sqlResult()->prepared_st, par, value.toDouble()); 0095 if (res != SQLITE_OK) { 0096 m_result.setServerErrorCode(res); 0097 storeResult(&m_result); 0098 return false; 0099 } 0100 break; 0101 } 0102 case KDbField::BigInteger: { 0103 //! @todo what about unsigned > LLONG_MAX ? 0104 bool ok; 0105 const qint64 int64Value = value.toLongLong(&ok); 0106 if (ok) { 0107 int res = sqlite3_bind_int64(sqlResult()->prepared_st, par, int64Value); 0108 if (res != SQLITE_OK) { 0109 m_result.setServerErrorCode(res); 0110 storeResult(&m_result); 0111 return false; 0112 } 0113 } else { 0114 int res = sqlite3_bind_null(sqlResult()->prepared_st, par); 0115 if (res != SQLITE_OK) { 0116 m_result.setServerErrorCode(res); 0117 storeResult(&m_result); 0118 return false; 0119 } 0120 } 0121 break; 0122 } 0123 case KDbField::Boolean: { 0124 int res = sqlite3_bind_text(sqlResult()->prepared_st, par, value.toBool() ? "1" : "0", 0125 1, SQLITE_TRANSIENT /*??*/); 0126 if (res != SQLITE_OK) { 0127 m_result.setServerErrorCode(res); 0128 storeResult(&m_result); 0129 return false; 0130 } 0131 break; 0132 } 0133 case KDbField::Time: { 0134 int res = sqlite3_bind_text(sqlResult()->prepared_st, par, 0135 qPrintable(KDbUtils::toISODateStringWithMs(value.toTime())), 0136 QLatin1String("HH:MM:SS").size(), SQLITE_TRANSIENT /*??*/); 0137 if (res != SQLITE_OK) { 0138 m_result.setServerErrorCode(res); 0139 storeResult(&m_result); 0140 return false; 0141 } 0142 break; 0143 } 0144 case KDbField::Date: { 0145 int res = sqlite3_bind_text(sqlResult()->prepared_st, par, 0146 qPrintable(value.toDate().toString(Qt::ISODate)), 0147 QLatin1String("YYYY-MM-DD").size(), SQLITE_TRANSIENT /*??*/); 0148 if (res != SQLITE_OK) { 0149 m_result.setServerErrorCode(res); 0150 storeResult(&m_result); 0151 return false; 0152 } 0153 break; 0154 } 0155 case KDbField::DateTime: { 0156 int res = sqlite3_bind_text(sqlResult()->prepared_st, par, 0157 qPrintable(KDbUtils::toISODateStringWithMs(value.toDateTime())), 0158 QLatin1String("YYYY-MM-DDTHH:MM:SS").size(), SQLITE_TRANSIENT /*??*/); 0159 if (res != SQLITE_OK) { 0160 m_result.setServerErrorCode(res); 0161 storeResult(&m_result); 0162 return false; 0163 } 0164 break; 0165 } 0166 case KDbField::BLOB: { 0167 const QByteArray byteArray(value.toByteArray()); 0168 int res = sqlite3_bind_blob(sqlResult()->prepared_st, par, 0169 byteArray.constData(), byteArray.size(), SQLITE_TRANSIENT /*??*/); 0170 if (res != SQLITE_OK) { 0171 m_result.setServerErrorCode(res); 0172 storeResult(&m_result); 0173 return false; 0174 } 0175 break; 0176 } 0177 default: { 0178 sqliteWarning() << "unsupported field type:" 0179 << field->type() << "- NULL value bound to column #" << par; 0180 int res = sqlite3_bind_null(sqlResult()->prepared_st, par); 0181 if (res != SQLITE_OK) { 0182 m_result.setServerErrorCode(res); 0183 storeResult(&m_result); 0184 return false; 0185 } 0186 } 0187 } //switch 0188 return true; 0189 } 0190 0191 QSharedPointer<KDbSqlResult> SqlitePreparedStatement::execute( 0192 KDbPreparedStatement::Type type, 0193 const KDbField::List& selectFieldList, 0194 KDbFieldList* insertFieldList, 0195 const KDbPreparedStatementParameters& parameters) 0196 { 0197 Q_UNUSED(insertFieldList); 0198 if (!sqlResult()->prepared_st) { 0199 return QSharedPointer<KDbSqlResult>(); 0200 } 0201 0202 int par = 1; // par.index counted from 1 0203 KDbField::ListIterator itFields(selectFieldList.constBegin()); 0204 for (QList<QVariant>::ConstIterator it = parameters.constBegin(); 0205 itFields != selectFieldList.constEnd(); 0206 it += (it == parameters.constEnd() ? 0 : 1), ++itFields, par++) 0207 { 0208 if (!bindValue(*itFields, it == parameters.constEnd() ? QVariant() : *it, par)) 0209 return QSharedPointer<KDbSqlResult>(); 0210 } 0211 0212 //real execution 0213 const int res = sqlite3_step(sqlResult()->prepared_st); 0214 if (type == KDbPreparedStatement::InsertStatement) { 0215 const bool ok = res == SQLITE_DONE; 0216 if (ok) { 0217 m_result = KDbResult(); 0218 } else { 0219 m_result.setServerErrorCode(res); 0220 storeResult(&m_result); 0221 sqliteWarning() << m_result << QString::fromLatin1(sqlite3_sql(sqlResult()->prepared_st)); 0222 } 0223 (void)sqlite3_reset(sqlResult()->prepared_st); 0224 return m_sqlResult; 0225 } 0226 else if (type == KDbPreparedStatement::SelectStatement) { 0227 //! @todo fetch result 0228 const bool ok = res == SQLITE_ROW; 0229 storeResult(&m_result); 0230 if (ok) { 0231 m_result = KDbResult(); 0232 } else { 0233 m_result.setServerErrorCode(res); 0234 storeResult(&m_result); 0235 sqliteWarning() << m_result << QString::fromLatin1(sqlite3_sql(sqlResult()->prepared_st)); 0236 } 0237 (void)sqlite3_reset(sqlResult()->prepared_st); 0238 return m_sqlResult; 0239 } 0240 return QSharedPointer<KDbSqlResult>(); 0241 }