File indexing completed on 2024-05-19 08:32:17
0001 /* This file is part of the KDE project 0002 Copyright (C) 2007 Sharan Rao <sharanrao@gmail.com> 0003 0004 This program 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 program 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 program; see the file COPYING. 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 <QByteArray> 0021 #include <QStringList> 0022 #include <QApplication> 0023 #include <QFile> 0024 #include <QTemporaryFile> 0025 0026 #include "SybaseConnection_p.h" 0027 0028 #include "KDbConnectionData.h" 0029 0030 QMap<DBPROCESS*, SybaseConnectionInternal*> SybaseConnectionInternal::dbProcessConnectionMap; 0031 0032 0033 int connectionMessageHandler(DBPROCESS* dbproc, DBINT msgno, int msgstate, int severity, 0034 char* msgtext, char* srvname, char* procname, int line) 0035 { 0036 if (!dbproc) { 0037 return 0; 0038 } 0039 0040 SybaseConnectionInternal* conn = SybaseConnectionInternal::dbProcessConnectionMap[dbproc]; 0041 if (conn) 0042 conn->messageHandler(msgno, msgstate, severity, msgtext, srvname, procname, line); 0043 0044 return (0); 0045 } 0046 0047 SybaseConnectionInternal::SybaseConnectionInternal(KDbConnection* connection) 0048 : ConnectionInternal(connection) 0049 , dbProcess(0) 0050 , res(0) 0051 { 0052 } 0053 0054 SybaseConnectionInternal::~SybaseConnectionInternal() 0055 { 0056 if (sybase_owned && dbProcess) { 0057 dbclose(dbProcess); 0058 dbProcess = 0; 0059 } 0060 } 0061 0062 void SybaseConnectionInternal::storeResult() 0063 { 0064 //sybaseDebug() << "Store Result!!"; 0065 // all message numbers and message texts were handled in the messageHandler 0066 // so don't do anything here 0067 } 0068 0069 void SybaseConnectionInternal::messageHandler(DBINT msgno, int msgstate, int severity, char* msgtext, char* srvname, char* procname, int line) 0070 { 0071 0072 Q_UNUSED(msgstate); 0073 Q_UNUSED(severity); 0074 Q_UNUSED(srvname); 0075 Q_UNUSED(procname); 0076 Q_UNUSED(line); 0077 0078 res = msgno; 0079 errmsg = QString::fromLatin1(msgtext); 0080 //sybaseDebug() << "Message Handler" << res << errmsg; 0081 } 0082 0083 bool SybaseConnectionInternal::db_connect(const KDbConnectionData& data) 0084 { 0085 if (dbinit() == FAIL) 0086 return false; 0087 0088 // set message handler 0089 dbmsghandle(connectionMessageHandler); 0090 0091 QByteArray localSocket; 0092 QString hostName = data.hostName; 0093 0094 0095 if (data.serverName.isEmpty()) { 0096 sybaseWarning() << "Can't connect without server name"; 0097 return false; 0098 } 0099 0100 0101 // set Error.handlers 0102 // set message handlers 0103 0104 LOGINREC* login; 0105 0106 login = dblogin(); 0107 if (!login) { 0108 //dbexit(); 0109 return false; 0110 } 0111 0112 // umm, copied from pqxx driver. 0113 if (hostName.isEmpty() || 0 == hostName.compare(QLatin1String("localhost"), Qt::CaseInsensitive)) { 0114 if (data.useLocalSocketFile) { 0115 if (data.localSocketFileName.isEmpty()) { 0116 QStringList sockets; 0117 #ifndef Q_OS_WIN 0118 sockets.append("/tmp/s.sybase.2638"); 0119 0120 foreach(const QString& socket, sockets) { 0121 if (QFile(socket).exists()) { 0122 localSocket = socket.toLatin1(); 0123 break; 0124 } 0125 } 0126 #endif 0127 } else 0128 localSocket = QFile::encodeName(data.localSocketFileName); 0129 } else { 0130 //we're not using local socket 0131 hostName = "127.0.0.1"; 0132 } 0133 } 0134 0135 QTemporaryFile confFile(QDir::tempPath() + QLatin1String("/kdb_sybase_XXXXXX.conf")); 0136 confFile.open(); 0137 0138 QTextStream out(&confFile); 0139 0140 // write global portion 0141 out << "[global]" << "\n"; 0142 out << " text size = " << 64512 << "\n" ; // Copied from default freetds.conf. is there a more reasonable number? 0143 0144 0145 // write server portion 0146 out << '[' << data.serverName << ']' << "\n"; 0147 out << " host = " << hostName << "\n"; 0148 0149 if (data.port == 0) 0150 out << " port = " << 5000 << "\n"; // default port to be used 0151 else 0152 out << " port = " << data.port << "\n"; 0153 0154 out << " tds version = " << 5.0 << "\n"; 0155 0156 // set the file to be read as confFile 0157 dbsetifile(confFile.fileName().toLatin1().data()); 0158 0159 // set Login parameters 0160 QByteArray pwd(data.password.isNull() ? QByteArray() : data.password.toLatin1()); 0161 0162 DBSETLUSER(login, data.userName.toLatin1()); 0163 DBSETLPWD(login, pwd); 0164 DBSETLAPP(login, qApp->applicationName().toLatin1()); 0165 0166 // make the connection 0167 // Host name assumed to be same as servername 0168 // where are ports specified ? ( in the interfaces file ? ) 0169 0170 dbProcess = dbopen(login, data.serverName.toLatin1().data()); 0171 0172 dbloginfree(login); 0173 0174 // Set/ Unset quoted identifier ? ? 0175 0176 if (dbProcess) { 0177 // add to map 0178 SybaseConnectionInternal::dbProcessConnectionMap[dbProcess] = this; 0179 0180 // set buffering to be true 0181 // what's a reasonable value of no. of rows to be kept in buffer ? 0182 // dbsetopt( dbProcess, DBBUFFER, "500", -1 ); 0183 0184 // set quoted identifier to be true 0185 dbsetopt(dbProcess, DBQUOTEDIDENT, "1", -1); 0186 0187 return true; 0188 } 0189 0190 storeResult(); 0191 0192 //dbexit(); 0193 // setError(ERR_DB_SPECIFIC,err); 0194 return false; 0195 } 0196 0197 bool SybaseConnectionInternal::db_disconnect() 0198 { 0199 dbclose(dbProcess); 0200 dbProcess = 0; 0201 return true; 0202 } 0203 0204 bool SybaseConnectionInternal::useDatabase(const QString &dbName) 0205 { 0206 if (dbuse(dbProcess, dbName.toLatin1().data()) == SUCCEED) { 0207 return true; 0208 } 0209 0210 return false; 0211 } 0212 0213 bool SybaseConnectionInternal::executeSql(const KDbEscapedString& sql) 0214 { 0215 // remove queries in buffer if any. flush existing results if any 0216 dbcancel(dbProcess); 0217 // put query in command bufffer 0218 dbcmd(dbProcess, sql.constData()); 0219 if (dbsqlexec(dbProcess) == SUCCEED) { 0220 while (dbresults(dbProcess) != NO_MORE_RESULTS) { 0221 /* nop */ 0222 } 0223 return true; 0224 } 0225 0226 // Error.handling 0227 0228 storeResult(); 0229 return false; 0230 } 0231 0232 QString SybaseConnectionInternal::escapeIdentifier(const QString& str) const 0233 { 0234 return QString(str).replace("'", "''"); 0235 } 0236 0237 //-------------------------------------- 0238 0239 SybaseCursorData::SybaseCursorData(KDbConnection* connection) 0240 : SybaseConnectionInternal(connection) 0241 , numRows(0) 0242 { 0243 sybase_owned = false; 0244 } 0245 0246 SybaseCursorData::~SybaseCursorData() 0247 { 0248 }