kexi
driver.cpp00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <kexidb/driver.h>
00021 #include <kexidb/driver_p.h>
00022 #include <kexidb/drivermanager.h>
00023 #include <kexidb/drivermanager_p.h>
00024 #include "error.h"
00025 #include "drivermanager.h"
00026 #include "connection.h"
00027 #include "connectiondata.h"
00028 #include "admin.h"
00029
00030 #include <qfileinfo.h>
00031
00032 #include <klocale.h>
00033 #include <kdebug.h>
00034
00035 #include <assert.h>
00036
00037 using namespace KexiDB;
00038
00041 QValueVector<QString> dflt_typeNames;
00042
00043
00044
00045
00046
00047 DriverBehaviour::DriverBehaviour()
00048 : UNSIGNED_TYPE_KEYWORD("UNSIGNED")
00049 , AUTO_INCREMENT_FIELD_OPTION("AUTO_INCREMENT")
00050 , AUTO_INCREMENT_PK_FIELD_OPTION("AUTO_INCREMENT PRIMARY KEY")
00051 , SPECIAL_AUTO_INCREMENT_DEF(false)
00052 , AUTO_INCREMENT_REQUIRES_PK(false)
00053 , ROW_ID_FIELD_RETURNS_LAST_AUTOINCREMENTED_VALUE(false)
00054 , QUOTATION_MARKS_FOR_IDENTIFIER('"')
00055 , USING_DATABASE_REQUIRED_TO_CONNECT(true)
00056 , _1ST_ROW_READ_AHEAD_REQUIRED_TO_KNOW_IF_THE_RESULT_IS_EMPTY(false)
00057 , SELECT_1_SUBQUERY_SUPPORTED(false)
00058 , SQL_KEYWORDS(0)
00059 {
00060 }
00061
00062
00063
00064 Driver::Info::Info()
00065 : fileBased(false)
00066 , allowImportingTo(true)
00067 {
00068 }
00069
00070
00071
00072 Driver::Driver( QObject *parent, const char *name, const QStringList & )
00073 : QObject( parent, name )
00074 , Object()
00075 , beh( new DriverBehaviour() )
00076 , d( new DriverPrivate() )
00077 {
00078 d->connections.setAutoDelete(false);
00079
00080 d->connections.resize(101);
00081 d->typeNames.resize(Field::LastType + 1);
00082
00083 d->initKexiKeywords();
00084 }
00085
00086
00087 Driver::~Driver()
00088 {
00089 DriverManagerInternal::self()->aboutDelete( this );
00090
00091 QPtrDictIterator<Connection> it( d->connections );
00092 Connection *conn;
00093 while ( (conn = it.toFirst()) ) {
00094 delete conn;
00095 }
00096 delete beh;
00097 delete d;
00098
00099 }
00100
00101 bool Driver::isValid()
00102 {
00103 clearError();
00104 if (KexiDB::version().major != version().major
00105 || KexiDB::version().minor != version().minor)
00106 {
00107 setError(ERR_INCOMPAT_DRIVER_VERSION,
00108 i18n("Incompatible database driver's \"%1\" version: found version %2, expected version %3.")
00109 .arg(name())
00110 .arg(QString("%1.%2").arg(version().major).arg(version().minor))
00111 .arg(QString("%1.%2").arg(KexiDB::version().major).arg(KexiDB::version().minor)));
00112 return false;
00113 }
00114
00115 QString inv_impl = i18n("Invalid database driver's \"%1\" implementation:\n").arg(name());
00116 QString not_init = i18n("Value of \"%1\" is not initialized for the driver.");
00117 if (beh->ROW_ID_FIELD_NAME.isEmpty()) {
00118 setError(ERR_INVALID_DRIVER_IMPL, inv_impl + not_init.arg("DriverBehaviour::ROW_ID_FIELD_NAME"));
00119 return false;
00120 }
00121
00122 return true;
00123 }
00124
00125 const QPtrList<Connection> Driver::connectionsList() const
00126 {
00127 QPtrList<Connection> clist;
00128 QPtrDictIterator<Connection> it( d->connections );
00129 for( ; it.current(); ++it )
00130 clist.append( &(*it) );
00131 return clist;
00132 }
00133
00134 QString Driver::fileDBDriverMimeType() const
00135 { return d->fileDBDriverMimeType; }
00136
00137 QString Driver::defaultFileBasedDriverMimeType()
00138 { return QString::fromLatin1("application/x-kexiproject-sqlite3"); }
00139
00140 QString Driver::defaultFileBasedDriverName()
00141 {
00142 DriverManager dm;
00143 return dm.lookupByMime(Driver::defaultFileBasedDriverMimeType()).lower();
00144 }
00145
00146 const KService* Driver::service() const
00147 { return d->service; }
00148
00149 bool Driver::isFileDriver() const
00150 { return d->isFileDriver; }
00151
00152 int Driver::features() const
00153 { return d->features; }
00154
00155 bool Driver::transactionsSupported() const
00156 { return d->features & (SingleTransactions | MultipleTransactions); }
00157
00158 AdminTools& Driver::adminTools() const
00159 {
00160 if (!d->adminTools)
00161 d->adminTools = drv_createAdminTools();
00162 return *d->adminTools;
00163 }
00164
00165 AdminTools* Driver::drv_createAdminTools() const
00166 {
00167 return new AdminTools();
00168 }
00169
00170 QString Driver::sqlTypeName(int id_t, int ) const
00171 {
00172 if (id_t > Field::InvalidType && id_t <= Field::LastType)
00173 return d->typeNames[(id_t>0 && id_t<=Field::LastType) ? id_t : Field::InvalidType ];
00174
00175 return d->typeNames[Field::InvalidType];
00176 }
00177
00178 Connection *Driver::createConnection( ConnectionData &conn_data, int options )
00179 {
00180 clearError();
00181 if (!isValid())
00182 return 0;
00183
00184 if (d->isFileDriver) {
00185 if (conn_data.fileName().isEmpty()) {
00186 setError(ERR_MISSING_DB_LOCATION, i18n("File name expected for file-based database driver.") );
00187 return 0;
00188 }
00189 }
00190
00191 Connection *conn = drv_createConnection( conn_data );
00192
00193 conn->setReadOnly(options & ReadOnlyConnection);
00194
00195 conn_data.driverName = name();
00196 d->connections.insert( conn, conn );
00197 return conn;
00198 }
00199
00200 Connection* Driver::removeConnection( Connection *conn )
00201 {
00202 clearError();
00203 return d->connections.take( conn );
00204 }
00205
00206 QString Driver::defaultSQLTypeName(int id_t)
00207 {
00208 if (id_t>=Field::Null)
00209 return "Null";
00210 if (dflt_typeNames.isEmpty()) {
00211 dflt_typeNames.resize(Field::LastType + 1);
00212 dflt_typeNames[Field::InvalidType]="InvalidType";
00213 dflt_typeNames[Field::Byte]="Byte";
00214 dflt_typeNames[Field::ShortInteger]="ShortInteger";
00215 dflt_typeNames[Field::Integer]="Integer";
00216 dflt_typeNames[Field::BigInteger]="BigInteger";
00217 dflt_typeNames[Field::Boolean]="Boolean";
00218 dflt_typeNames[Field::Date]="Date";
00219 dflt_typeNames[Field::DateTime]="DateTime";
00220 dflt_typeNames[Field::Time]="Time";
00221 dflt_typeNames[Field::Float]="Float";
00222 dflt_typeNames[Field::Double]="Double";
00223 dflt_typeNames[Field::Text]="Text";
00224 dflt_typeNames[Field::LongText]="LongText";
00225 dflt_typeNames[Field::BLOB]="BLOB";
00226 }
00227 return dflt_typeNames[id_t];
00228 }
00229
00230 bool Driver::isSystemObjectName( const QString& n ) const
00231 {
00232 return Driver::isKexiDBSystemObjectName(n);
00233 }
00234
00235 bool Driver::isKexiDBSystemObjectName( const QString& n )
00236 {
00237 if (!n.lower().startsWith("kexi__"))
00238 return false;
00239 const QStringList list( Connection::kexiDBSystemTableNames() );
00240 return list.find(n.lower())!=list.constEnd();
00241 }
00242
00243 bool Driver::isSystemFieldName( const QString& n ) const
00244 {
00245 if (!beh->ROW_ID_FIELD_NAME.isEmpty() && n.lower()==beh->ROW_ID_FIELD_NAME.lower())
00246 return true;
00247 return drv_isSystemFieldName(n);
00248 }
00249
00250 QString Driver::valueToSQL( uint ftype, const QVariant& v ) const
00251 {
00252 if (v.isNull())
00253 return "NULL";
00254 switch (ftype) {
00255 case Field::Text:
00256 case Field::LongText: {
00257 QString s = v.toString();
00258 return escapeString(s);
00259 }
00260 case Field::Byte:
00261 case Field::ShortInteger:
00262 case Field::Integer:
00263 case Field::BigInteger:
00264 return v.toString();
00265 case Field::Float:
00266 case Field::Double: {
00267 if (v.type()==QVariant::String) {
00268
00269 QString s(v.toString());
00270 return s.replace(',', ".");
00271 }
00272 return v.toString();
00273 }
00274
00275 case Field::Boolean:
00276 return QString::number(v.toInt()?1:0);
00277 case Field::Time:
00278 return QString("\'")+v.toTime().toString(Qt::ISODate)+"\'";
00279 case Field::Date:
00280 return QString("\'")+v.toDate().toString(Qt::ISODate)+"\'";
00281 case Field::DateTime:
00282 return dateTimeToSQL( v.toDateTime() );
00283 case Field::BLOB: {
00284 if (v.toByteArray().isEmpty())
00285 return QString::fromLatin1("NULL");
00286 if (v.type()==QVariant::String)
00287 return escapeBLOB(v.toString().utf8());
00288 return escapeBLOB(v.toByteArray());
00289 }
00290 case Field::InvalidType:
00291 return "!INVALIDTYPE!";
00292 default:
00293 KexiDBDbg << "Driver::valueToSQL(): UNKNOWN!" << endl;
00294 return QString::null;
00295 }
00296 return QString::null;
00297 }
00298
00299 QVariant Driver::propertyValue( const QCString& propName ) const
00300 {
00301 return d->properties[propName.lower()];
00302 }
00303
00304 QString Driver::propertyCaption( const QCString& propName ) const
00305 {
00306 return d->propertyCaptions[propName.lower()];
00307 }
00308
00309 QValueList<QCString> Driver::propertyNames() const
00310 {
00311 QValueList<QCString> names = d->properties.keys();
00312 qHeapSort(names);
00313 return names;
00314 }
00315
00316 QString Driver::escapeIdentifier(const QString& str, int options) const
00317 {
00318 QCString cstr = str.latin1();
00319 return QString(escapeIdentifier(cstr, options));
00320 }
00321
00322 QCString Driver::escapeIdentifier(const QCString& str, int options) const
00323 {
00324 bool needOuterQuotes = false;
00325
00326
00327
00328 if(options & EscapeAlways)
00329 needOuterQuotes = true;
00330
00331
00332 else if(!d->driverSQLDict)
00333 needOuterQuotes = true;
00334
00335
00336 else if(d->kexiSQLDict->find(str))
00337 needOuterQuotes = true;
00338
00339
00340
00341 else if((options & EscapeDriver) && d->driverSQLDict->find(str))
00342 needOuterQuotes = true;
00343
00344
00345 else if(str.find(' ') != -1)
00346 needOuterQuotes = true;
00347
00348 if(needOuterQuotes && (options & EscapeKexi)) {
00349 const char quote = '"';
00350 return quote + QCString(str).replace( quote, "\"\"" ) + quote;
00351 }
00352 else if (needOuterQuotes) {
00353 const char quote = beh->QUOTATION_MARKS_FOR_IDENTIFIER.latin1();
00354 return quote + drv_escapeIdentifier(str) + quote;
00355 } else {
00356 return drv_escapeIdentifier(str);
00357 }
00358 }
00359
00360 void Driver::initSQLKeywords(int hashSize) {
00361
00362 if(!d->driverSQLDict && beh->SQL_KEYWORDS != 0) {
00363 d->initDriverKeywords(beh->SQL_KEYWORDS, hashSize);
00364 }
00365 }
00366
00367 #include "driver.moc"
|