kexi

mysqldriver.cpp

00001 /* This file is part of the KDE project
00002 Copyright (C) 2002   Lucijan Busch <lucijan@gmx.at>
00003 Daniel Molkentin <molkentin@kde.org>
00004 Copyright (C) 2003   Joseph Wenninger<jowenn@kde.org>
00005 
00006 This program is free software; you can redistribute it and/or
00007 modify it under the terms of the GNU Library General Public
00008 License as published by the Free Software Foundation; either
00009 version 2 of the License, or (at your option) any later version.
00010 
00011 This program is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 Library General Public License for more details.
00015 
00016 You should have received a copy of the GNU Library General Public License
00017 along with this program; see the file COPYING.  If not, write to
00018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020 */
00021 
00022 #ifdef Q_WS_WIN
00023 # include <mysql/config-win.h>
00024 #endif
00025 #include <mysql_version.h>
00026 #include <mysql.h>
00027 #define BOOL bool
00028 
00029 #include <qvariant.h>
00030 #include <qfile.h>
00031 #include <qdict.h>
00032 
00033 #include <kgenericfactory.h>
00034 #include <kdebug.h>
00035 
00036 #include "mysqldriver.h"
00037 #include "mysqlconnection.h"
00038 #include <kexidb/field.h>
00039 #include <kexidb/driver_p.h>
00040 #include <kexidb/utils.h>
00041 
00042 using namespace KexiDB;
00043 
00044 KEXIDB_DRIVER_INFO( MySqlDriver, mysql )
00045 
00046 /* TODO: Implement buffered/unbuffered, rather than buffer everything.
00047    Each MYSQL connection can only handle at most one unbuffered cursor,
00048    so MySqlConnection should keep count?
00049  */
00050 
00051 
00057 MySqlDriver::MySqlDriver(QObject *parent, const char *name, const QStringList &args) : Driver(parent, name,args)
00058 {
00059 //  KexiDBDrvDbg << "MySqlDriver::MySqlDriver()" << endl;
00060 
00061     d->isFileDriver=false;
00062     d->features=IgnoreTransactions | CursorForward;
00063 
00064     beh->ROW_ID_FIELD_NAME="LAST_INSERT_ID()";
00065     beh->ROW_ID_FIELD_RETURNS_LAST_AUTOINCREMENTED_VALUE=true;
00066     beh->_1ST_ROW_READ_AHEAD_REQUIRED_TO_KNOW_IF_THE_RESULT_IS_EMPTY=false;
00067     beh->USING_DATABASE_REQUIRED_TO_CONNECT=false;
00068     beh->QUOTATION_MARKS_FOR_IDENTIFIER='`';
00069     beh->SQL_KEYWORDS = keywords;
00070     initSQLKeywords(331);
00071     
00072     //predefined properties
00073 #if MYSQL_VERSION_ID < 40000
00074     d->properties["client_library_version"] = MYSQL_SERVER_VERSION; //nothing better
00075     d->properties["default_server_encoding"] = MYSQL_CHARSET; //nothing better
00076 #elif MYSQL_VERSION_ID < 50000
00077 //OK?   d->properties["client_library_version"] = mysql_get_client_version();
00078 #endif
00079 
00080     d->typeNames[Field::Byte]="TINYINT";
00081     d->typeNames[Field::ShortInteger]="SMALLINT";
00082     d->typeNames[Field::Integer]="INT";
00083     d->typeNames[Field::BigInteger]="BIGINT";
00084     // Can use BOOLEAN here, but BOOL has been in MySQL longer
00085     d->typeNames[Field::Boolean]="BOOL";
00086     d->typeNames[Field::Date]="DATE";
00087     d->typeNames[Field::DateTime]="DATETIME";
00088     d->typeNames[Field::Time]="TIME";
00089     d->typeNames[Field::Float]="FLOAT";
00090     d->typeNames[Field::Double]="DOUBLE";
00091     d->typeNames[Field::Text]="VARCHAR";
00092     d->typeNames[Field::LongText]="LONGTEXT";
00093     d->typeNames[Field::BLOB]="BLOB";
00094 }
00095 
00096 MySqlDriver::~MySqlDriver()
00097 {
00098 }
00099 
00100 KexiDB::Connection*
00101 MySqlDriver::drv_createConnection( ConnectionData &conn_data )
00102 {
00103     return new MySqlConnection( this, conn_data );
00104 }
00105 
00106 bool MySqlDriver::isSystemDatabaseName(const QString &n) const
00107 {
00108     return n.lower()=="mysql" || Driver::isSystemObjectName(n);
00109 }
00110 
00111 bool MySqlDriver::drv_isSystemFieldName(const QString&) const {
00112     return false;
00113 }
00114 
00115 QString MySqlDriver::escapeString(const QString& str) const
00116 {
00117     //escape as in http://dev.mysql.com/doc/refman/5.0/en/string-syntax.html
00119 
00120     const int old_length = str.length();
00121     int i;
00122     for ( i = 0; i < old_length; i++ ) { //anything to escape?
00123         const unsigned int ch = str[i].unicode();
00124         if (ch == '\\' || ch == '\'' || ch == '"' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '\b' || ch == '\0')
00125             break;
00126     }
00127     if (i >= old_length) { //no characters to escape
00128         return QString::fromLatin1("'") + str + QString::fromLatin1("'");
00129     }
00130 
00131     QChar *new_string = new QChar[ old_length * 3 + 1 ]; // a worst case approximation
00133     int new_length = 0;
00134     new_string[new_length++] = '\''; //prepend '
00135     for ( i = 0; i < old_length; i++, new_length++ ) {
00136         const unsigned int ch = str[i].unicode();
00137         if (ch == '\\') {
00138             new_string[new_length++] = '\\';
00139             new_string[new_length] = '\\';
00140         }
00141         else if (ch <= '\'') {//check for speedup
00142             if (ch == '\'') {
00143                 new_string[new_length++] = '\\';
00144                 new_string[new_length] = '\'';
00145             }
00146             else if (ch == '"') {
00147                 new_string[new_length++] = '\\';
00148                 new_string[new_length] = '"';
00149             }
00150             else if (ch == '\n') {
00151                 new_string[new_length++] = '\\';
00152                 new_string[new_length] = 'n';
00153             }
00154             else if (ch == '\r') {
00155                 new_string[new_length++] = '\\';
00156                 new_string[new_length] = 'r';
00157             }
00158             else if (ch == '\t') {
00159                 new_string[new_length++] = '\\';
00160                 new_string[new_length] = 't';
00161             }
00162             else if (ch == '\b') {
00163                 new_string[new_length++] = '\\';
00164                 new_string[new_length] = 'b';
00165             }
00166             else if (ch == '\0') {
00167                 new_string[new_length++] = '\\';
00168                 new_string[new_length] = '0';
00169             }
00170             else
00171                 new_string[new_length] = str[i];
00172         }
00173         else
00174             new_string[new_length] = str[i];
00175     }
00176 
00177     new_string[new_length++] = '\''; //append '
00178     QString result(new_string, new_length);
00179     delete [] new_string;
00180     return result;
00181 }
00182 
00183 QString MySqlDriver::escapeBLOB(const QByteArray& array) const
00184 {
00185     return KexiDB::escapeBLOB(array, KexiDB::BLOBEscape0xHex);
00186 }
00187 
00188 QCString MySqlDriver::escapeString(const QCString& str) const
00189 {
00192 
00193     return QCString("'")+QCString(str)
00194         .replace( '\\', "\\\\" )
00195         .replace( '\'', "\\''" )
00196         .replace( '"', "\\\"" )
00197         + QCString("'");
00198 }
00199 
00203 QString MySqlDriver::drv_escapeIdentifier( const QString& str) const {
00204     return QString(str).replace('`', "'");
00205 }
00206 
00207 QCString MySqlDriver::drv_escapeIdentifier( const QCString& str) const {
00208     return QCString(str).replace('`', "'");
00209 }
00210 
00211 #include "mysqldriver.moc"
00212 
KDE Home | KDE Accessibility Home | Description of Access Keys